Skip to content

Commit

Permalink
merge YT explode 6.4.2
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm360 committed Sep 27, 2024
2 parents 48f7f09 + 40cf581 commit 8e1bd8e
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 23 deletions.
9 changes: 3 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var duration = video.Duration; // 00:07:20
Every YouTube video has a number of streams available, differing in containers, video quality, bitrate, framerate, and other parameters.
Additionally, the streams are further divided into 3 categories based on their content:

- Muxed streams — contain both video and audio
- ~~Muxed streams — contain both video and audio~~ (no longer provided by YouTube)
- Audio-only streams — contain only audio
- Video-only streams — contain only video

Expand Down Expand Up @@ -105,13 +105,10 @@ using YoutubeExplode.Videos.Streams;

// ...
// Get highest quality muxed stream
var streamInfo = streamManifest.GetMuxedStreams().GetWithHighestVideoQuality();

// ...or highest bitrate audio-only stream
// Get the highest bitrate audio-only stream
var streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate();

// ...or highest quality MP4 video-only stream
// ...or the highest quality MP4 video-only stream
var streamInfo = streamManifest
.GetVideoOnlyStreams()
.Where(s => s.Container == Container.Mp4)
Expand Down
2 changes: 1 addition & 1 deletion YoutubeDownloader.Tests/StreamSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ await youtube.Videos.Streams.GetHttpLiveStreamUrlAsync(VideoIds.RequiresPurchase
testOutput.WriteLine(ex.ToString());
}

[Fact]
[Fact(Skip = "The iOS client returns HLS URLs even for non-live videos")]
public async Task I_can_try_to_get_the_HTTP_live_stream_URL_for_a_video_and_get_an_error_if_it_is_not_live()
{
// Arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ private async IAsyncEnumerable<ClosedCaptionTrackInfo> GetClosedCaptionTrackInfo
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
// Use the TVHTML5 client instead of ANDROID_TESTSUITE because the latter doesn't provide closed captions
var playerResponse = await _controller.GetPlayerResponseAsync(
videoId,
null,
cancellationToken
);
var playerResponse = await _controller.GetPlayerResponseAsync(videoId, cancellationToken);

foreach (var trackData in playerResponse.ClosedCaptionTracks)
{
Expand Down
27 changes: 17 additions & 10 deletions YoutubeDownloader/Videos/VideoController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ public async ValueTask<PlayerResponse> GetPlayerResponseAsync(
CancellationToken cancellationToken = default
)
{
// The most optimal client to impersonate is the Android client, because
// it doesn't require signature deciphering (for both normal and n-parameter signatures).
// However, the regular Android client has a limitation, preventing it from downloading
// multiple streams from the same manifest (or the same stream multiple times).
// As a workaround, we're using ANDROID_TESTSUITE which appears to offer the same
// functionality, but doesn't impose the aforementioned limitation.
// The most optimal client to impersonate is any mobile client, because they
// don't require signature deciphering (for both normal and n-parameter signatures).
// However, we can't use the ANDROID client because it has a limitation, preventing it
// from downloading multiple streams from the same manifest (or the same stream multiple times).
// https://github.com/Tyrrrz/YoutubeExplode/issues/705
// Previously, we were using ANDROID_TESTSUITE as a workaround, which appeared to offer the same
// functionality, but without the aforementioned limitation. However, YouTube discontinued this
// client, so now we have to use IOS instead.
// https://github.com/Tyrrrz/YoutubeExplode/issues/817
using var request = new HttpRequestMessage(
HttpMethod.Post,
"https://www.youtube.com/youtubei/v1/player"
Expand All @@ -66,10 +68,15 @@ public async ValueTask<PlayerResponse> GetPlayerResponseAsync(
"videoId": {{Json.Serialize(videoId)}},
"context": {
"client": {
"clientName": "ANDROID_TESTSUITE",
"clientVersion": "1.9",
"androidSdkVersion": 30,
"clientName": "IOS",
"clientVersion": "19.29.1",
"deviceMake": "Apple",
"deviceModel": "iPhone16,2",
"hl": "en",
"osName": "iPhone",
"osVersion": "17.5.1.21F90",
"timeZone": "UTC",
"userAgent": "com.google.ios.youtube/19.29.1 (iPhone16,2; U; CPU iOS 17_5_1 like Mac OS X;)",
"gl": "US",
"utcOffsetMinutes": 0
}
Expand All @@ -82,7 +89,7 @@ public async ValueTask<PlayerResponse> GetPlayerResponseAsync(
// https://github.com/iv-org/invidious/issues/3230#issuecomment-1226887639
request.Headers.Add(
"User-Agent",
"com.google.android.youtube/17.36.4 (Linux; U; Android 12; GB) gzip"
"com.google.ios.youtube/19.29.1 (iPhone16,2; U; CPU iOS 17_5_1 like Mac OS X)"
);

using var response = await Http.SendAsync(request, cancellationToken);
Expand Down

0 comments on commit 8e1bd8e

Please sign in to comment.