[YouTube] Support the iOS client in YoutubeDashManifestCreator and decrypt again the n parameter, if present, for all clients

This commits reverts a new behavior introduced in this branch, which only applied the decryption if needed on streams from the WEB client.
Also fix rebase issues and documentations style in YoutubeDashManifestCreator.
This commit is contained in:
TiA4f8R 2022-04-11 19:35:57 +02:00
parent 436ddde29f
commit 07b045f20d
No known key found for this signature in database
GPG Key ID: E6D3E7F5949450DD
2 changed files with 25 additions and 33 deletions

View File

@ -33,8 +33,11 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.addClientInfoHeaders; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.addClientInfoHeaders;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getYoutubeAndroidAppUserAgent; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getAndroidUserAgent;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getIosUserAgent;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isIosStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isTvHtml5SimplyEmbeddedPlayerStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl;
import static org.schabi.newpipe.extractor.utils.Utils.EMPTY_STRING; import static org.schabi.newpipe.extractor.utils.Utils.EMPTY_STRING;
import static org.schabi.newpipe.extractor.utils.Utils.isBlank; import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
@ -562,54 +565,44 @@ public final class YoutubeDashManifestCreator {
@Nonnull final ItagItem itagItem, @Nonnull final ItagItem itagItem,
final DeliveryType deliveryType) final DeliveryType deliveryType)
throws YoutubeDashManifestCreationException { throws YoutubeDashManifestCreationException {
final boolean isAWebStreamingUrl = isWebStreamingUrl(baseStreamingUrl); final boolean isAHtml5StreamingUrl = isWebStreamingUrl(baseStreamingUrl)
|| isTvHtml5SimplyEmbeddedPlayerStreamingUrl(baseStreamingUrl);
final boolean isAnAndroidStreamingUrl = isAndroidStreamingUrl(baseStreamingUrl); final boolean isAnAndroidStreamingUrl = isAndroidStreamingUrl(baseStreamingUrl);
final boolean isAnAndroidStreamingUrlAndAPostLiveDvrStream = isAnAndroidStreamingUrl final boolean isAnIosStreamingUrl = isIosStreamingUrl(baseStreamingUrl);
&& deliveryType == DeliveryType.LIVE; if (isAHtml5StreamingUrl) {
if (isAWebStreamingUrl) {
baseStreamingUrl += ALR_YES; baseStreamingUrl += ALR_YES;
} }
baseStreamingUrl = appendRnParamAndSqParamIfNeeded(baseStreamingUrl, deliveryType); baseStreamingUrl = appendRnParamAndSqParamIfNeeded(baseStreamingUrl, deliveryType);
final Downloader downloader = NewPipe.getDownloader(); final Downloader downloader = NewPipe.getDownloader();
if (isAWebStreamingUrl) { if (isAHtml5StreamingUrl) {
final String mimeTypeExpected = itagItem.getMediaFormat().getMimeType(); final String mimeTypeExpected = itagItem.getMediaFormat().getMimeType();
if (!isNullOrEmpty(mimeTypeExpected)) { if (!isNullOrEmpty(mimeTypeExpected)) {
return getStreamingWebUrlWithoutRedirects(downloader, baseStreamingUrl, return getStreamingWebUrlWithoutRedirects(downloader, baseStreamingUrl,
mimeTypeExpected, deliveryType); mimeTypeExpected, deliveryType);
} }
} else if (isAnAndroidStreamingUrlAndAPostLiveDvrStream) { } else if (isAnAndroidStreamingUrl || isAnIosStreamingUrl) {
try { try {
final Map<String, List<String>> headers = new HashMap<>(); final Map<String, List<String>> headers = new HashMap<>();
headers.put("User-Agent", Collections.singletonList( headers.put("User-Agent", Collections.singletonList(
getYoutubeAndroidAppUserAgent(null))); isAnAndroidStreamingUrl ? getAndroidUserAgent(null)
: getIosUserAgent(null)));
final byte[] emptyBody = "".getBytes(StandardCharsets.UTF_8); final byte[] emptyBody = "".getBytes(StandardCharsets.UTF_8);
return downloader.post(baseStreamingUrl, headers, emptyBody); return downloader.post(baseStreamingUrl, headers, emptyBody);
} catch (final IOException | ExtractionException e) { } catch (final IOException | ExtractionException e) {
throw new YoutubeDashManifestCreationException( throw new YoutubeDashManifestCreationException(
"Could not generate the DASH manifest: error when trying to get the " "Could not generate the DASH manifest: error when trying to get the "
+ "ANDROID streaming post-live-DVR URL response", e); + (isAnIosStreamingUrl ? "ANDROID" : "IOS")
+ " streaming URL response", e);
} }
} }
try { try {
final Map<String, List<String>> headers = new HashMap<>(); return downloader.get(baseStreamingUrl);
if (isAnAndroidStreamingUrl) {
headers.put("User-Agent", Collections.singletonList(
getYoutubeAndroidAppUserAgent(null)));
}
return downloader.get(baseStreamingUrl, headers);
} catch (final IOException | ExtractionException e) { } catch (final IOException | ExtractionException e) {
if (isAnAndroidStreamingUrl) {
throw new YoutubeDashManifestCreationException( throw new YoutubeDashManifestCreationException(
"Could not generate the DASH manifest: error when trying to get the " "Could not generate the DASH manifest: error when trying to get the streaming "
+ "ANDROID streaming URL response", e); + "URL response", e);
} else {
throw new YoutubeDashManifestCreationException(
"Could not generate the DASH manifest: error when trying to get the "
+ "streaming URL response", e);
}
} }
} }
@ -834,8 +827,10 @@ public final class YoutubeDashManifestCreator {
* sequence of the stream * sequence of the stream
* @param deliveryType the {@link DeliveryType} of the stream, see the enum for * @param deliveryType the {@link DeliveryType} of the stream, see the enum for
* possible values * possible values
* @param itagItem the {@link ItagItem} which will be used to get the duration
* of progressive streams
* @param durationSecondsFallback the duration in seconds, extracted from player response, used * @param durationSecondsFallback the duration in seconds, extracted from player response, used
* as a fallback * as a fallback if the duration could not be determined
* @return a {@link Document} object which contains a {@code <MPD>} element * @return a {@link Document} object which contains a {@code <MPD>} element
* @throws YoutubeDashManifestCreationException if something goes wrong when generating/ * @throws YoutubeDashManifestCreationException if something goes wrong when generating/
* appending the {@link Document object} or the * appending the {@link Document object} or the
@ -1698,7 +1693,7 @@ public final class YoutubeDashManifestCreator {
} }
/** /**
* Set the clear factor of cached OTF streams * Set the clear factor of cached OTF streams.
* *
* @param otfStreamsClearFactor the clear factor of OTF streams manifests cache. * @param otfStreamsClearFactor the clear factor of OTF streams manifests cache.
*/ */
@ -1707,7 +1702,7 @@ public final class YoutubeDashManifestCreator {
} }
/** /**
* Set the clear factor of cached post-live-DVR streams * Set the clear factor of cached post-live-DVR streams.
* *
* @param postLiveDvrStreamsClearFactor the clear factor of post-live-DVR streams manifests * @param postLiveDvrStreamsClearFactor the clear factor of post-live-DVR streams manifests
* cache. * cache.
@ -1718,7 +1713,7 @@ public final class YoutubeDashManifestCreator {
} }
/** /**
* Set the clear factor of cached progressive streams * Set the clear factor of cached progressive streams.
* *
* @param progressiveStreamsClearFactor the clear factor of progressive streams manifests * @param progressiveStreamsClearFactor the clear factor of progressive streams manifests
* cache. * cache.

View File

@ -29,12 +29,10 @@ import static org.schabi.newpipe.extractor.services.youtube.ItagItem.CONTENT_LEN
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.fixThumbnailUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.fixThumbnailUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.generateContentPlaybackNonce; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.generateContentPlaybackNonce;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.generateTParameter; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.generateTParameter;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getClientVersion;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonAndroidPostResponse; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonAndroidPostResponse;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonIosPostResponse; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonIosPostResponse;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareAndroidMobileJsonBuilder; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareAndroidMobileJsonBuilder;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareIosMobileJsonBuilder; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareIosMobileJsonBuilder;
@ -1366,9 +1364,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
// Add the content playback nonce to the stream URL // Add the content playback nonce to the stream URL
streamUrl += "&" + CPN + "=" + contentPlaybackNonce; streamUrl += "&" + CPN + "=" + contentPlaybackNonce;
if (isWebStreamingUrl(streamUrl)) { // Decrypt the n parameter if it is present
streamUrl = tryDecryptUrl(streamUrl, videoId) + "&cver=" + getClientVersion(); streamUrl = tryDecryptUrl(streamUrl, videoId);
}
final JsonObject initRange = formatData.getObject("initRange"); final JsonObject initRange = formatData.getObject("initRange");
final JsonObject indexRange = formatData.getObject("indexRange"); final JsonObject indexRange = formatData.getObject("indexRange");