diff --git a/YoutubeExplode.Converter/ConversionFormat.cs b/YoutubeExplode.Converter/ConversionFormat.cs index c911bfa3..4f4fbebd 100644 --- a/YoutubeExplode.Converter/ConversionFormat.cs +++ b/YoutubeExplode.Converter/ConversionFormat.cs @@ -8,23 +8,18 @@ namespace YoutubeExplode.Converter; /// Encapsulates conversion media format. /// [Obsolete("Use YoutubeExplode.Videos.Streams.Container instead"), ExcludeFromCodeCoverage] -public readonly struct ConversionFormat +public readonly struct ConversionFormat(string name) { /// /// Format name. /// - public string Name { get; } + public string Name { get; } = name; /// /// Whether this format is a known audio-only format. /// public bool IsAudioOnly => new Container(Name).IsAudioOnly(); - /// - /// Initializes an instance of . - /// - public ConversionFormat(string name) => Name = name; - /// public override string ToString() => Name; } diff --git a/YoutubeExplode.Converter/ConversionRequest.cs b/YoutubeExplode.Converter/ConversionRequest.cs index 876c6b4e..3fcb9f9e 100644 --- a/YoutubeExplode.Converter/ConversionRequest.cs +++ b/YoutubeExplode.Converter/ConversionRequest.cs @@ -7,22 +7,39 @@ namespace YoutubeExplode.Converter; /// /// Conversion options. /// -public class ConversionRequest +public class ConversionRequest( + string ffmpegCliFilePath, + string outputFilePath, + Container container, + ConversionPreset preset +) { + /// + /// Initializes an instance of . + /// + [Obsolete("Use the other constructor overload"), ExcludeFromCodeCoverage] + public ConversionRequest( + string ffmpegCliFilePath, + string outputFilePath, + ConversionFormat format, + ConversionPreset preset + ) + : this(ffmpegCliFilePath, outputFilePath, new Container(format.Name), preset) { } + /// /// Path to the FFmpeg CLI. /// - public string FFmpegCliFilePath { get; } + public string FFmpegCliFilePath { get; } = ffmpegCliFilePath; /// /// Output file path. /// - public string OutputFilePath { get; } + public string OutputFilePath { get; } = outputFilePath; /// /// Output container. /// - public Container Container { get; } + public Container Container { get; } = container; /// /// Output format. @@ -33,33 +50,5 @@ public class ConversionRequest /// /// Encoder preset. /// - public ConversionPreset Preset { get; } - - /// - /// Initializes an instance of . - /// - public ConversionRequest( - string ffmpegCliFilePath, - string outputFilePath, - Container container, - ConversionPreset preset - ) - { - FFmpegCliFilePath = ffmpegCliFilePath; - OutputFilePath = outputFilePath; - Container = container; - Preset = preset; - } - - /// - /// Initializes an instance of . - /// - [Obsolete("Use the other constructor overload"), ExcludeFromCodeCoverage] - public ConversionRequest( - string ffmpegCliFilePath, - string outputFilePath, - ConversionFormat format, - ConversionPreset preset - ) - : this(ffmpegCliFilePath, outputFilePath, new Container(format.Name), preset) { } + public ConversionPreset Preset { get; } = preset; } diff --git a/YoutubeExplode.Converter/ConversionRequestBuilder.cs b/YoutubeExplode.Converter/ConversionRequestBuilder.cs index f6a7c7ed..266c7fb4 100644 --- a/YoutubeExplode.Converter/ConversionRequestBuilder.cs +++ b/YoutubeExplode.Converter/ConversionRequestBuilder.cs @@ -9,21 +9,14 @@ namespace YoutubeExplode.Converter; /// /// Builder for . /// -public class ConversionRequestBuilder +public class ConversionRequestBuilder(string outputFilePath) { - private readonly string _outputFilePath; - private string? _ffmpegCliFilePath; private Container? _container; private ConversionPreset _preset; - /// - /// Initializes an instance of . - /// - public ConversionRequestBuilder(string outputFilePath) => _outputFilePath = outputFilePath; - private Container GetDefaultContainer() => - new(Path.GetExtension(_outputFilePath).TrimStart('.').NullIfWhiteSpace() ?? "mp4"); + new(Path.GetExtension(outputFilePath).TrimStart('.').NullIfWhiteSpace() ?? "mp4"); /// /// Sets the path to the FFmpeg CLI. @@ -77,7 +70,7 @@ public ConversionRequestBuilder SetPreset(ConversionPreset preset) public ConversionRequest Build() => new( _ffmpegCliFilePath ?? FFmpeg.GetFilePath(), - _outputFilePath, + outputFilePath, _container ?? GetDefaultContainer(), _preset ); diff --git a/YoutubeExplode/Channels/Channel.cs b/YoutubeExplode/Channels/Channel.cs index 3bf472d0..cfd0f638 100644 --- a/YoutubeExplode/Channels/Channel.cs +++ b/YoutubeExplode/Channels/Channel.cs @@ -7,29 +7,19 @@ namespace YoutubeExplode.Channels; /// /// Metadata associated with a YouTube channel. /// -public class Channel : IChannel +public class Channel(ChannelId id, string title, IReadOnlyList thumbnails) : IChannel { /// - public ChannelId Id { get; } + public ChannelId Id { get; } = id; /// public string Url => $"https://www.youtube.com/channel/{Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public Channel(ChannelId id, string title, IReadOnlyList thumbnails) - { - Id = id; - Title = title; - Thumbnails = thumbnails; - } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Channels/ChannelClient.cs b/YoutubeExplode/Channels/ChannelClient.cs index 76a9c367..c5b757e1 100644 --- a/YoutubeExplode/Channels/ChannelClient.cs +++ b/YoutubeExplode/Channels/ChannelClient.cs @@ -15,19 +15,9 @@ namespace YoutubeExplode.Channels; /// /// Operations related to YouTube channels. /// -public class ChannelClient +public class ChannelClient(HttpClient http) { - private readonly HttpClient _http; - private readonly ChannelController _controller; - - /// - /// Initializes an instance of . - /// - public ChannelClient(HttpClient http) - { - _http = http; - _controller = new ChannelController(http); - } + private readonly ChannelController _controller = new(http); private Channel Get(ChannelPage channelPage) { @@ -118,6 +108,6 @@ public IAsyncEnumerable GetUploadsAsync( { // Replace 'UC' in the channel ID with 'UU' var playlistId = "UU" + channelId.Value[2..]; - return new PlaylistClient(_http).GetVideosAsync(playlistId, cancellationToken); + return new PlaylistClient(http).GetVideosAsync(playlistId, cancellationToken); } } diff --git a/YoutubeExplode/Common/Author.cs b/YoutubeExplode/Common/Author.cs index ecfbbc9c..559f594e 100644 --- a/YoutubeExplode/Common/Author.cs +++ b/YoutubeExplode/Common/Author.cs @@ -7,12 +7,12 @@ namespace YoutubeExplode.Common; /// /// Reference to a channel that owns a specific YouTube video or playlist. /// -public class Author +public class Author(ChannelId channelId, string channelTitle) { /// /// Channel ID. /// - public ChannelId ChannelId { get; } + public ChannelId ChannelId { get; } = channelId; /// /// Channel URL. @@ -22,21 +22,12 @@ public class Author /// /// Channel title. /// - public string ChannelTitle { get; } + public string ChannelTitle { get; } = channelTitle; /// [Obsolete("Use ChannelTitle instead."), ExcludeFromCodeCoverage] public string Title => ChannelTitle; - /// - /// Initializes an instance of . - /// - public Author(ChannelId channelId, string channelTitle) - { - ChannelId = channelId; - ChannelTitle = channelTitle; - } - /// [ExcludeFromCodeCoverage] public override string ToString() => ChannelTitle; diff --git a/YoutubeExplode/Common/Batch.cs b/YoutubeExplode/Common/Batch.cs index f6187e3e..c9645ad4 100644 --- a/YoutubeExplode/Common/Batch.cs +++ b/YoutubeExplode/Common/Batch.cs @@ -6,18 +6,13 @@ namespace YoutubeExplode.Common; /// /// Generic collection of items returned by a single request. /// -public class Batch +public class Batch(IReadOnlyList items) where T : IBatchItem { /// /// Items included in the batch. /// - public IReadOnlyList Items { get; } - - /// - /// Initializes an instance of . - /// - public Batch(IReadOnlyList items) => Items = items; + public IReadOnlyList Items { get; } = items; } internal static class Batch diff --git a/YoutubeExplode/Common/Resolution.cs b/YoutubeExplode/Common/Resolution.cs index f9429206..3dc2d5a3 100644 --- a/YoutubeExplode/Common/Resolution.cs +++ b/YoutubeExplode/Common/Resolution.cs @@ -6,32 +6,23 @@ namespace YoutubeExplode.Common; /// /// Resolution of an image or a video. /// -public readonly partial struct Resolution +public readonly partial struct Resolution(int width, int height) { /// /// Viewport width, measured in pixels. /// - public int Width { get; } + public int Width { get; } = width; /// /// Viewport height, measured in pixels. /// - public int Height { get; } + public int Height { get; } = height; /// /// Viewport area (i.e. width multiplied by height). /// public int Area => Width * Height; - /// - /// Initializes an instance of . - /// - public Resolution(int width, int height) - { - Width = width; - Height = height; - } - /// [ExcludeFromCodeCoverage] public override string ToString() => $"{Width}x{Height}"; diff --git a/YoutubeExplode/Common/Thumbnail.cs b/YoutubeExplode/Common/Thumbnail.cs index ccaab477..4c58498f 100644 --- a/YoutubeExplode/Common/Thumbnail.cs +++ b/YoutubeExplode/Common/Thumbnail.cs @@ -9,26 +9,17 @@ namespace YoutubeExplode.Common; /// /// Thumbnail image. /// -public partial class Thumbnail +public partial class Thumbnail(string url, Resolution resolution) { /// /// Thumbnail URL. /// - public string Url { get; } + public string Url { get; } = url; /// /// Thumbnail resolution. /// - public Resolution Resolution { get; } - - /// - /// Initializes an instance of . - /// - public Thumbnail(string url, Resolution resolution) - { - Url = url; - Resolution = resolution; - } + public Resolution Resolution { get; } = resolution; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Exceptions/PlaylistUnavailableException.cs b/YoutubeExplode/Exceptions/PlaylistUnavailableException.cs index 696ad1b1..a7d1d8aa 100644 --- a/YoutubeExplode/Exceptions/PlaylistUnavailableException.cs +++ b/YoutubeExplode/Exceptions/PlaylistUnavailableException.cs @@ -3,11 +3,4 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown when the requested playlist is unavailable. /// -public class PlaylistUnavailableException : YoutubeExplodeException -{ - /// - /// Initializes an instance of . - /// - public PlaylistUnavailableException(string message) - : base(message) { } -} +public class PlaylistUnavailableException(string message) : YoutubeExplodeException(message); diff --git a/YoutubeExplode/Exceptions/RequestLimitExceededException.cs b/YoutubeExplode/Exceptions/RequestLimitExceededException.cs index a52cf053..8b540ac9 100644 --- a/YoutubeExplode/Exceptions/RequestLimitExceededException.cs +++ b/YoutubeExplode/Exceptions/RequestLimitExceededException.cs @@ -3,11 +3,4 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown when YouTube denies a request because the client has exceeded rate limit. /// -public class RequestLimitExceededException : YoutubeExplodeException -{ - /// - /// Initializes an instance of . - /// - public RequestLimitExceededException(string message) - : base(message) { } -} +public class RequestLimitExceededException(string message) : YoutubeExplodeException(message); diff --git a/YoutubeExplode/Exceptions/VideoRequiresPurchaseException.cs b/YoutubeExplode/Exceptions/VideoRequiresPurchaseException.cs index 6325c2c8..32bcc95d 100644 --- a/YoutubeExplode/Exceptions/VideoRequiresPurchaseException.cs +++ b/YoutubeExplode/Exceptions/VideoRequiresPurchaseException.cs @@ -5,16 +5,11 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown when the requested video requires purchase. /// -public class VideoRequiresPurchaseException : VideoUnplayableException +public class VideoRequiresPurchaseException(string message, VideoId previewVideoId) + : VideoUnplayableException(message) { /// /// ID of a free preview video which is used as promotion for the original video. /// - public VideoId PreviewVideoId { get; } - - /// - /// Initializes an instance of - /// - public VideoRequiresPurchaseException(string message, VideoId previewVideoId) - : base(message) => PreviewVideoId = previewVideoId; + public VideoId PreviewVideoId { get; } = previewVideoId; } diff --git a/YoutubeExplode/Exceptions/VideoUnavailableException.cs b/YoutubeExplode/Exceptions/VideoUnavailableException.cs index af7f0e1a..1727757e 100644 --- a/YoutubeExplode/Exceptions/VideoUnavailableException.cs +++ b/YoutubeExplode/Exceptions/VideoUnavailableException.cs @@ -3,11 +3,4 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown when the requested video is unavailable. /// -public class VideoUnavailableException : VideoUnplayableException -{ - /// - /// Initializes an instance of . - /// - public VideoUnavailableException(string message) - : base(message) { } -} +public class VideoUnavailableException(string message) : VideoUnplayableException(message); diff --git a/YoutubeExplode/Exceptions/VideoUnplayableException.cs b/YoutubeExplode/Exceptions/VideoUnplayableException.cs index c7c65f7f..3964c781 100644 --- a/YoutubeExplode/Exceptions/VideoUnplayableException.cs +++ b/YoutubeExplode/Exceptions/VideoUnplayableException.cs @@ -3,11 +3,4 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown when the requested video is unplayable. /// -public class VideoUnplayableException : YoutubeExplodeException -{ - /// - /// Initializes an instance of . - /// - public VideoUnplayableException(string message) - : base(message) { } -} +public class VideoUnplayableException(string message) : YoutubeExplodeException(message); diff --git a/YoutubeExplode/Exceptions/YoutubeExplodeException.cs b/YoutubeExplode/Exceptions/YoutubeExplodeException.cs index e8385d66..91875d45 100644 --- a/YoutubeExplode/Exceptions/YoutubeExplodeException.cs +++ b/YoutubeExplode/Exceptions/YoutubeExplodeException.cs @@ -5,12 +5,4 @@ namespace YoutubeExplode.Exceptions; /// /// Exception thrown within . /// -public class YoutubeExplodeException : Exception -{ - /// - /// Initializes an instance of . - /// - /// - public YoutubeExplodeException(string message) - : base(message) { } -} +public class YoutubeExplodeException(string message) : Exception(message); diff --git a/YoutubeExplode/Playlists/Playlist.cs b/YoutubeExplode/Playlists/Playlist.cs index 141c9dec..37a770fd 100644 --- a/YoutubeExplode/Playlists/Playlist.cs +++ b/YoutubeExplode/Playlists/Playlist.cs @@ -7,45 +7,33 @@ namespace YoutubeExplode.Playlists; /// /// Metadata associated with a YouTube playlist. /// -public class Playlist : IPlaylist +public class Playlist( + PlaylistId id, + string title, + Author? author, + string description, + IReadOnlyList thumbnails +) : IPlaylist { /// - public PlaylistId Id { get; } + public PlaylistId Id { get; } = id; /// public string Url => $"https://www.youtube.com/playlist?list={Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public Author? Author { get; } + public Author? Author { get; } = author; /// /// Playlist description. /// - public string Description { get; } + public string Description { get; } = description; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public Playlist( - PlaylistId id, - string title, - Author? author, - string description, - IReadOnlyList thumbnails - ) - { - Id = id; - Title = title; - Author = author; - Description = description; - Thumbnails = thumbnails; - } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Playlists/PlaylistClient.cs b/YoutubeExplode/Playlists/PlaylistClient.cs index 380fbd51..35d8dcdd 100644 --- a/YoutubeExplode/Playlists/PlaylistClient.cs +++ b/YoutubeExplode/Playlists/PlaylistClient.cs @@ -13,14 +13,9 @@ namespace YoutubeExplode.Playlists; /// /// Operations related to YouTube playlists. /// -public class PlaylistClient +public class PlaylistClient(HttpClient http) { - private readonly PlaylistController _controller; - - /// - /// Initializes an instance of . - /// - public PlaylistClient(HttpClient http) => _controller = new PlaylistController(http); + private readonly PlaylistController _controller = new(http); /// /// Gets the metadata associated with the specified playlist. diff --git a/YoutubeExplode/Playlists/PlaylistVideo.cs b/YoutubeExplode/Playlists/PlaylistVideo.cs index 8b50a68e..227e6b3a 100644 --- a/YoutubeExplode/Playlists/PlaylistVideo.cs +++ b/YoutubeExplode/Playlists/PlaylistVideo.cs @@ -9,64 +9,51 @@ namespace YoutubeExplode.Playlists; /// /// Metadata associated with a YouTube video included in a playlist. /// -public class PlaylistVideo : IVideo, IBatchItem +public class PlaylistVideo( + PlaylistId playlistId, + VideoId id, + string title, + Author author, + TimeSpan? duration, + IReadOnlyList thumbnails +) : IVideo, IBatchItem { + /// + /// Initializes an instance of . + /// + // Binary backwards compatibility (PlaylistId was added) + [Obsolete("Use the other constructor instead."), ExcludeFromCodeCoverage] + public PlaylistVideo( + VideoId id, + string title, + Author author, + TimeSpan? duration, + IReadOnlyList thumbnails + ) + : this(default, id, title, author, duration, thumbnails) { } + /// /// ID of the playlist that contains this video. /// - public PlaylistId PlaylistId { get; } + public PlaylistId PlaylistId { get; } = playlistId; /// - public VideoId Id { get; } + public VideoId Id { get; } = id; /// public string Url => $"https://www.youtube.com/watch?v={Id}&list={PlaylistId}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public Author Author { get; } + public Author Author { get; } = author; /// - public TimeSpan? Duration { get; } + public TimeSpan? Duration { get; } = duration; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public PlaylistVideo( - PlaylistId playlistId, - VideoId id, - string title, - Author author, - TimeSpan? duration, - IReadOnlyList thumbnails - ) - { - PlaylistId = playlistId; - Id = id; - Title = title; - Author = author; - Duration = duration; - Thumbnails = thumbnails; - } - - /// - /// Initializes an instance of . - /// - // Binary backwards compatibility (PlaylistId was added) - [Obsolete("Use the other constructor instead."), ExcludeFromCodeCoverage] - public PlaylistVideo( - VideoId id, - string title, - Author author, - TimeSpan? duration, - IReadOnlyList thumbnails - ) - : this(default, id, title, author, duration, thumbnails) { } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Search/ChannelSearchResult.cs b/YoutubeExplode/Search/ChannelSearchResult.cs index 8bdaf94b..7fc832b6 100644 --- a/YoutubeExplode/Search/ChannelSearchResult.cs +++ b/YoutubeExplode/Search/ChannelSearchResult.cs @@ -8,29 +8,21 @@ namespace YoutubeExplode.Search; /// /// Metadata associated with a YouTube channel returned by a search query. /// -public class ChannelSearchResult : ISearchResult, IChannel +public class ChannelSearchResult(ChannelId id, string title, IReadOnlyList thumbnails) + : ISearchResult, + IChannel { /// - public ChannelId Id { get; } + public ChannelId Id { get; } = id; /// public string Url => $"https://www.youtube.com/channel/{Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public ChannelSearchResult(ChannelId id, string title, IReadOnlyList thumbnails) - { - Id = id; - Title = title; - Thumbnails = thumbnails; - } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Search/PlaylistSearchResult.cs b/YoutubeExplode/Search/PlaylistSearchResult.cs index 49127f0e..eda25e5e 100644 --- a/YoutubeExplode/Search/PlaylistSearchResult.cs +++ b/YoutubeExplode/Search/PlaylistSearchResult.cs @@ -8,38 +8,27 @@ namespace YoutubeExplode.Search; /// /// Metadata associated with a YouTube playlist returned by a search query. /// -public class PlaylistSearchResult : ISearchResult, IPlaylist +public class PlaylistSearchResult( + PlaylistId id, + string title, + Author? author, + IReadOnlyList thumbnails +) : ISearchResult, IPlaylist { /// - public PlaylistId Id { get; } + public PlaylistId Id { get; } = id; /// public string Url => $"https://www.youtube.com/playlist?list={Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public Author? Author { get; } + public Author? Author { get; } = author; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public PlaylistSearchResult( - PlaylistId id, - string title, - Author? author, - IReadOnlyList thumbnails - ) - { - Id = id; - Title = title; - Author = author; - Thumbnails = thumbnails; - } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Search/SearchClient.cs b/YoutubeExplode/Search/SearchClient.cs index 8a00433e..521631c5 100644 --- a/YoutubeExplode/Search/SearchClient.cs +++ b/YoutubeExplode/Search/SearchClient.cs @@ -14,14 +14,9 @@ namespace YoutubeExplode.Search; /// /// Operations related to YouTube search. /// -public class SearchClient +public class SearchClient(HttpClient http) { - private readonly SearchController _controller; - - /// - /// Initializes an instance of . - /// - public SearchClient(HttpClient http) => _controller = new SearchController(http); + private readonly SearchController _controller = new(http); /// /// Enumerates batches of search results returned by the specified query. diff --git a/YoutubeExplode/Search/VideoSearchResult.cs b/YoutubeExplode/Search/VideoSearchResult.cs index dd847578..df158bab 100644 --- a/YoutubeExplode/Search/VideoSearchResult.cs +++ b/YoutubeExplode/Search/VideoSearchResult.cs @@ -9,43 +9,31 @@ namespace YoutubeExplode.Search; /// /// Metadata associated with a YouTube video returned by a search query. /// -public class VideoSearchResult : ISearchResult, IVideo +public class VideoSearchResult( + VideoId id, + string title, + Author author, + TimeSpan? duration, + IReadOnlyList thumbnails +) : ISearchResult, IVideo { /// - public VideoId Id { get; } + public VideoId Id { get; } = id; /// public string Url => $"https://www.youtube.com/watch?v={Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public Author Author { get; } + public Author Author { get; } = author; /// - public TimeSpan? Duration { get; } + public TimeSpan? Duration { get; } = duration; /// - public IReadOnlyList Thumbnails { get; } - - /// - /// Initializes an instance of . - /// - public VideoSearchResult( - VideoId id, - string title, - Author author, - TimeSpan? duration, - IReadOnlyList thumbnails - ) - { - Id = id; - Title = title; - Author = author; - Duration = duration; - Thumbnails = thumbnails; - } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaption.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaption.cs index 1b3f8a3e..fe993604 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaption.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaption.cs @@ -8,22 +8,27 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Individual closed caption contained within a track. /// -public class ClosedCaption +public class ClosedCaption( + string text, + TimeSpan offset, + TimeSpan duration, + IReadOnlyList parts +) { /// /// Text displayed by the caption. /// - public string Text { get; } + public string Text { get; } = text; /// /// Time at which the caption starts displaying. /// - public TimeSpan Offset { get; } + public TimeSpan Offset { get; } = offset; /// /// Duration of time for which the caption is displayed. /// - public TimeSpan Duration { get; } + public TimeSpan Duration { get; } = duration; /// /// Caption parts, usually representing individual words. @@ -31,23 +36,7 @@ public class ClosedCaption /// /// May be empty because not all captions have parts. /// - public IReadOnlyList Parts { get; } - - /// - /// Initializes an instance of . - /// - public ClosedCaption( - string text, - TimeSpan offset, - TimeSpan duration, - IReadOnlyList parts - ) - { - Text = text; - Offset = offset; - Duration = duration; - Parts = parts; - } + public IReadOnlyList Parts { get; } = parts; /// /// Gets the caption part displayed at the specified point in time, relative to the caption's own offset. diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionClient.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionClient.cs index bb5e32e6..d267144d 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionClient.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionClient.cs @@ -15,14 +15,9 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Operations related to closed captions of YouTube videos. /// -public class ClosedCaptionClient +public class ClosedCaptionClient(HttpClient http) { - private readonly ClosedCaptionController _controller; - - /// - /// Initializes an instance of . - /// - public ClosedCaptionClient(HttpClient http) => _controller = new ClosedCaptionController(http); + private readonly ClosedCaptionController _controller = new(http); private async IAsyncEnumerable GetClosedCaptionTrackInfosAsync( VideoId videoId, diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionManifest.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionManifest.cs index cd9f3521..1e2ed660 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionManifest.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionManifest.cs @@ -7,17 +7,12 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Describes closed caption tracks available for a YouTube video. /// -public class ClosedCaptionManifest +public class ClosedCaptionManifest(IReadOnlyList tracks) { /// /// Available closed caption tracks. /// - public IReadOnlyList Tracks { get; } - - /// - /// Initializes an instance of . - /// - public ClosedCaptionManifest(IReadOnlyList tracks) => Tracks = tracks; + public IReadOnlyList Tracks { get; } = tracks; /// /// Gets the closed caption track in the specified language (identified by ISO-639-1 code or display name). diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionPart.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionPart.cs index 31091e98..6e54c92d 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionPart.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionPart.cs @@ -1,31 +1,23 @@ using System; using System.Diagnostics.CodeAnalysis; +using AngleSharp.Media.Dom; namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Individual closed caption part contained within a track. /// -public class ClosedCaptionPart +public class ClosedCaptionPart(string text, TimeSpan offset) { /// /// Text displayed by the caption part. /// - public string Text { get; } + public string Text { get; } = text; /// /// Time at which the caption part starts displaying, relative to the caption's own offset. /// - public TimeSpan Offset { get; } - - /// - /// Initializes an instance of . - /// - public ClosedCaptionPart(string text, TimeSpan offset) - { - Text = text; - Offset = offset; - } + public TimeSpan Offset { get; } = offset; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrack.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrack.cs index 28319502..57966cd9 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrack.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrack.cs @@ -7,20 +7,12 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Contains closed captions in a specific language. /// -public class ClosedCaptionTrack +public class ClosedCaptionTrack(IReadOnlyList captions) { /// /// Closed captions included in the track. /// - public IReadOnlyList Captions { get; } - - /// - /// Initializes an instance of . - /// - public ClosedCaptionTrack(IReadOnlyList captions) - { - Captions = captions; - } + public IReadOnlyList Captions { get; } = captions; /// /// Gets the caption displayed at the specified point in time. diff --git a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrackInfo.cs b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrackInfo.cs index 7802365a..c7120400 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrackInfo.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/ClosedCaptionTrackInfo.cs @@ -5,32 +5,22 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Metadata associated with a closed caption track of a YouTube video. /// -public class ClosedCaptionTrackInfo +public class ClosedCaptionTrackInfo(string url, Language language, bool isAutoGenerated) { /// /// Track URL. /// - public string Url { get; } + public string Url { get; } = url; /// /// Track language. /// - public Language Language { get; } + public Language Language { get; } = language; /// /// Whether the track was automatically generated. /// - public bool IsAutoGenerated { get; } - - /// - /// Initializes an instance of . - /// - public ClosedCaptionTrackInfo(string url, Language language, bool isAutoGenerated) - { - Url = url; - Language = language; - IsAutoGenerated = isAutoGenerated; - } + public bool IsAutoGenerated { get; } = isAutoGenerated; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/ClosedCaptions/Language.cs b/YoutubeExplode/Videos/ClosedCaptions/Language.cs index 7f05b4cc..4d25af38 100644 --- a/YoutubeExplode/Videos/ClosedCaptions/Language.cs +++ b/YoutubeExplode/Videos/ClosedCaptions/Language.cs @@ -6,27 +6,18 @@ namespace YoutubeExplode.Videos.ClosedCaptions; /// /// Language information. /// -public readonly partial struct Language +public readonly partial struct Language(string code, string name) { /// /// Two-letter or three-letter language code, possibly with a regional identifier /// (e.g. 'en' or 'en-US' or 'eng'). /// - public string Code { get; } + public string Code { get; } = code; /// /// Full international name of the language. /// - public string Name { get; } - - /// - /// Initializes an instance of . - /// - public Language(string code, string name) - { - Code = code; - Name = name; - } + public string Name { get; } = name; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/Engagement.cs b/YoutubeExplode/Videos/Engagement.cs index 75b89446..08da2a1c 100644 --- a/YoutubeExplode/Videos/Engagement.cs +++ b/YoutubeExplode/Videos/Engagement.cs @@ -5,17 +5,17 @@ namespace YoutubeExplode.Videos; /// /// Engagement statistics. /// -public class Engagement +public class Engagement(long viewCount, long likeCount, long dislikeCount) { /// /// View count. /// - public long ViewCount { get; } + public long ViewCount { get; } = viewCount; /// /// Like count. /// - public long LikeCount { get; } + public long LikeCount { get; } = likeCount; /// /// Dislike count. @@ -23,7 +23,7 @@ public class Engagement /// /// YouTube no longer shows dislikes, so this value is always 0. /// - public long DislikeCount { get; } + public long DislikeCount { get; } = dislikeCount; /// /// Average rating. @@ -34,16 +34,6 @@ public class Engagement public double AverageRating => LikeCount + DislikeCount != 0 ? 1 + 4.0 * LikeCount / (LikeCount + DislikeCount) : 0; // avoid division by 0 - /// - /// Initializes an instance of . - /// - public Engagement(long viewCount, long likeCount, long dislikeCount) - { - ViewCount = viewCount; - LikeCount = likeCount; - DislikeCount = dislikeCount; - } - /// [ExcludeFromCodeCoverage] public override string ToString() => $"Rating: {AverageRating:N1}"; diff --git a/YoutubeExplode/Videos/Streams/AudioOnlyStreamInfo.cs b/YoutubeExplode/Videos/Streams/AudioOnlyStreamInfo.cs index 1346d2a1..59cb8e55 100644 --- a/YoutubeExplode/Videos/Streams/AudioOnlyStreamInfo.cs +++ b/YoutubeExplode/Videos/Streams/AudioOnlyStreamInfo.cs @@ -5,40 +5,28 @@ namespace YoutubeExplode.Videos.Streams; /// /// Metadata associated with an audio-only YouTube media stream. /// -public class AudioOnlyStreamInfo : IAudioStreamInfo +public class AudioOnlyStreamInfo( + string url, + Container container, + FileSize size, + Bitrate bitrate, + string audioCodec +) : IAudioStreamInfo { /// - public string Url { get; } + public string Url { get; } = url; /// - public Container Container { get; } + public Container Container { get; } = container; /// - public FileSize Size { get; } + public FileSize Size { get; } = size; /// - public Bitrate Bitrate { get; } + public Bitrate Bitrate { get; } = bitrate; /// - public string AudioCodec { get; } - - /// - /// Initializes an instance of . - /// - public AudioOnlyStreamInfo( - string url, - Container container, - FileSize size, - Bitrate bitrate, - string audioCodec - ) - { - Url = url; - Container = container; - Size = size; - Bitrate = bitrate; - AudioCodec = audioCodec; - } + public string AudioCodec { get; } = audioCodec; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/Streams/Bitrate.cs b/YoutubeExplode/Videos/Streams/Bitrate.cs index 50f6a6f7..54d2fc0b 100644 --- a/YoutubeExplode/Videos/Streams/Bitrate.cs +++ b/YoutubeExplode/Videos/Streams/Bitrate.cs @@ -5,12 +5,12 @@ namespace YoutubeExplode.Videos.Streams; /// /// Bitrate. /// -public readonly partial struct Bitrate +public readonly partial struct Bitrate(long bitsPerSecond) { /// /// Bitrate in bits per second. /// - public long BitsPerSecond { get; } + public long BitsPerSecond { get; } = bitsPerSecond; /// /// Bitrate in kilobits per second. @@ -27,11 +27,6 @@ public readonly partial struct Bitrate /// public double GigaBitsPerSecond => MegaBitsPerSecond / 1024.0; - /// - /// Initializes an instance of . - /// - public Bitrate(long bitsPerSecond) => BitsPerSecond = bitsPerSecond; - private string GetLargestWholeNumberSymbol() { if (Math.Abs(GigaBitsPerSecond) >= 1) diff --git a/YoutubeExplode/Videos/Streams/Container.cs b/YoutubeExplode/Videos/Streams/Container.cs index 52a8e02a..10cef6fe 100644 --- a/YoutubeExplode/Videos/Streams/Container.cs +++ b/YoutubeExplode/Videos/Streams/Container.cs @@ -5,13 +5,13 @@ namespace YoutubeExplode.Videos.Streams; /// /// Stream container. /// -public readonly partial struct Container +public readonly partial struct Container(string name) { /// /// Container name (e.g. mp4, webm, etc). /// Can be used as file extension. /// - public string Name { get; } + public string Name { get; } = name; /// /// Whether this container is a known audio-only container. @@ -30,11 +30,6 @@ public readonly partial struct Container || string.Equals(Name, "aac", StringComparison.OrdinalIgnoreCase) || string.Equals(Name, "opus", StringComparison.OrdinalIgnoreCase); - /// - /// Initializes an instance of . - /// - public Container(string name) => Name = name; - /// public override string ToString() => Name; } diff --git a/YoutubeExplode/Videos/Streams/FileSize.cs b/YoutubeExplode/Videos/Streams/FileSize.cs index d0086284..7d236529 100644 --- a/YoutubeExplode/Videos/Streams/FileSize.cs +++ b/YoutubeExplode/Videos/Streams/FileSize.cs @@ -6,12 +6,12 @@ namespace YoutubeExplode.Videos.Streams; /// File size. /// // Loosely based on https://github.com/omar/ByteSize (MIT license) -public readonly partial struct FileSize +public readonly partial struct FileSize(long bytes) { /// /// Size in bytes. /// - public long Bytes { get; } + public long Bytes { get; } = bytes; /// /// Size in kilobytes. @@ -28,11 +28,6 @@ public readonly partial struct FileSize /// public double GigaBytes => MegaBytes / 1024.0; - /// - /// Initializes an instance of . - /// - public FileSize(long bytes) => Bytes = bytes; - private string GetLargestWholeNumberSymbol() { if (Math.Abs(GigaBytes) >= 1) diff --git a/YoutubeExplode/Videos/Streams/MuxedStreamInfo.cs b/YoutubeExplode/Videos/Streams/MuxedStreamInfo.cs index a07358c0..0983038b 100644 --- a/YoutubeExplode/Videos/Streams/MuxedStreamInfo.cs +++ b/YoutubeExplode/Videos/Streams/MuxedStreamInfo.cs @@ -6,55 +6,40 @@ namespace YoutubeExplode.Videos.Streams; /// /// Metadata associated with a muxed (audio + video combined) media stream. /// -public class MuxedStreamInfo : IAudioStreamInfo, IVideoStreamInfo +public class MuxedStreamInfo( + string url, + Container container, + FileSize size, + Bitrate bitrate, + string audioCodec, + string videoCodec, + VideoQuality videoQuality, + Resolution videoResolution +) : IAudioStreamInfo, IVideoStreamInfo { /// - public string Url { get; } + public string Url { get; } = url; /// - public Container Container { get; } + public Container Container { get; } = container; /// - public FileSize Size { get; } + public FileSize Size { get; } = size; /// - public Bitrate Bitrate { get; } + public Bitrate Bitrate { get; } = bitrate; /// - public string AudioCodec { get; } + public string AudioCodec { get; } = audioCodec; /// - public string VideoCodec { get; } + public string VideoCodec { get; } = videoCodec; /// - public VideoQuality VideoQuality { get; } + public VideoQuality VideoQuality { get; } = videoQuality; /// - public Resolution VideoResolution { get; } - - /// - /// Initializes an instance of . - /// - public MuxedStreamInfo( - string url, - Container container, - FileSize size, - Bitrate bitrate, - string audioCodec, - string videoCodec, - VideoQuality videoQuality, - Resolution resolution - ) - { - Url = url; - Container = container; - Size = size; - Bitrate = bitrate; - AudioCodec = audioCodec; - VideoCodec = videoCodec; - VideoQuality = videoQuality; - VideoResolution = resolution; - } + public Resolution VideoResolution { get; } = videoResolution; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/Streams/StreamClient.cs b/YoutubeExplode/Videos/Streams/StreamClient.cs index e27a7e76..d6db8c58 100644 --- a/YoutubeExplode/Videos/Streams/StreamClient.cs +++ b/YoutubeExplode/Videos/Streams/StreamClient.cs @@ -19,24 +19,14 @@ namespace YoutubeExplode.Videos.Streams; /// /// Operations related to media streams of YouTube videos. /// -public class StreamClient +public class StreamClient(HttpClient http) { - private readonly HttpClient _http; - private readonly StreamController _controller; + private readonly StreamController _controller = new(http); // Because we determine the player version ourselves, it's safe to cache the cipher manifest // for the entire lifetime of the client. private CipherManifest? _cipherManifest; - /// - /// Initializes an instance of . - /// - public StreamClient(HttpClient http) - { - _http = http; - _controller = new StreamController(http); - } - private async ValueTask ResolveCipherManifestAsync( CancellationToken cancellationToken ) @@ -63,7 +53,7 @@ CancellationToken cancellationToken // sending a HEAD request and parsing the Content-Length header. if (contentLength is null) { - using var response = await _http.HeadAsync(url, cancellationToken); + using var response = await http.HeadAsync(url, cancellationToken); contentLength = response.Content.Headers.ContentLength; // 404 error indicates that the stream is not available @@ -77,7 +67,7 @@ CancellationToken cancellationToken { // Streams may have mismatched content length, so ensure that the obtained value is correct // https://github.com/Tyrrrz/YoutubeExplode/issues/759 - using var response = await _http.GetAsync( + using var response = await http.GetAsync( // Try to access the last byte of the stream MediaStream.GetSegmentUrl(url, contentLength.Value - 2, contentLength.Value - 1), HttpCompletionOption.ResponseHeadersRead, @@ -341,7 +331,7 @@ public async ValueTask GetAsync( CancellationToken cancellationToken = default ) { - var stream = new MediaStream(_http, streamInfo); + var stream = new MediaStream(http, streamInfo); await stream.InitializeAsync(cancellationToken); return stream; diff --git a/YoutubeExplode/Videos/Streams/StreamManifest.cs b/YoutubeExplode/Videos/Streams/StreamManifest.cs index 7cb12d6e..d0a72f21 100644 --- a/YoutubeExplode/Videos/Streams/StreamManifest.cs +++ b/YoutubeExplode/Videos/Streams/StreamManifest.cs @@ -6,20 +6,12 @@ namespace YoutubeExplode.Videos.Streams; /// /// Describes media streams available for a YouTube video. /// -public class StreamManifest +public class StreamManifest(IReadOnlyList streams) { /// /// Available streams. /// - public IReadOnlyList Streams { get; } - - /// - /// Initializes an instance of . - /// - public StreamManifest(IReadOnlyList streams) - { - Streams = streams; - } + public IReadOnlyList Streams { get; } = streams; /// /// Gets streams that contain audio (i.e. muxed and audio-only streams). diff --git a/YoutubeExplode/Videos/Streams/VideoOnlyStreamInfo.cs b/YoutubeExplode/Videos/Streams/VideoOnlyStreamInfo.cs index 487d793b..b96a43f7 100644 --- a/YoutubeExplode/Videos/Streams/VideoOnlyStreamInfo.cs +++ b/YoutubeExplode/Videos/Streams/VideoOnlyStreamInfo.cs @@ -6,50 +6,36 @@ namespace YoutubeExplode.Videos.Streams; /// /// Metadata associated with a video-only media stream. /// -public class VideoOnlyStreamInfo : IVideoStreamInfo +public class VideoOnlyStreamInfo( + string url, + Container container, + FileSize size, + Bitrate bitrate, + string videoCodec, + VideoQuality videoQuality, + Resolution videoResolution +) : IVideoStreamInfo { /// - public string Url { get; } + public string Url { get; } = url; /// - public Container Container { get; } + public Container Container { get; } = container; /// - public FileSize Size { get; } + public FileSize Size { get; } = size; /// - public Bitrate Bitrate { get; } + public Bitrate Bitrate { get; } = bitrate; /// - public string VideoCodec { get; } + public string VideoCodec { get; } = videoCodec; /// - public VideoQuality VideoQuality { get; } + public VideoQuality VideoQuality { get; } = videoQuality; /// - public Resolution VideoResolution { get; } - - /// - /// Initializes an instance of . - /// - public VideoOnlyStreamInfo( - string url, - Container container, - FileSize size, - Bitrate bitrate, - string videoCodec, - VideoQuality videoQuality, - Resolution videoResolution - ) - { - Url = url; - Container = container; - Size = size; - Bitrate = bitrate; - VideoCodec = videoCodec; - VideoQuality = videoQuality; - VideoResolution = videoResolution; - } + public Resolution VideoResolution { get; } = videoResolution; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/Streams/VideoQuality.cs b/YoutubeExplode/Videos/Streams/VideoQuality.cs index fcf3bbd4..f52b875d 100644 --- a/YoutubeExplode/Videos/Streams/VideoQuality.cs +++ b/YoutubeExplode/Videos/Streams/VideoQuality.cs @@ -8,45 +8,35 @@ namespace YoutubeExplode.Videos.Streams; /// /// Video stream quality. /// -public readonly partial struct VideoQuality +public readonly partial struct VideoQuality(string label, int maxHeight, int framerate) { + /// + /// Initializes an instance of . + /// + public VideoQuality(int maxHeight, int framerate) + : this(FormatLabel(maxHeight, framerate), maxHeight, framerate) { } + /// /// Quality label, as seen on YouTube (e.g. 1080p, 720p60, etc). /// - public string Label { get; } + public string Label { get; } = label; /// /// Maximum video height allowed by this quality (e.g. 1080 for 1080p60). /// Actual video height may be lower in some cases. /// - public int MaxHeight { get; } + public int MaxHeight { get; } = maxHeight; /// /// Video framerate, measured in frames per second. /// - public int Framerate { get; } + public int Framerate { get; } = framerate; /// /// Whether this is a high definition video (i.e. 1080p or above). /// public bool IsHighDefinition => MaxHeight >= 1080; - /// - /// Initializes an instance of . - /// - public VideoQuality(string label, int maxHeight, int framerate) - { - Label = label; - MaxHeight = maxHeight; - Framerate = framerate; - } - - /// - /// Initializes an instance of . - /// - public VideoQuality(int maxHeight, int framerate) - : this(FormatLabel(maxHeight, framerate), maxHeight, framerate) { } - internal Resolution GetDefaultVideoResolution() => MaxHeight switch { diff --git a/YoutubeExplode/Videos/Video.cs b/YoutubeExplode/Videos/Video.cs index b2661f31..04734623 100644 --- a/YoutubeExplode/Videos/Video.cs +++ b/YoutubeExplode/Videos/Video.cs @@ -8,71 +8,55 @@ namespace YoutubeExplode.Videos; /// /// Metadata associated with a YouTube video. /// -public class Video : IVideo +public class Video( + VideoId id, + string title, + Author author, + DateTimeOffset uploadDate, + string description, + TimeSpan? duration, + IReadOnlyList thumbnails, + IReadOnlyList keywords, + Engagement engagement +) : IVideo { /// - public VideoId Id { get; } + public VideoId Id { get; } = id; /// public string Url => $"https://www.youtube.com/watch?v={Id}"; /// - public string Title { get; } + public string Title { get; } = title; /// - public Author Author { get; } + public Author Author { get; } = author; /// /// Video upload date. /// - public DateTimeOffset UploadDate { get; } + public DateTimeOffset UploadDate { get; } = uploadDate; /// /// Video description. /// - public string Description { get; } + public string Description { get; } = description; /// - public TimeSpan? Duration { get; } + public TimeSpan? Duration { get; } = duration; /// - public IReadOnlyList Thumbnails { get; } + public IReadOnlyList Thumbnails { get; } = thumbnails; /// /// Available search keywords for the video. /// - public IReadOnlyList Keywords { get; } + public IReadOnlyList Keywords { get; } = keywords; /// /// Engagement statistics for the video. /// - public Engagement Engagement { get; } - - /// - /// Initializes an instance of . - /// - public Video( - VideoId id, - string title, - Author author, - DateTimeOffset uploadDate, - string description, - TimeSpan? duration, - IReadOnlyList thumbnails, - IReadOnlyList keywords, - Engagement engagement - ) - { - Id = id; - Title = title; - Author = author; - UploadDate = uploadDate; - Description = description; - Duration = duration; - Thumbnails = thumbnails; - Keywords = keywords; - Engagement = engagement; - } + public Engagement Engagement { get; } = engagement; /// [ExcludeFromCodeCoverage] diff --git a/YoutubeExplode/Videos/VideoClient.cs b/YoutubeExplode/Videos/VideoClient.cs index 46e9059e..b4063101 100644 --- a/YoutubeExplode/Videos/VideoClient.cs +++ b/YoutubeExplode/Videos/VideoClient.cs @@ -12,30 +12,19 @@ namespace YoutubeExplode.Videos; /// /// Operations related to YouTube videos. /// -public class VideoClient +public class VideoClient(HttpClient http) { - private readonly VideoController _controller; + private readonly VideoController _controller = new(http); /// /// Operations related to media streams of YouTube videos. /// - public StreamClient Streams { get; } + public StreamClient Streams { get; } = new(http); /// /// Operations related to closed captions of YouTube videos. /// - public ClosedCaptionClient ClosedCaptions { get; } - - /// - /// Initializes an instance of . - /// - public VideoClient(HttpClient http) - { - _controller = new VideoController(http); - - Streams = new StreamClient(http); - ClosedCaptions = new ClosedCaptionClient(http); - } + public ClosedCaptionClient ClosedCaptions { get; } = new(http); /// /// Gets the metadata associated with the specified video.