2024-12-06 21:47:04 +02:00

85 lines
2.8 KiB
C#

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