diff --git a/YouTube.API.Test/YouTube.API.Test.csproj b/YouTube.API.Test/YouTube.API.Test.csproj index d10404e..74167eb 100644 --- a/YouTube.API.Test/YouTube.API.Test.csproj +++ b/YouTube.API.Test/YouTube.API.Test.csproj @@ -8,8 +8,11 @@ - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/YouTube.API/Generators/ManifestGenerator.cs b/YouTube.API/Generators/ManifestGenerator.cs index c624edf..4507d4d 100644 --- a/YouTube.API/Generators/ManifestGenerator.cs +++ b/YouTube.API/Generators/ManifestGenerator.cs @@ -12,8 +12,8 @@ using System.Threading.Tasks; using System.Xml; using YouTube.Models; using YoutubeExplode; -using YoutubeExplode.Models; -using YoutubeExplode.Models.MediaStreams; +using YoutubeExplode.Videos; +using YoutubeExplode.Videos.Streams; namespace YouTube.Generators { @@ -23,7 +23,7 @@ namespace YouTube.Generators YoutubeClient Client { get; } string Id { get; } Video Meta { get; set; } - MediaStreamInfoSet UrlsSet { get; set; } + StreamManifest UrlsSet { get; set; } public ManifestGenerator(IClientService service, string id) { @@ -34,21 +34,22 @@ namespace YouTube.Generators public async Task> GenerateManifestsAsync() { - Meta = await Client.GetVideoAsync(Id); + Meta = await Client.Videos.GetAsync(Id); if (Meta == null) throw new FileNotFoundException("Video not found. Check video ID and visibility preferences"); - UrlsSet = await Client.GetVideoMediaStreamInfosAsync(Id); - - if (!string.IsNullOrWhiteSpace(UrlsSet.HlsLiveStreamUrl)) + if (!string.IsNullOrWhiteSpace(await Client.Videos.Streams.GetHttpLiveStreamUrlAsync(Id))) throw new NotSupportedException("This is livestream. Use 'YouTubeClient.VideoPlayback.List()' to get playback URLs"); + UrlsSet = await Client.Videos.Streams.GetManifestAsync(Id); + List list = new List { await GenerateManifest("Auto") }; - foreach (string i in UrlsSet.GetAllVideoQualityLabels()) + + foreach (string i in UrlsSet.GetVideo().Select(k => k.VideoQualityLabel).Distinct()) list.Add(await GenerateManifest(i)); return list.AsReadOnly(); diff --git a/YouTube.API/Models/ClosedCaptionInfo.cs b/YouTube.API/Models/ClosedCaptionInfo.cs index d3af9f0..ab60364 100644 --- a/YouTube.API/Models/ClosedCaptionInfo.cs +++ b/YouTube.API/Models/ClosedCaptionInfo.cs @@ -1,5 +1,5 @@ using System.Globalization; -using YoutubeExplode.Models.ClosedCaptions; +using YoutubeExplode.Videos.ClosedCaptions; namespace YouTube.Models { diff --git a/YouTube.API/Models/VideoPlayback.cs b/YouTube.API/Models/VideoPlayback.cs index 8e94953..c7e2910 100644 --- a/YouTube.API/Models/VideoPlayback.cs +++ b/YouTube.API/Models/VideoPlayback.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using YoutubeExplode.Videos.Streams; namespace YouTube.Models { @@ -11,9 +12,9 @@ namespace YouTube.Models public class PlaybackUrlsData { - public IReadOnlyList Video { get; set; } - public IReadOnlyList Audio { get; set; } + public StreamManifest VideoFilesManifest { get; set; } public string LiveStreamUrl { get; set; } + [Obsolete] public DateTime ValidUntil { get; set; } } } diff --git a/YouTube.API/Resources/CaptionsResource.cs b/YouTube.API/Resources/CaptionsResource.cs index 9fe8cfe..fb984e8 100644 --- a/YouTube.API/Resources/CaptionsResource.cs +++ b/YouTube.API/Resources/CaptionsResource.cs @@ -29,7 +29,7 @@ namespace YouTube.Resources public async Task ExecuteAsync() { YoutubeClient client = new YoutubeClient(Service.HttpClient); - var response = await client.GetClosedCaptionTrackAsync(CaptionInfo.TrackInfo); + var response = await client.Videos.ClosedCaptions.GetAsync(CaptionInfo.TrackInfo); List captions = new List(); foreach (var i in response.Captions) captions.Add(new ClosedCaptionTrack.ClosedCaption diff --git a/YouTube.API/Resources/VideoPlaybackResource.cs b/YouTube.API/Resources/VideoPlaybackResource.cs index b7635f8..2808ff2 100644 --- a/YouTube.API/Resources/VideoPlaybackResource.cs +++ b/YouTube.API/Resources/VideoPlaybackResource.cs @@ -1,12 +1,13 @@ using Google.Apis.Services; +using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.Threading.Tasks; using YouTube.Models; using YoutubeExplode; -using YoutubeExplode.Models.ClosedCaptions; -using YoutubeExplode.Models.MediaStreams; +using YoutubeExplode.Videos.ClosedCaptions; +using YoutubeExplode.Videos.Streams; namespace YouTube.Resources { @@ -29,60 +30,21 @@ namespace YouTube.Resources { VideoPlayback item = new VideoPlayback(); YoutubeClient client = new YoutubeClient(Service.HttpClient); - MediaStreamInfoSet streamSet = await client.GetVideoMediaStreamInfosAsync(Id); item.Id = Id; - item.PlaybackUrls.ValidUntil = streamSet.ValidUntil.DateTime; - if (!string.IsNullOrWhiteSpace(streamSet.HlsLiveStreamUrl)) - { - item.PlaybackUrls.LiveStreamUrl = streamSet.HlsLiveStreamUrl; + item.PlaybackUrls.ValidUntil = DateTime.Now + TimeSpan.FromHours(1); + + item.PlaybackUrls.LiveStreamUrl = await client.Videos.Streams.GetHttpLiveStreamUrlAsync(Id); + + if (!string.IsNullOrWhiteSpace(item.PlaybackUrls.LiveStreamUrl)) return item; - } - List audio = new List(); - foreach (AudioStreamInfo i in streamSet.Audio) - audio.Add(new AudioPlaybackUrl - { - Url = i.Url, - Bitrate = (int)i.Bitrate, - Format = (AudioFormat)i.AudioEncoding, - Quality = Extensions.RangeOffset((int)i.Bitrate / 1024, 128, 255) switch - { - -1 => AudioQuality.Low, - 1 => AudioQuality.High, - _ => AudioQuality.Medium - } - }); - item.PlaybackUrls.Audio = audio.AsReadOnly(); + item.PlaybackUrls.VideoFilesManifest = await client.Videos.Streams.GetManifestAsync(Id); - List video = new List(); - foreach (VideoStreamInfo i in streamSet.Video) - video.Add(new VideoPlaybackUrl - { - Format = (VideoFormat)i.VideoEncoding, - HasAudio = false, - Quality = i.VideoQualityLabel, - Url = i.Url, - Resolution = new Size(i.Resolution.Width, i.Resolution.Height), - Bitrate = (int)i.Bitrate - }); - - foreach (MuxedStreamInfo i in streamSet.Muxed) - video.Add(new VideoPlaybackUrl - { - Format = (VideoFormat)i.VideoEncoding, - HasAudio = true, - Quality = i.VideoQualityLabel, - Url = i.Url, - Resolution = new Size(i.Resolution.Width, i.Resolution.Height), - Bitrate = 0 - }); - item.PlaybackUrls.Video = video.AsReadOnly(); - - var ccSet = await client.GetVideoClosedCaptionTrackInfosAsync(Id); + ClosedCaptionManifest ccSet = await client.Videos.ClosedCaptions.GetManifestAsync(Id); List captions = new List(); - foreach (ClosedCaptionTrackInfo i in ccSet) + foreach (ClosedCaptionTrackInfo i in ccSet.Tracks) captions.Add(new ClosedCaptionInfo { AutoGenerated = i.IsAutoGenerated, diff --git a/YouTube.API/YouTube.API.csproj b/YouTube.API/YouTube.API.csproj index d096a51..bd4ddc6 100644 --- a/YouTube.API/YouTube.API.csproj +++ b/YouTube.API/YouTube.API.csproj @@ -1,7 +1,7 @@  - net46;netstandard2.0 + net461;netstandard2.1 YouTube.API YouTube Michael "XFox" Gordeev @@ -29,7 +29,7 @@ - +