diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java index e01f0cfb9..302fb3ef9 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java @@ -1,7 +1,28 @@ +/* + * Created by Christian Schabesberger on 12.02.17. + * + * Copyright (C) Christian Schabesberger 2017 + * YoutubeChannelInfoItemExtractor.java is part of NewPipe Extractor. + * + * NewPipe Extractor is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NewPipe Extractor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NewPipe Extractor. If not, see . + */ + package org.schabi.newpipe.extractor.services.youtube.extractors; import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; @@ -9,28 +30,11 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.Utils; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.fixThumbnailUrl; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; +import javax.annotation.Nonnull; +import java.util.List; -/* - * Created by Christian Schabesberger on 12.02.17. - * - * Copyright (C) Christian Schabesberger 2017 - * YoutubeChannelInfoItemExtractor.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailsFromInfoItem; public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor { private final JsonObject channelInfoItem; @@ -53,15 +57,13 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor this.withHandle = wHandle; } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { + public List getThumbnails() throws ParsingException { try { - final String url = channelInfoItem.getObject("thumbnail").getArray("thumbnails") - .getObject(0).getString("url"); - - return fixThumbnailUrl(url); + return getThumbnailsFromInfoItem(channelInfoItem); } catch (final Exception e) { - throw new ParsingException("Could not get thumbnail url", e); + throw new ParsingException("Could not get thumbnails", e); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java index 95209a65f..fb6463a54 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java @@ -1,7 +1,8 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; -import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; @@ -11,9 +12,12 @@ import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.Utils; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import static org.schabi.newpipe.extractor.comments.CommentsInfoItem.UNKNOWN_REPLY_COUNT; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtractor { @@ -42,20 +46,25 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract return commentRenderer; } + @Nonnull + private List getAuthorThumbnails() throws ParsingException { + try { + return getImagesFromThumbnailsArray(JsonUtils.getArray(getCommentRenderer(), + "authorThumbnail.thumbnails")); + } catch (final Exception e) { + throw new ParsingException("Could not get author thumbnails", e); + } + } + @Override public String getUrl() throws ParsingException { return url; } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { - try { - final JsonArray arr = JsonUtils.getArray(getCommentRenderer(), - "authorThumbnail.thumbnails"); - return JsonUtils.getString(arr.getObject(2), "url"); - } catch (final Exception e) { - throw new ParsingException("Could not get thumbnail url", e); - } + public List getThumbnails() throws ParsingException { + return getAuthorThumbnails(); } @Override @@ -204,15 +213,10 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract } } + @Nonnull @Override - public String getUploaderAvatarUrl() throws ParsingException { - try { - final JsonArray arr = JsonUtils.getArray(getCommentRenderer(), - "authorThumbnail.thumbnails"); - return JsonUtils.getString(arr.getObject(2), "url"); - } catch (final Exception e) { - throw new ParsingException("Could not get author thumbnail", e); - } + public List getUploaderAvatars() throws ParsingException { + return getAuthorThumbnails(); } @Override @@ -228,6 +232,7 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract return getCommentRenderer().has("pinnedCommentBadge"); } + @Override public boolean isUploaderVerified() throws ParsingException { return getCommentRenderer().has("authorCommentBadge"); } @@ -261,7 +266,7 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract } @Override - public Page getReplies() throws ParsingException { + public Page getReplies() { try { final String id = JsonUtils.getString( JsonUtils.getArray(json, "replies.commentRepliesRenderer.contents") diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java index d5a83d3b7..d917eb2d7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java @@ -1,14 +1,18 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import org.jsoup.nodes.Element; +import org.schabi.newpipe.extractor.Image; +import org.schabi.newpipe.extractor.Image.ResolutionLevel; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.time.OffsetDateTime; import java.time.format.DateTimeParseException; +import java.util.List; public class YoutubeFeedInfoItemExtractor implements StreamInfoItemExtractor { private final Element entryElement; @@ -51,12 +55,6 @@ public class YoutubeFeedInfoItemExtractor implements StreamInfoItemExtractor { return entryElement.select("author > uri").first().text(); } - @Nullable - @Override - public String getUploaderAvatarUrl() throws ParsingException { - return null; - } - @Override public boolean isUploaderVerified() throws ParsingException { return false; @@ -89,12 +87,51 @@ public class YoutubeFeedInfoItemExtractor implements StreamInfoItemExtractor { return entryElement.getElementsByTag("link").first().attr("href"); } + @Nonnull @Override - public String getThumbnailUrl() { + public List getThumbnails() { + final Element thumbnailElement = entryElement.getElementsByTag("media:thumbnail").first(); + if (thumbnailElement == null) { + return List.of(); + } + + final String feedThumbnailUrl = thumbnailElement.attr("url"); + + // If the thumbnail URL is empty, it means that no thumbnail is available, return an empty + // list in this case + if (feedThumbnailUrl.isEmpty()) { + return List.of(); + } + // The hqdefault thumbnail has some black bars at the top and at the bottom, while the // mqdefault doesn't, so return the mqdefault one. It should always exist, according to // https://stackoverflow.com/a/20542029/9481500. - return entryElement.getElementsByTag("media:thumbnail").first().attr("url") - .replace("hqdefault", "mqdefault"); + final String newFeedThumbnailUrl = feedThumbnailUrl.replace("hqdefault", "mqdefault"); + + int height; + int width; + + // If the new thumbnail URL is equal to the feed one, it means that a different image + // resolution is used on feeds, so use the height and width provided instead of the + // mqdefault ones + if (newFeedThumbnailUrl.equals(feedThumbnailUrl)) { + try { + height = Integer.parseInt(thumbnailElement.attr("height")); + } catch (final NumberFormatException e) { + height = Image.HEIGHT_UNKNOWN; + } + + try { + width = Integer.parseInt(thumbnailElement.attr("width")); + } catch (final NumberFormatException e) { + width = Image.WIDTH_UNKNOWN; + } + } else { + height = 320; + width = 180; + } + + return List.of( + new Image(newFeedThumbnailUrl, height, width, ResolutionLevel.fromHeight(height))); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMixOrPlaylistInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMixOrPlaylistInfoItemExtractor.java index 4847302e6..16c7a3e3e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMixOrPlaylistInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMixOrPlaylistInfoItemExtractor.java @@ -2,11 +2,12 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractPlaylistTypeFromPlaylistUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailUrlFromInfoItem; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailsFromInfoItem; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; @@ -14,6 +15,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper; import javax.annotation.Nonnull; +import java.util.List; public class YoutubeMixOrPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor { private final JsonObject mixInfoItem; @@ -40,9 +42,10 @@ public class YoutubeMixOrPlaylistInfoItemExtractor implements PlaylistInfoItemEx return url; } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { - return getThumbnailUrlFromInfoItem(mixInfoItem); + public List getThumbnails() throws ParsingException { + return getThumbnailsFromInfoItem(mixInfoItem); } @Override @@ -75,7 +78,7 @@ public class YoutubeMixOrPlaylistInfoItemExtractor implements PlaylistInfoItemEx return Integer.parseInt(countString); } catch (final NumberFormatException ignored) { // un-parsable integer: this is a mix with infinite items and "50+" as count string - // (though youtube music mixes do not necessarily have an infinite count of songs) + // (though YouTube Music mixes do not necessarily have an infinite count of songs) return ListExtractor.ITEM_COUNT_INFINITE; } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistInfoItemExtractor.java index c3a7707dc..a0584a20f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistInfoItemExtractor.java @@ -2,17 +2,21 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.Utils; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.fixThumbnailUrl; +import javax.annotation.Nonnull; +import java.util.List; + +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromObject; - public class YoutubePlaylistInfoItemExtractor implements PlaylistInfoItemExtractor { private final JsonObject playlistInfoItem; @@ -20,8 +24,9 @@ public class YoutubePlaylistInfoItemExtractor implements PlaylistInfoItemExtract this.playlistInfoItem = playlistInfoItem; } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { + public List getThumbnails() throws ParsingException { try { JsonArray thumbnails = playlistInfoItem.getArray("thumbnails") .getObject(0) @@ -31,9 +36,9 @@ public class YoutubePlaylistInfoItemExtractor implements PlaylistInfoItemExtract .getArray("thumbnails"); } - return fixThumbnailUrl(thumbnails.getObject(0).getString("url")); + return getImagesFromThumbnailsArray(thumbnails); } catch (final Exception e) { - throw new ParsingException("Could not get thumbnail url", e); + throw new ParsingException("Could not get thumbnails", e); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java index 1b68c2ddf..911cb4bed 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java @@ -1,6 +1,8 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.localization.TimeAgoParser; @@ -13,9 +15,11 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailUrlFromInfoItem; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailsFromInfoItem; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import java.util.List; + /** * A {@link StreamInfoItemExtractor} for YouTube's {@code reelItemRenderers}. * @@ -53,9 +57,10 @@ public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor { } } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { - return getThumbnailUrlFromInfoItem(reelInfo); + public List getThumbnails() throws ParsingException { + return getThumbnailsFromInfoItem(reelInfo); } @Override @@ -101,7 +106,7 @@ public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor { } @Override - public boolean isShortFormContent() throws ParsingException { + public boolean isShortFormContent() { return true; } @@ -122,12 +127,6 @@ public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor { return null; } - @Nullable - @Override - public String getUploaderAvatarUrl() throws ParsingException { - return null; - } - @Override public boolean isUploaderVerified() throws ParsingException { return false; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 1607e0a0f..178cc2bf6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -1,7 +1,33 @@ +/* + * Copyright (C) Christian Schabesberger 2016 + * YoutubeStreamInfoItemExtractor.java is part of NewPipe Extractor. + * + * NewPipe Extractor is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NewPipe Extractor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NewPipe Extractor. If not, see . + */ + package org.schabi.newpipe.extractor.services.youtube.extractors; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailsFromInfoItem; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromNavigationEndpoint; +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; + import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; + +import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.localization.TimeAgoParser; @@ -15,35 +41,14 @@ import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; + import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; +import java.util.List; import java.util.regex.Pattern; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailUrlFromInfoItem; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromNavigationEndpoint; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; - -/* - * Copyright (C) Christian Schabesberger 2016 - * YoutubeStreamInfoItemExtractor.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { private static final Pattern ACCESSIBILITY_DATA_VIEW_COUNT_REGEX = @@ -215,21 +220,22 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { return url; } - @Nullable + @Nonnull @Override - public String getUploaderAvatarUrl() throws ParsingException { + public List getUploaderAvatars() throws ParsingException { if (videoInfo.has("channelThumbnailSupportedRenderers")) { - return JsonUtils.getArray(videoInfo, "channelThumbnailSupportedRenderers" - + ".channelThumbnailWithLinkRenderer.thumbnail.thumbnails") - .getObject(0).getString("url"); + return getImagesFromThumbnailsArray(JsonUtils.getArray(videoInfo, + // CHECKSTYLE:OFF + "channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails")); + // CHECKSTYLE:ON } if (videoInfo.has("channelThumbnail")) { - return JsonUtils.getArray(videoInfo, "channelThumbnail.thumbnails") - .getObject(0).getString("url"); + return getImagesFromThumbnailsArray( + JsonUtils.getArray(videoInfo, "channelThumbnail.thumbnails")); } - return null; + return List.of(); } @Override @@ -371,9 +377,10 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { videoInfoTitleAccessibilityData))); } + @Nonnull @Override - public String getThumbnailUrl() throws ParsingException { - return getThumbnailUrlFromInfoItem(videoInfo); + public List getThumbnails() throws ParsingException { + return getThumbnailsFromInfoItem(videoInfo); } private boolean isPremium() { @@ -409,10 +416,10 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { @Nullable @Override public String getShortDescription() throws ParsingException { - if (videoInfo.has("detailedMetadataSnippets")) { return getTextFromObject(videoInfo.getArray("detailedMetadataSnippets") - .getObject(0).getObject("snippetText")); + .getObject(0) + .getObject("snippetText")); } if (videoInfo.has("descriptionSnippet")) {