Skip to content

Commit

Permalink
Attempt to load video data even without OK playability status.
Browse files Browse the repository at this point in the history
  • Loading branch information
devoxin committed Dec 3, 2024
1 parent e53e32e commit 37919d0
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ protected JsonBrowser loadTrackInfoFromInnertube(@NotNull YoutubeAudioSourceMana
@NotNull HttpInterface httpInterface,
@NotNull String videoId,
@Nullable PlayabilityStatus status) throws CannotBeLoaded, IOException {
// retain backwards-compatible behaviour for callers that do not use the new method with the additional parameter.
return loadTrackInfoFromInnertube(source, httpInterface, videoId, status, true);
}

@NotNull
protected JsonBrowser loadTrackInfoFromInnertube(@NotNull YoutubeAudioSourceManager source,
@NotNull HttpInterface httpInterface,
@NotNull String videoId,
@Nullable PlayabilityStatus status,
boolean validatePlayabilityStatus) throws CannotBeLoaded, IOException {
SignatureCipherManager cipherManager = source.getCipherManager();
CachedPlayerScript playerScript = cipherManager.getCachedPlayerScript(httpInterface);
SignatureCipher signatureCipher = cipherManager.getCipherScript(httpInterface, playerScript.url);
Expand Down Expand Up @@ -112,22 +122,28 @@ protected JsonBrowser loadTrackInfoFromInnertube(@NotNull YoutubeAudioSourceMana

JsonBrowser json = loadJsonResponse(httpInterface, request, "player api response");
JsonBrowser playabilityJson = json.get("playabilityStatus");
// fix: Make this method throw if a status was supplied (typically when we recurse).
PlayabilityStatus playabilityStatus = getPlayabilityStatus(playabilityJson, status != null);

// All other branches should've been caught by getPlayabilityStatus().
// An exception will be thrown if we can't handle it.
if (playabilityStatus == PlayabilityStatus.NON_EMBEDDABLE) {
if (isEmbedded()) {
throw new FriendlyException("Loading information for video failed", Severity.COMMON,
new RuntimeException("Non-embeddable video cannot be loaded by embedded client"));
}
JsonBrowser videoDetails = json.get("videoDetails");

json = loadTrackInfoFromInnertube(source, httpInterface, videoId, playabilityStatus);
getPlayabilityStatus(json.get("playabilityStatus"), true);
}
// we should always check playabilityStatus if videoDetails is null because it could contain important
// information as to why, which prevents false reports about this not working as intended etc etc.
if (validatePlayabilityStatus || videoDetails.isNull()) {
// fix: Make this method throw if a status was supplied (typically when we recurse).
PlayabilityStatus playabilityStatus = getPlayabilityStatus(playabilityJson, status != null);

// All other branches should've been caught by getPlayabilityStatus().
// An exception will be thrown if we can't handle it.
if (playabilityStatus == PlayabilityStatus.NON_EMBEDDABLE) {
if (isEmbedded()) {
throw new FriendlyException("Loading information for video failed", Severity.COMMON,
new RuntimeException("Non-embeddable video cannot be loaded by embedded client"));
}

JsonBrowser videoDetails = json.get("videoDetails");
// forcefully set validatePlayabilityStatus to true because the code is at this point for a reason.
// we want to make sure the re-check gets an accurate reason for any playability issues.
json = loadTrackInfoFromInnertube(source, httpInterface, videoId, playabilityStatus, true);
getPlayabilityStatus(json.get("playabilityStatus"), true);
}
}

if (videoDetails.isNull()) {
throw new FriendlyException("Loading information for video failed", Severity.SUSPICIOUS,
Expand Down Expand Up @@ -344,7 +360,7 @@ public AudioItem loadVideo(@NotNull YoutubeAudioSourceManager source,
throw new OptionDisabledException("Video loading is disabled for this client");
}

JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null);
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null, false);
JsonBrowser playabilityStatus = json.get("playabilityStatus");
JsonBrowser videoDetails = json.get("videoDetails");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public abstract class StreamingNonMusicClient extends NonMusicClient {
public TrackFormats loadFormats(@NotNull YoutubeAudioSourceManager source,
@NotNull HttpInterface httpInterface,
@NotNull String videoId) throws CannotBeLoaded, IOException {
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null);
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null, true);
JsonBrowser playabilityStatus = json.get("playabilityStatus");
JsonBrowser videoDetails = json.get("videoDetails");
CachedPlayerScript playerScript = source.getCipherManager().getCachedPlayerScript(httpInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public AudioItem loadVideo(@NotNull YoutubeAudioSourceManager source,
throw new OptionDisabledException("Video loading is disabled for this client");
}

JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null);
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null, false);
JsonBrowser playabilityStatus = json.get("playabilityStatus");
JsonBrowser videoDetails = json.get("videoDetails");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public abstract class ThumbnailStreamingNonMusicClient extends ThumbnailNonMusic
public TrackFormats loadFormats(@NotNull YoutubeAudioSourceManager source,
@NotNull HttpInterface httpInterface,
@NotNull String videoId) throws CannotBeLoaded, IOException {
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null);
JsonBrowser json = loadTrackInfoFromInnertube(source, httpInterface, videoId, null, true);
JsonBrowser playabilityStatus = json.get("playabilityStatus");
JsonBrowser videoDetails = json.get("videoDetails");
CachedPlayerScript playerScript = source.getCipherManager().getCachedPlayerScript(httpInterface);
Expand Down

0 comments on commit 37919d0

Please sign in to comment.