4242import java .time .format .DateTimeFormatter ;
4343import java .util .*;
4444
45- import static org .schabi .newpipe .extractor .services .youtube .YoutubeDashManifestCreator .createDashManifestFromOtfStreamingUrl ;
4645import static org .schabi .newpipe .extractor .services .youtube .YoutubeDashManifestCreator .createDashManifestFromPostLiveStreamDvrStreamingUrl ;
4746import static org .schabi .newpipe .extractor .services .youtube .YoutubeParsingHelper .*;
4847import static org .schabi .newpipe .extractor .utils .Utils .EMPTY_STRING ;
@@ -80,7 +79,7 @@ public static class DeobfuscateException extends ParsingException {
8079 }
8180 }
8281
83- /*////////////////////////////////////////////////////////////////////////// */
82+ /*////////////////////////////////////////////////////////////////////////*/
8483
8584 @ Nullable
8685 private static String cachedDeobfuscationCode = null ;
@@ -91,6 +90,7 @@ public static class DeobfuscateException extends ParsingException {
9190
9291 private JsonObject playerResponse ;
9392 private JsonObject nextResponse ;
93+ private StreamType streamType ;
9494
9595 @ Nullable
9696 private JsonObject desktopStreamingData ;
@@ -689,13 +689,7 @@ public List<SubtitlesStream> getSubtitles(final MediaFormat format) throws Parsi
689689 public StreamType getStreamType () {
690690 assertPageFetched ();
691691
692- if (playerResponse .getObject ("playabilityStatus" ).has ("liveStreamability" )) {
693- return StreamType .LIVE_STREAM ;
694- } else if (playerResponse .getObject ("videoDetails" ).getBoolean ("isPostLiveDvr" , false )) {
695- return StreamType .POST_LIVE_STREAM ;
696- } else {
697- return StreamType .VIDEO_STREAM ;
698- }
692+ return streamType ;
699693 }
700694
701695 @ Nullable
@@ -792,18 +786,39 @@ public void onFetchPage(@Nonnull final Downloader downloader)
792786
793787 final JsonObject playabilityStatus = playerResponse .getObject ("playabilityStatus" );
794788
795- boolean ageRestricted = playabilityStatus .getString ("reason" , EMPTY_STRING )
789+ final boolean isAgeRestricted = playabilityStatus .getString ("reason" , EMPTY_STRING )
796790 .contains ("age" );
797791
798792 if (!playerResponse .has ("streamingData" )) {
799793 try {
800794 fetchDesktopEmbedJsonPlayer (contentCountry , localization , videoId );
801795 } catch (final Exception ignored ) {
802796 }
797+
798+ if (playerResponse .getObject ("playabilityStatus" ).has ("liveStreamability" )) {
799+ streamType = StreamType .LIVE_STREAM ;
800+ } else if (playerResponse .getObject ("videoDetails" ).getBoolean ("isPostLiveDvr" ,
801+ false )) {
802+ streamType = StreamType .POST_LIVE_STREAM ;
803+ } else {
804+ streamType = StreamType .VIDEO_STREAM ;
805+ }
806+
803807 try {
804- fetchAndroidEmbedJsonPlayer (contentCountry , localization , videoId );
808+ if (streamType == StreamType .VIDEO_STREAM || desktopStreamingData == null ) {
809+ fetchAndroidEmbedJsonPlayer (contentCountry , localization , videoId );
810+ }
805811 } catch (final Exception ignored ) {
806812 }
813+ } else {
814+ if (playerResponse .getObject ("playabilityStatus" ).has ("liveStreamability" )) {
815+ streamType = StreamType .LIVE_STREAM ;
816+ } else if (playerResponse .getObject ("videoDetails" ).getBoolean ("isPostLiveDvr" ,
817+ false )) {
818+ streamType = StreamType .POST_LIVE_STREAM ;
819+ } else {
820+ streamType = StreamType .VIDEO_STREAM ;
821+ }
807822 }
808823
809824 if (desktopStreamingData == null && playerResponse .has ("streamingData" )) {
@@ -814,7 +829,7 @@ public void onFetchPage(@Nonnull final Downloader downloader)
814829 checkPlayabilityStatus (youtubePlayerResponse , playabilityStatus );
815830 }
816831
817- if (ageRestricted ) {
832+ if (isAgeRestricted ) {
818833 final byte [] ageRestrictedBody = JsonWriter .string (prepareDesktopEmbedVideoJsonBuilder (
819834 localization , contentCountry , videoId )
820835 .done ())
@@ -824,14 +839,15 @@ public void onFetchPage(@Nonnull final Downloader downloader)
824839 nextResponse = getJsonPostResponse ("next" , body , localization );
825840 }
826841
827- if (!ageRestricted ) {
842+ if (!isAgeRestricted && (streamType == StreamType .VIDEO_STREAM
843+ || desktopStreamingData == null )) {
828844 try {
829845 fetchAndroidMobileJsonPlayer (contentCountry , localization , videoId );
830846 } catch (final Exception ignored ) {
831847 }
832848 }
833849
834- if (isCipherProtectedContent ()) {
850+ if (! isAgeRestricted && isCipherProtectedContent () && sts == null ) {
835851 fetchDesktopJsonPlayerWithSts (contentCountry , localization , videoId );
836852 }
837853 }
@@ -860,28 +876,24 @@ private void checkPlayabilityStatus(final JsonObject youtubePlayerResponse,
860876 "This age-restricted video cannot be watched." );
861877 }
862878 }
863- if (status .equalsIgnoreCase ("unplayable" )) {
864- if (reason != null ) {
865- if (reason .contains ("Music Premium" )) {
866- throw new YoutubeMusicPremiumContentException ();
867- }
868- if (reason .contains ("payment" )) {
869- throw new PaidContentException ("This video is a paid video" );
870- }
871- if (reason .contains ("members-only" )) {
872- throw new PaidContentException (
873- "This video is only available for members of the channel of this video" );
874- }
875- if (reason .contains ("unavailable" )) {
876- final String detailedErrorMessage = getTextFromObject (playabilityStatus
877- .getObject ("errorScreen" ).getObject ("playerErrorMessageRenderer" )
878- .getObject ("subreason" ));
879- if (detailedErrorMessage != null ) {
880- if (detailedErrorMessage .contains ("country" )) {
881- throw new GeographicRestrictionException (
882- "This video is not available in user's country." );
883- }
884- }
879+ if (status .equalsIgnoreCase ("unplayable" ) && reason != null ) {
880+ if (reason .contains ("Music Premium" )) {
881+ throw new YoutubeMusicPremiumContentException ();
882+ }
883+ if (reason .contains ("payment" )) {
884+ throw new PaidContentException ("This video is a paid video" );
885+ }
886+ if (reason .contains ("members-only" )) {
887+ throw new PaidContentException (
888+ "This video is only available for members of the channel of this video" );
889+ }
890+ if (reason .contains ("unavailable" )) {
891+ final String detailedErrorMessage = getTextFromObject (playabilityStatus
892+ .getObject ("errorScreen" ).getObject ("playerErrorMessageRenderer" )
893+ .getObject ("subreason" ));
894+ if (detailedErrorMessage != null && detailedErrorMessage .contains ("country" )) {
895+ throw new GeographicRestrictionException (
896+ "This video is not available in user's country." );
885897 }
886898 }
887899 }
0 commit comments