mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Rework resolve formats for Vimeo
This commit is contained in:
@@ -12,9 +12,9 @@ namespace Podsync.Services.Resolver
|
|||||||
{
|
{
|
||||||
private static readonly TimeSpan ProcessWaitTimeout = TimeSpan.FromMinutes(1);
|
private static readonly TimeSpan ProcessWaitTimeout = TimeSpan.FromMinutes(1);
|
||||||
private static readonly TimeSpan WaitTimeoutBetweenFailedCalls = TimeSpan.FromSeconds(30);
|
private static readonly TimeSpan WaitTimeoutBetweenFailedCalls = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
private const string Ytdl = "youtube-dl";
|
private const string YtdlName = "youtube-dl";
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public YtdlWrapper(IStorageService storageService, ILogger<YtdlWrapper> logger) : base(storageService)
|
public YtdlWrapper(IStorageService storageService, ILogger<YtdlWrapper> logger) : base(storageService)
|
||||||
@@ -23,7 +23,7 @@ namespace Podsync.Services.Resolver
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cmd = Command.Run(Ytdl, "--version");
|
var cmd = Command.Run(YtdlName, "--version");
|
||||||
var version = cmd.Result.StandardOutput;
|
var version = cmd.Result.StandardOutput;
|
||||||
|
|
||||||
Version = version;
|
Version = version;
|
||||||
@@ -39,48 +39,72 @@ namespace Podsync.Services.Resolver
|
|||||||
public override string Version { get; }
|
public override string Version { get; }
|
||||||
|
|
||||||
|
|
||||||
protected override async Task<Uri> ResolveInternal(Uri videoUrl, ResolveFormat resolveFormat)
|
protected override async Task<Uri> ResolveInternal(Uri videoUrl, ResolveFormat format)
|
||||||
{
|
{
|
||||||
var format = SelectFormat(resolveFormat);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await ResolveInternal(videoUrl, format);
|
return await Ytdl(videoUrl, format);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
// Give a try one more time, often it helps
|
// Give a try one more time, often it helps
|
||||||
await Task.Delay(WaitTimeoutBetweenFailedCalls);
|
await Task.Delay(WaitTimeoutBetweenFailedCalls);
|
||||||
return await ResolveInternal(videoUrl, format);
|
return await Ytdl(videoUrl, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string SelectFormat(ResolveFormat format)
|
private static IEnumerable<string> GetArguments(Uri videoUrl, ResolveFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
var host = videoUrl.Host.ToLowerInvariant();
|
||||||
{
|
|
||||||
case ResolveFormat.VideoHigh:
|
|
||||||
return "best[ext=mp4]";
|
|
||||||
case ResolveFormat.VideoLow:
|
|
||||||
return "worst[ext=mp4]";
|
|
||||||
case ResolveFormat.AudioHigh:
|
|
||||||
return "bestaudio[ext=m4a]/worstaudio[ext=m4a]";
|
|
||||||
case ResolveFormat.AudioLow:
|
|
||||||
return "worstaudio[ext=m4a]/bestaudio[ext=m4a]";
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(format), "Unsupported format", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GetArguments(Uri videoUrl, string format)
|
|
||||||
{
|
|
||||||
// Video format code, see the "FORMAT SELECTION"
|
// Video format code, see the "FORMAT SELECTION"
|
||||||
yield return "-f";
|
yield return "-f";
|
||||||
yield return format;
|
|
||||||
|
if (host.Contains("youtube.com"))
|
||||||
|
{
|
||||||
|
if (format == ResolveFormat.VideoHigh)
|
||||||
|
{
|
||||||
|
yield return "best[ext=mp4]";
|
||||||
|
}
|
||||||
|
else if (format == ResolveFormat.VideoLow)
|
||||||
|
{
|
||||||
|
yield return "worst[ext=mp4]";
|
||||||
|
}
|
||||||
|
else if (format == ResolveFormat.AudioHigh)
|
||||||
|
{
|
||||||
|
yield return "bestaudio[ext=m4a]/worstaudio[ext=m4a]";
|
||||||
|
}
|
||||||
|
else if (format == ResolveFormat.AudioLow)
|
||||||
|
{
|
||||||
|
yield return "worstaudio[ext=m4a]/bestaudio[ext=m4a]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Unsupported resolve format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (host.Contains("vimeo.com"))
|
||||||
|
{
|
||||||
|
if (format == ResolveFormat.VideoHigh)
|
||||||
|
{
|
||||||
|
yield return "Original/http-1080p/http-720p/http-360p/http-270p";
|
||||||
|
}
|
||||||
|
else if (format == ResolveFormat.VideoLow)
|
||||||
|
{
|
||||||
|
yield return "http-270p/http-360p/http-540p/http-720p/http-1080p";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Unsupported resolve format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Unsupported video provider");
|
||||||
|
}
|
||||||
|
|
||||||
// Simulate, quiet but print URL
|
// Simulate, quiet but print URL
|
||||||
yield return "-g";
|
yield return "-g";
|
||||||
yield return videoUrl.ToString();
|
|
||||||
|
|
||||||
// Do not download the video and do not write anything to disk
|
// Do not download the video and do not write anything to disk
|
||||||
yield return "-s";
|
yield return "-s";
|
||||||
@@ -90,11 +114,13 @@ namespace Podsync.Services.Resolver
|
|||||||
|
|
||||||
// Do NOT contact the youtube-dl server for debugging
|
// Do NOT contact the youtube-dl server for debugging
|
||||||
yield return "--no-call-home";
|
yield return "--no-call-home";
|
||||||
|
|
||||||
|
yield return videoUrl.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Uri> ResolveInternal(Uri videoUrl, string format)
|
private async Task<Uri> Ytdl(Uri videoUrl, ResolveFormat format)
|
||||||
{
|
{
|
||||||
var cmd = Command.Run(Ytdl, GetArguments(videoUrl, format), opts => opts.ThrowOnError().Timeout(ProcessWaitTimeout));
|
var cmd = Command.Run(YtdlName, GetArguments(videoUrl, format), opts => opts.ThrowOnError().Timeout(ProcessWaitTimeout));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@@ -57,5 +57,23 @@ namespace Podsync.Tests.Services.Resolver
|
|||||||
var downloadUrl = await _resolver.Resolve(new Uri("https://www.youtube.com/watch?v=-csRxRj_zcw&t=45s"), ResolveFormat.AudioHigh);
|
var downloadUrl = await _resolver.Resolve(new Uri("https://www.youtube.com/watch?v=-csRxRj_zcw&t=45s"), ResolveFormat.AudioHigh);
|
||||||
Assert.True(downloadUrl.IsAbsoluteUri);
|
Assert.True(downloadUrl.IsAbsoluteUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("https://vimeo.com/94747106", ResolveFormat.VideoHigh)]
|
||||||
|
[InlineData("https://vimeo.com/199203302", ResolveFormat.VideoHigh)]
|
||||||
|
[InlineData("https://vimeo.com/93003441", ResolveFormat.VideoHigh)]
|
||||||
|
[InlineData("https://vimeo.com/93003441", ResolveFormat.VideoLow)]
|
||||||
|
public async Task ResolveVimeoLinks(string link, ResolveFormat format)
|
||||||
|
{
|
||||||
|
var downloadUrl = await _resolver.Resolve(new Uri(link), format);
|
||||||
|
Assert.True(downloadUrl.IsWellFormedOriginalString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task VimeoAudioExceptionTest()
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(async () => await _resolver.Resolve(new Uri("https://vimeo.com/94747106"), ResolveFormat.AudioHigh));
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(async () => await _resolver.Resolve(new Uri("https://vimeo.com/94747106"), ResolveFormat.AudioLow));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user