updated dependencies
This commit is contained in:
parent
24c1868e6b
commit
5695b2287c
@ -1,44 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using DTLib.Extensions;
|
|
||||||
|
|
||||||
namespace VkAudioDownloader.CLI;
|
|
||||||
|
|
||||||
public class LaunchArgument
|
|
||||||
{
|
|
||||||
public string[] Aliases;
|
|
||||||
public string Description;
|
|
||||||
public string? ParamName;
|
|
||||||
public Action? Handler;
|
|
||||||
public Action<string>? HandlerWithArg;
|
|
||||||
|
|
||||||
private LaunchArgument(string[] aliases, string description)
|
|
||||||
{
|
|
||||||
Aliases = aliases;
|
|
||||||
Description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LaunchArgument(string[] aliases, string description, Action handler)
|
|
||||||
: this(aliases, description) => Handler = handler;
|
|
||||||
|
|
||||||
public LaunchArgument(string[] aliases, string description, Action<string> handler, string paramName)
|
|
||||||
: this(aliases, description)
|
|
||||||
{
|
|
||||||
HandlerWithArg = handler;
|
|
||||||
ParamName = paramName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringBuilder AppendHelpInfo(StringBuilder b)
|
|
||||||
{
|
|
||||||
b.Append(Aliases[0]);
|
|
||||||
for (int i = 1; i < Aliases.Length; i++)
|
|
||||||
b.Append(", ").Append(Aliases[i]);
|
|
||||||
if (!String.IsNullOrEmpty(ParamName))
|
|
||||||
b.Append(" [").Append(ParamName).Append(']');
|
|
||||||
b.Append(" - ").Append(Description);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() =>
|
|
||||||
$"{{{{{Aliases.MergeToString(", ")}}}, Handler: {Handler is null}, HandlerWithArg: {HandlerWithArg is null}}}";
|
|
||||||
}
|
|
||||||
@ -1,114 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace VkAudioDownloader.CLI;
|
|
||||||
|
|
||||||
public class LaunchArgumentParser
|
|
||||||
{
|
|
||||||
private Dictionary<string, LaunchArgument> argDict = new();
|
|
||||||
private List<LaunchArgument> argList = new();
|
|
||||||
public bool ExitIfNoArgs = true;
|
|
||||||
|
|
||||||
public class ExitAfterHelpException : Exception
|
|
||||||
{
|
|
||||||
internal ExitAfterHelpException() : base("your program can use this exception to exit after displaying help message")
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CreateHelpMessage()
|
|
||||||
{
|
|
||||||
StringBuilder b = new();
|
|
||||||
foreach (var arg in argList)
|
|
||||||
arg.AppendHelpInfo(b).Append('\n');
|
|
||||||
b.Remove(b.Length-1, 1);
|
|
||||||
return b.ToString();
|
|
||||||
}
|
|
||||||
public string CreateHelpArgMessage(string argAlias)
|
|
||||||
{
|
|
||||||
StringBuilder b = new();
|
|
||||||
var arg = Get(argAlias);
|
|
||||||
arg.AppendHelpInfo(b);
|
|
||||||
return b.ToString();
|
|
||||||
}
|
|
||||||
private void HelpHandler()
|
|
||||||
{
|
|
||||||
Console.WriteLine(CreateHelpMessage());
|
|
||||||
throw new ExitAfterHelpException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HelpArgHandler(string argAlias)
|
|
||||||
{
|
|
||||||
Console.WriteLine(CreateHelpArgMessage(argAlias));
|
|
||||||
throw new ExitAfterHelpException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public LaunchArgumentParser()
|
|
||||||
{
|
|
||||||
var help = new LaunchArgument(new[] { "h", "help" },
|
|
||||||
"shows help message", HelpHandler);
|
|
||||||
Add(help);
|
|
||||||
var helpArg = new LaunchArgument( new[]{ "ha", "helparg" },
|
|
||||||
"shows help message for particular argument",
|
|
||||||
HelpArgHandler, "argAlias");
|
|
||||||
Add(helpArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LaunchArgumentParser(ICollection<LaunchArgument> arguments) : this()
|
|
||||||
{
|
|
||||||
foreach (var arg in arguments)
|
|
||||||
Add(arg);
|
|
||||||
}
|
|
||||||
public LaunchArgumentParser(params LaunchArgument[] arguments) : this()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < arguments.Length; i++)
|
|
||||||
Add(arguments[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(LaunchArgument arg)
|
|
||||||
{
|
|
||||||
argList.Add(arg);
|
|
||||||
for(int a=0; a<arg.Aliases.Length; a++)
|
|
||||||
argDict.Add(arg.Aliases[a], arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LaunchArgument Get(string argAlias)
|
|
||||||
{
|
|
||||||
// different argument providing patterns
|
|
||||||
if (!argDict.TryGetValue(argAlias, out var arg) && // arg
|
|
||||||
!(argAlias.StartsWith("--") && argDict.TryGetValue(argAlias.Substring(2), out arg)) && // --arg
|
|
||||||
!(argAlias.StartsWith('-') && argDict.TryGetValue(argAlias.Substring(1), out arg)) && // -arg
|
|
||||||
!(argAlias.StartsWith('/') && argDict.TryGetValue(argAlias.Substring(1), out arg))) // /arg
|
|
||||||
throw new Exception($"invalid argument: {argAlias}\n{CreateHelpMessage()}");
|
|
||||||
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <param name="args">program launch args</param>
|
|
||||||
/// <exception cref="Exception">argument {args[i]} should have a parameter after it</exception>
|
|
||||||
/// <exception cref="NullReferenceException">argument hasn't got any handlers</exception>
|
|
||||||
/// <exception cref="ExitAfterHelpException">happens after help message is displayed</exception>
|
|
||||||
public void ParseAndHandle(string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 0 && ExitIfNoArgs)
|
|
||||||
{
|
|
||||||
HelpHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
LaunchArgument arg = Get(args[i]);
|
|
||||||
|
|
||||||
if (arg.HandlerWithArg is not null)
|
|
||||||
{
|
|
||||||
if (i+1 >= args.Length)
|
|
||||||
throw new Exception($"argument <{args[i]}> should have a parameter after it");
|
|
||||||
arg.HandlerWithArg(args[++i]);
|
|
||||||
}
|
|
||||||
else if (arg.Handler is not null)
|
|
||||||
arg.Handler();
|
|
||||||
else throw new NullReferenceException($"argument <{args[i]}> hasn't got any handlers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DTLib.Dtsod;
|
using DTLib.Dtsod;
|
||||||
using System.IO;
|
using DTLib.Console;
|
||||||
using DTLib.Extensions;
|
using DTLib.Extensions;
|
||||||
|
using DTLib.Filesystem;
|
||||||
|
using DTLib.Logging;
|
||||||
using VkAudioDownloader;
|
using VkAudioDownloader;
|
||||||
using DTLib.Logging.New;
|
|
||||||
using VkAudioDownloader.CLI;
|
|
||||||
|
|
||||||
Console.InputEncoding = StringConverter.UTF8;
|
Console.InputEncoding = StringConverter.UTF8;
|
||||||
Console.OutputEncoding = StringConverter.UTF8;
|
Console.OutputEncoding = StringConverter.UTF8;
|
||||||
@ -14,7 +14,7 @@ LaunchArgumentParser argParser = new LaunchArgumentParser();
|
|||||||
|
|
||||||
if(!File.Exists("config.dtsod"))
|
if(!File.Exists("config.dtsod"))
|
||||||
{
|
{
|
||||||
File.Copy("config.dtsod.default", "config.dtsod");
|
File.Copy("config.dtsod.default", "config.dtsod", true);
|
||||||
throw new Exception("No config detected, default created. Edit it!");
|
throw new Exception("No config detected, default created. Edit it!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ var logger = new CompositeLogger(new DefaultLogFormat(true),
|
|||||||
new ConsoleLogger(),
|
new ConsoleLogger(),
|
||||||
new FileLogger("logs", "VkAudioDownloaer"),
|
new FileLogger("logs", "VkAudioDownloaer"),
|
||||||
new FileLogger("logs", "VkAudioDownloaer_debug") { DebugLogEnabled = true});
|
new FileLogger("logs", "VkAudioDownloaer_debug") { DebugLogEnabled = true});
|
||||||
var mainLoggerContext = new ContextLogger(logger, "Main");
|
var mainLoggerContext = new ContextLogger("Main", logger);
|
||||||
mainLoggerContext.LogDebug("DEBUG LOG ENABLED");
|
mainLoggerContext.LogDebug("DEBUG LOG ENABLED");
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -54,7 +54,7 @@ try
|
|||||||
var audio = audios[ain];
|
var audio = audios[ain];
|
||||||
Console.WriteLine($"selected {audio.AudioToString()}");
|
Console.WriteLine($"selected {audio.AudioToString()}");
|
||||||
|
|
||||||
string downloadedFile = client.DownloadAudioAsync(audio, "downloads").GetAwaiter().GetResult();
|
IOPath downloadedFile = client.DownloadAudioAsync(audio, "downloads").GetAwaiter().GetResult();
|
||||||
mainLoggerContext.LogInfo($"audio {audio.AudioToString()} downloaded to {downloadedFile}");
|
mainLoggerContext.LogInfo($"audio {audio.AudioToString()} downloaded to {downloadedFile}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using VkNet.Model.Attachments;
|
using VkNet.Model;
|
||||||
|
|
||||||
namespace VkAudioDownloader;
|
namespace VkAudioDownloader;
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +1,25 @@
|
|||||||
using CliWrap;
|
using CliWrap;
|
||||||
|
using DTLib.Logging;
|
||||||
|
|
||||||
namespace VkAudioDownloader.Helpers;
|
namespace VkAudioDownloader.Helpers;
|
||||||
|
|
||||||
public class FFMPegHelper
|
public class FFMPegHelper
|
||||||
{
|
{
|
||||||
private ContextLogger _logger;
|
private ContextLogger _logger;
|
||||||
private readonly string ffmpeg;
|
private readonly IOPath ffmpeg_exe;
|
||||||
public FFMPegHelper(ILogger logger, string ffmpegDir)
|
public FFMPegHelper(ILogger logger, IOPath ffmpegDir)
|
||||||
{
|
{
|
||||||
_logger = new ContextLogger(logger, nameof(FFMPegHelper));
|
_logger = new ContextLogger(nameof(FFMPegHelper), logger);
|
||||||
ffmpeg=Path.Concat(ffmpegDir,"ffmpeg");
|
ffmpeg_exe=Path.Concat(ffmpegDir,"ffmpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>creates fragments list for ffmppeg concat</summary>
|
/// <summary>creates fragments list for ffmppeg concat</summary>
|
||||||
/// <param name="fragmentsDir">there file list.txt will be created</param>
|
/// <param name="fragmentsDir">there file list.txt will be created</param>
|
||||||
/// <param name="fragments">audio files in fragmentsDir (with or without dir in path)</param>
|
/// <param name="fragments">audio files in fragmentsDir (with or without dir in path)</param>
|
||||||
/// <returns></returns>
|
/// <returns>path to list.txt file</returns>
|
||||||
public string CreateFragmentList(string fragmentsDir, string[] fragments)
|
public IOPath CreateFragmentList(IOPath fragmentsDir, IOPath[] fragments)
|
||||||
{
|
{
|
||||||
string listFile = Path.Concat(fragmentsDir, "list.txt");
|
IOPath listFile = Path.Concat(fragmentsDir, "list.txt");
|
||||||
using var playlistFile = File.OpenWrite(listFile);
|
using var playlistFile = File.OpenWrite(listFile);
|
||||||
for (var i = 0; i < fragments.Length; i++)
|
for (var i = 0; i < fragments.Length; i++)
|
||||||
{
|
{
|
||||||
@ -33,7 +34,7 @@ public class FFMPegHelper
|
|||||||
/// <summary>converts ts files in directory to opus</summary>
|
/// <summary>converts ts files in directory to opus</summary>
|
||||||
/// <param name="localDir">directory with ts fragment files</param>
|
/// <param name="localDir">directory with ts fragment files</param>
|
||||||
/// <returns>paths to created opus files</returns>
|
/// <returns>paths to created opus files</returns>
|
||||||
public Task<string[]> ToOpus(string localDir) =>
|
public Task<IOPath[]> ToOpus(IOPath localDir) =>
|
||||||
ToOpus(Directory.GetFiles(localDir, "*.ts"));
|
ToOpus(Directory.GetFiles(localDir, "*.ts"));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -41,24 +42,24 @@ public class FFMPegHelper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fragments">ts fragment files</param>
|
/// <param name="fragments">ts fragment files</param>
|
||||||
/// <returns>paths to created opus files</returns>
|
/// <returns>paths to created opus files</returns>
|
||||||
public async Task<string[]> ToOpus(string[] fragments)
|
public async Task<IOPath[]> ToOpus(IOPath[] fragments)
|
||||||
{
|
{
|
||||||
string[] output = new string[fragments.Length];
|
IOPath[] output = new IOPath[fragments.Length];
|
||||||
var tasks = new Task<CommandResult>[fragments.Length];
|
var tasks = new Task<CommandResult>[fragments.Length];
|
||||||
|
|
||||||
for (var i = 0; i < fragments.Length; i++)
|
for (var i = 0; i < fragments.Length; i++)
|
||||||
{
|
{
|
||||||
string tsFile = fragments[i];
|
IOPath tsFile = fragments[i];
|
||||||
string opusFile = tsFile.Replace(".ts",".opus");
|
IOPath opusFile = tsFile.Replace(".ts",".opus");
|
||||||
_logger.LogDebug($"{tsFile} -> {opusFile}");
|
_logger.LogDebug($"{tsFile} -> {opusFile}");
|
||||||
var command = Cli.Wrap(ffmpeg).WithArguments(new[]
|
var command = Cli.Wrap(ffmpeg_exe.Str).WithArguments(new[]
|
||||||
{
|
{
|
||||||
"-i", tsFile, // input
|
"-i", tsFile.Str, // input
|
||||||
"-loglevel", "warning", "-hide_banner", "-nostats", // print only warnings and errors
|
"-loglevel", "warning", "-hide_banner", "-nostats", // print only warnings and errors
|
||||||
"-map", "0:0", // select first audio track (sometimes there are blank buggy second thack)
|
"-map", "0:0", // select first audio track (sometimes there are blank buggy second thack)
|
||||||
"-filter:a", "asetpts=PTS-STARTPTS", // fixes pts
|
"-filter:a", "asetpts=PTS-STARTPTS", // fixes pts
|
||||||
"-c", "libopus", "-b:a", "96k", // encoding params
|
"-c", "libopus", "-b:a", "96k", // encoding params
|
||||||
opusFile // output
|
opusFile.Str // output
|
||||||
})
|
})
|
||||||
// ffmpeg prints all log to stderr, because in stdout it ptints encoded file
|
// ffmpeg prints all log to stderr, because in stdout it ptints encoded file
|
||||||
.WithStandardErrorPipe(PipeTarget.ToDelegate(StdErrHandle));
|
.WithStandardErrorPipe(PipeTarget.ToDelegate(StdErrHandle));
|
||||||
@ -78,17 +79,17 @@ public class FFMPegHelper
|
|||||||
else _logger.LogWarn(msg);
|
else _logger.LogWarn(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Concat(string outfile, string fragmentListFile, string codec="libopus")
|
public async Task Concat(IOPath outfile, IOPath fragmentListFile, string codec="libopus")
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"{fragmentListFile} -> {outfile}");
|
_logger.LogDebug($"{fragmentListFile} -> {outfile}");
|
||||||
var command = Cli.Wrap(ffmpeg).WithArguments(new[]
|
var command = Cli.Wrap(ffmpeg_exe.Str).WithArguments(new[]
|
||||||
{
|
{
|
||||||
"-f", "concat", // mode
|
"-f", "concat", // mode
|
||||||
"-i", fragmentListFile, // input list
|
"-i", fragmentListFile.Str, // input list
|
||||||
"-loglevel", "warning", "-hide_banner", "-nostats", // print only warnings and errors
|
"-loglevel", "warning", "-hide_banner", "-nostats", // print only warnings and errors
|
||||||
"-filter:a", "asetpts=PTS-STARTPTS", // fixes pts
|
"-filter:a", "asetpts=PTS-STARTPTS", // fixes pts
|
||||||
"-c", codec, "-b:a", "96k", // encoding params
|
"-c", codec, "-b:a", "96k", // encoding params
|
||||||
outfile, "-y" // output override
|
outfile.Str, "-y" // output override
|
||||||
})
|
})
|
||||||
// ffmpeg prints all log to stderr, because in stdout it ptints encoded file
|
// ffmpeg prints all log to stderr, because in stdout it ptints encoded file
|
||||||
.WithStandardErrorPipe(PipeTarget.ToDelegate(
|
.WithStandardErrorPipe(PipeTarget.ToDelegate(
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class HttpHelper : HttpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task DownloadAsync(HLSFragment fragment, string localDir) =>
|
public async Task DownloadAsync(HLSFragment fragment, string localDir) =>
|
||||||
await WriteStreamAsync(await GetStreamAsync(fragment), Path.Concat(localDir, fragment.Name));
|
await WriteStreamAsync(await GetStreamAsync(fragment), Path.Concat(localDir, fragment.Name).ToString()!);
|
||||||
|
|
||||||
public async Task DownloadAsync(HLSPlaylist playlist, string localDir)
|
public async Task DownloadAsync(HLSPlaylist playlist, string localDir)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,10 +20,10 @@
|
|||||||
|
|
||||||
<!--external dependencies-->
|
<!--external dependencies-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
<PackageReference Include="CliWrap" Version="3.6.4" />
|
||||||
<PackageReference Include="VkNet.AudioBypassService" Version="1.7.4" />
|
<PackageReference Include="VkNet.AudioBypassService" Version="1.7.6" />
|
||||||
<PackageReference Include="VkNet" Version="1.72.0" />
|
<PackageReference Include="VkNet" Version="1.76.0" />
|
||||||
<PackageReference Include="DTLib.Dtsod" Version="1.0.2" />
|
<PackageReference Include="DTLib.Dtsod" Version="1.3.0" />
|
||||||
<PackageReference Include="DTLib.Logging" Version="1.0.6" />
|
<PackageReference Include="DTLib.Logging" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ global using System.Threading.Tasks;
|
|||||||
global using System.Collections.Generic;
|
global using System.Collections.Generic;
|
||||||
global using DTLib.Filesystem;
|
global using DTLib.Filesystem;
|
||||||
global using DTLib.Extensions;
|
global using DTLib.Extensions;
|
||||||
global using DTLib.Logging.New;
|
using DTLib.Logging;
|
||||||
using DTLib.Logging.DependencyInjection;
|
using DTLib.Logging.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
@ -11,9 +11,7 @@ using VkAudioDownloader.Helpers;
|
|||||||
using VkNet;
|
using VkNet;
|
||||||
using VkNet.Enums.Filters;
|
using VkNet.Enums.Filters;
|
||||||
using VkNet.Model;
|
using VkNet.Model;
|
||||||
using VkNet.Model.RequestParams;
|
|
||||||
using VkNet.Utils;
|
using VkNet.Utils;
|
||||||
using VkNet.Model.Attachments;
|
|
||||||
using VkNet.AudioBypassService.Extensions;
|
using VkNet.AudioBypassService.Extensions;
|
||||||
using VkAudioDownloader.VkM3U8;
|
using VkAudioDownloader.VkM3U8;
|
||||||
|
|
||||||
@ -23,14 +21,14 @@ public class VkClient : IDisposable
|
|||||||
{
|
{
|
||||||
public VkApi Api;
|
public VkApi Api;
|
||||||
public VkClientConfig Config;
|
public VkClientConfig Config;
|
||||||
private DTLib.Logging.New.ContextLogger _logger;
|
private ContextLogger _logger;
|
||||||
public HttpHelper Http;
|
public HttpHelper Http;
|
||||||
public FFMPegHelper Ffmpeg;
|
public FFMPegHelper Ffmpeg;
|
||||||
|
|
||||||
public VkClient(VkClientConfig conf, DTLib.Logging.New.ILogger logger)
|
public VkClient(VkClientConfig conf, DTLib.Logging.ILogger logger)
|
||||||
{
|
{
|
||||||
Config = conf;
|
Config = conf;
|
||||||
_logger = new ContextLogger(logger, nameof(VkClient));
|
_logger = new ContextLogger(nameof(VkClient), logger);
|
||||||
Http = new HttpHelper();
|
Http = new HttpHelper();
|
||||||
Ffmpeg = new FFMPegHelper(logger, conf.FfmpegDir);
|
Ffmpeg = new FFMPegHelper(logger, conf.FfmpegDir);
|
||||||
var services = new ServiceCollection()
|
var services = new ServiceCollection()
|
||||||
@ -80,16 +78,16 @@ public class VkClient : IDisposable
|
|||||||
});
|
});
|
||||||
|
|
||||||
///<returns>file name</returns>
|
///<returns>file name</returns>
|
||||||
public Task<string> DownloadAudioAsync(Audio audio, string localDir) =>
|
public Task<IOPath> DownloadAudioAsync(Audio audio, string localDir) =>
|
||||||
DownloadAudioAsync(audio, localDir,TimeSpan.FromHours(1));
|
DownloadAudioAsync(audio, localDir,TimeSpan.FromHours(1));
|
||||||
|
|
||||||
///<returns>file name</returns>
|
///<returns>file name</returns>
|
||||||
public async Task<string> DownloadAudioAsync(Audio audio, string localDir, TimeSpan durationLimit)
|
public async Task<IOPath> DownloadAudioAsync(Audio audio, string localDir, TimeSpan durationLimit)
|
||||||
{
|
{
|
||||||
if (!audio.Url.ToString().StartsWith("http"))
|
if (!audio.Url.ToString().StartsWith("http"))
|
||||||
throw new Exception($"incorrect audio url: {audio.Url}");
|
throw new Exception($"incorrect audio url: {audio.Url}");
|
||||||
|
|
||||||
string outFile = Path.Concat(localDir, DTLib.Filesystem.Path.CorrectString($"{audio.Artist}-{audio.Title}.opus"));
|
IOPath outFile = Path.Concat(localDir, DTLib.Filesystem.Path.ReplaceRestrictedChars($"{audio.Artist}-{audio.Title}.opus"));
|
||||||
string fragmentDir = $"{outFile}_{DateTime.Now.Ticks}";
|
string fragmentDir = $"{outFile}_{DateTime.Now.Ticks}";
|
||||||
if(File.Exists(outFile))
|
if(File.Exists(outFile))
|
||||||
_logger.LogWarn( $"file {outFile} already exists");
|
_logger.LogWarn( $"file {outFile} already exists");
|
||||||
@ -101,8 +99,8 @@ public class VkClient : IDisposable
|
|||||||
throw new Exception($"duration limit <{durationLimit}> exceeded by track <{audio}> - <{hls.Duration}>");
|
throw new Exception($"duration limit <{durationLimit}> exceeded by track <{audio}> - <{hls.Duration}>");
|
||||||
|
|
||||||
await Http.DownloadAsync(hls, fragmentDir);
|
await Http.DownloadAsync(hls, fragmentDir);
|
||||||
string[] opusFragments = await Ffmpeg.ToOpus(fragmentDir);
|
var opusFragments = await Ffmpeg.ToOpus(fragmentDir);
|
||||||
string listFile = Ffmpeg.CreateFragmentList(fragmentDir, opusFragments);
|
IOPath listFile = Ffmpeg.CreateFragmentList(fragmentDir, opusFragments);
|
||||||
await Ffmpeg.Concat(outFile, listFile);
|
await Ffmpeg.Concat(outFile, listFile);
|
||||||
Directory.Delete(fragmentDir);
|
Directory.Delete(fragmentDir);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user