85 lines
2.8 KiB
C#
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
|
|
);
|
|
}
|
|
}
|