Skip to content

Commit 9e8483d

Browse files
committed
[YouTube] implement support retrieving SABR URL and player config
1 parent 455cf8e commit 9e8483d

4 files changed

Lines changed: 74 additions & 2 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public static JsonObject getWebMetadataPlayerResponse(
7272
.getBytes(StandardCharsets.UTF_8);
7373

7474
final String url = YOUTUBEI_V1_URL + PLAYER + "?" + DISABLE_PRETTY_PRINT_PARAMETER
75-
+ "&$fields=microformat,playabilityStatus,storyboards,videoDetails";
75+
+ "&$fields=microformat,playabilityStatus,storyboards,videoDetails,playerConfig";
7676

7777
return JsonUtils.toJsonObject(getValidJsonResponseBody(
7878
getDownloader().postWithContentTypeJson(

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
109109
private static PoTokenProvider poTokenProvider;
110110
private static boolean fetchIosClient;
111111

112+
private JsonObject androidPlayerResponse;
112113
private JsonObject playerResponse;
113114
private JsonObject nextResponse;
114115

@@ -700,6 +701,29 @@ public List<VideoStream> getVideoOnlyStreams() throws ExtractionException {
700701
getVideoStreamBuilderHelper(true), "video-only");
701702
}
702703

704+
@Override
705+
public String getServerAbrStreamingUrl() {
706+
assertPageFetched();
707+
return java.util.stream.Stream.of(
708+
html5StreamingData,
709+
androidStreamingData,
710+
iosStreamingData)
711+
.filter(Objects::nonNull)
712+
.map(streamingData -> streamingData.getString(SERVER_ABR_STREAMING_URL))
713+
.findFirst()
714+
.get();
715+
}
716+
717+
@Override
718+
public String getUstreamerConfig() {
719+
assertPageFetched();
720+
return androidPlayerResponse
721+
.getObject("playerConfig")
722+
.getObject("mediaCommonConfig")
723+
.getObject("mediaUstreamerRequestConfig")
724+
.getString("videoPlaybackUstreamerConfig");
725+
}
726+
703727
@Override
704728
@Nonnull
705729
public List<SubtitlesStream> getSubtitlesDefault() throws ParsingException {
@@ -835,6 +859,7 @@ public String getErrorMessage() {
835859

836860
private static final String FORMATS = "formats";
837861
private static final String ADAPTIVE_FORMATS = "adaptiveFormats";
862+
private static final String SERVER_ABR_STREAMING_URL = "serverAbrStreamingUrl";
838863
private static final String STREAMING_DATA = "streamingData";
839864
private static final String NEXT = "next";
840865
private static final String SIGNATURE_CIPHER = "signatureCipher";
@@ -1031,7 +1056,6 @@ private void fetchAndroidClient(@Nonnull final Localization localization,
10311056
try {
10321057
androidCpn = generateContentPlaybackNonce();
10331058

1034-
final JsonObject androidPlayerResponse;
10351059
if (androidPoTokenResult == null) {
10361060
androidPlayerResponse = YoutubeStreamHelper.getAndroidReelPlayerResponse(
10371061
contentCountry, localization, videoId, androidCpn);

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,26 @@ public ContentAvailability getContentAvailability() throws ParsingException {
593593
return ContentAvailability.UNKNOWN;
594594
}
595595

596+
/**
597+
* The URL for server adaptive bitrate streaming.
598+
*
599+
* @return The stream's SABR URL.
600+
* @throws ParsingException if there is an error in the extraction
601+
*/
602+
public String getServerAbrStreamingUrl() throws ParsingException {
603+
return null;
604+
}
605+
606+
/**
607+
* The ustreamerConfig for server adaptive bitrate streaming.
608+
*
609+
* @return The stream's ustreamerConfig.
610+
* @throws ParsingException if there is an error in the extraction
611+
*/
612+
public String getUstreamerConfig() throws ParsingException {
613+
return null;
614+
}
615+
596616
public enum Privacy {
597617
PUBLIC,
598618
UNLISTED,

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,16 @@ private static void extractOptionalData(final StreamInfo streamInfo,
335335
} catch (final Exception e) {
336336
streamInfo.addError(e);
337337
}
338+
try {
339+
streamInfo.setServerAbrStreamingUrl(extractor.getServerAbrStreamingUrl());
340+
} catch (final Exception e) {
341+
streamInfo.addError(e);
342+
}
343+
try {
344+
streamInfo.setUstreamerConfig(extractor.getUstreamerConfig());
345+
} catch (final Exception e) {
346+
streamInfo.addError(e);
347+
}
338348

339349
streamInfo.setRelatedItems(ExtractorHelper.getRelatedItemsOrLogError(streamInfo,
340350
extractor));
@@ -388,6 +398,8 @@ private static void extractOptionalData(final StreamInfo streamInfo,
388398
private boolean shortFormContent = false;
389399
@Nonnull
390400
private ContentAvailability contentAvailability = ContentAvailability.AVAILABLE;
401+
private String serverAbrStreamingUrl = "";
402+
private String ustreamerConfig = "";
391403

392404
/**
393405
* Preview frames, e.g. for the storyboard / seekbar thumbnail preview
@@ -743,4 +755,20 @@ public ContentAvailability getContentAvailability() {
743755
public void setContentAvailability(@Nonnull final ContentAvailability availability) {
744756
this.contentAvailability = availability;
745757
}
758+
759+
public String getServerAbrStreamingUrl() {
760+
return serverAbrStreamingUrl;
761+
}
762+
763+
public void setServerAbrStreamingUrl(final String serverAbrStreamingUrl) {
764+
this.serverAbrStreamingUrl = serverAbrStreamingUrl;
765+
}
766+
767+
public String getUstreamerConfig() {
768+
return ustreamerConfig;
769+
}
770+
771+
public void setUstreamerConfig(final String ustreamerConfig) {
772+
this.ustreamerConfig = ustreamerConfig;
773+
}
746774
}

0 commit comments

Comments
 (0)