85 lines
2.8 KiB
C#
Raw Permalink Normal View History

2022-04-10 03:38:39 +03:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
2022-04-10 03:38:39 +03:00
using System.Threading;
using System.Threading.Tasks;
using Gress;
using YoutubeDownloader.Core.Utils;
2022-04-10 03:38:39 +03:00
using YoutubeExplode;
using YoutubeExplode.Converter;
using YoutubeExplode.Videos;
using YoutubeExplode.Videos.ClosedCaptions;
namespace YoutubeDownloader.Core.Downloading;
2023-12-10 23:57:23 +02:00
public class VideoDownloader(IReadOnlyList<Cookie>? initialCookies = null)
2022-04-10 03:38:39 +03:00
{
private readonly YoutubeClient _youtube = new(Http.Client, initialCookies ?? []);
2022-04-10 03:38:39 +03:00
public async Task<IReadOnlyList<VideoDownloadOption>> GetDownloadOptionsAsync(
VideoId videoId,
bool includeLanguageSpecificAudioStreams = true,
2023-10-21 17:58:59 +03:00
CancellationToken cancellationToken = default
)
2022-04-10 03:38:39 +03:00
{
var manifest = await _youtube.Videos.Streams.GetManifestAsync(videoId, cancellationToken);
return VideoDownloadOption.ResolveAll(manifest, includeLanguageSpecificAudioStreams);
2022-04-10 03:38:39 +03:00
}
public async Task<VideoDownloadOption> GetBestDownloadOptionAsync(
VideoId videoId,
VideoDownloadPreference preference,
bool includeLanguageSpecificAudioStreams = true,
2023-10-21 17:58:59 +03:00
CancellationToken cancellationToken = default
)
2022-04-10 03:38:39 +03:00
{
var options = await GetDownloadOptionsAsync(
videoId,
includeLanguageSpecificAudioStreams,
cancellationToken
);
2022-04-10 03:38:39 +03:00
2023-10-21 17:58:59 +03:00
return preference.TryGetBestOption(options)
?? throw new InvalidOperationException("No suitable download option found.");
2022-04-10 03:38:39 +03:00
}
2022-06-29 16:13:03 +03:00
public async Task DownloadVideoAsync(
2022-04-10 03:38:39 +03:00
string filePath,
IVideo video,
VideoDownloadOption downloadOption,
2023-12-27 16:10:14 +02:00
bool includeSubtitles = true,
2022-04-10 03:38:39 +03:00
IProgress<Percentage>? progress = null,
2023-10-21 17:58:59 +03:00
CancellationToken cancellationToken = default
)
2022-04-10 03:38:39 +03:00
{
2023-12-27 16:10:14 +02:00
// Include subtitles in the output container
2023-12-27 19:45:49 +02:00
var trackInfos = new List<ClosedCaptionTrackInfo>();
if (includeSubtitles && !downloadOption.Container.IsAudioOnly)
{
var manifest = await _youtube.Videos.ClosedCaptions.GetManifestAsync(
video.Id,
cancellationToken
);
trackInfos.AddRange(manifest.Tracks);
}
2022-04-10 03:38:39 +03:00
var dirPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrWhiteSpace(dirPath))
Directory.CreateDirectory(dirPath);
2023-12-27 19:45:49 +02:00
await _youtube.Videos.DownloadAsync(
downloadOption.StreamInfos,
trackInfos,
new ConversionRequestBuilder(filePath)
.SetFFmpegPath(FFmpeg.TryGetCliFilePath() ?? "ffmpeg")
2023-12-27 19:45:49 +02:00
.SetContainer(downloadOption.Container)
.SetPreset(ConversionPreset.Medium)
.Build(),
progress?.ToDoubleBased(),
cancellationToken
);
2022-04-10 03:38:39 +03:00
}
2023-10-21 17:58:59 +03:00
}