From 8eee867cff5672468fcfab3d5cf5c3d57b02ed87 Mon Sep 17 00:00:00 2001 From: nilaoda Date: Fri, 26 Aug 2022 22:19:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/N_m3u8DL-RE.Common/Resource/ResString.cs | 1 + src/N_m3u8DL-RE.Common/Resource/StaticText.cs | 6 ++++ src/N_m3u8DL-RE/Column/DownloadSpeedColumn.cs | 30 +++++++++++-------- src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs | 6 ++-- src/N_m3u8DL-RE/CommandLine/MyOption.cs | 4 +++ .../DownloadManager/SimpleDownloadManager.cs | 30 ++++++++++++++----- src/N_m3u8DL-RE/Util/MergeUtil.cs | 4 +++ 7 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.cs b/src/N_m3u8DL-RE.Common/Resource/ResString.cs index 7fe79eb..ae1a685 100644 --- a/src/N_m3u8DL-RE.Common/Resource/ResString.cs +++ b/src/N_m3u8DL-RE.Common/Resource/ResString.cs @@ -48,6 +48,7 @@ namespace N_m3u8DL_RE.Common.Resource public static string cmd_uiLanguage { get => GetText("cmd_uiLanguage"); } public static string cmd_urlProcessorArgs { get => GetText("cmd_urlProcessorArgs"); } public static string cmd_useShakaPackager { get => GetText("cmd_useShakaPackager"); } + public static string cmd_concurrentDownload { get => GetText("cmd_concurrentDownload"); } public static string cmd_useMkvmerge { get => GetText("cmd_useMkvmerge"); } public static string cmd_muxAfterDone { get => GetText("cmd_muxAfterDone"); } public static string cmd_muxToMp4 { get => GetText("cmd_muxToMp4"); } diff --git a/src/N_m3u8DL-RE.Common/Resource/StaticText.cs b/src/N_m3u8DL-RE.Common/Resource/StaticText.cs index 6cb03e9..6cd0eb6 100644 --- a/src/N_m3u8DL-RE.Common/Resource/StaticText.cs +++ b/src/N_m3u8DL-RE.Common/Resource/StaticText.cs @@ -244,6 +244,12 @@ namespace N_m3u8DL_RE.Common.Resource zhTW: "混流时使用mkvmerge替代ffmpeg", enUS: "Use mkvmerge instead of ffmpeg to mux" ), + ["cmd_concurrentDownload"] = new TextContainer + ( + zhCN: "并发下载已选择的音频、视频和字幕", + zhTW: "並發下載已選擇的音訊、影片和字幕", + enUS: "Concurrently download the selected audio, video and subtitles" + ), ["cmd_muxAfterDone"] = new TextContainer ( zhCN: "所有工作完成时尝试混流分离的音视频. 你能够以:分隔形式指定如下参数:\r\n\r\n" + diff --git a/src/N_m3u8DL-RE/Column/DownloadSpeedColumn.cs b/src/N_m3u8DL-RE/Column/DownloadSpeedColumn.cs index 0fa0903..c446732 100644 --- a/src/N_m3u8DL-RE/Column/DownloadSpeedColumn.cs +++ b/src/N_m3u8DL-RE/Column/DownloadSpeedColumn.cs @@ -3,6 +3,7 @@ using N_m3u8DL_RE.Entity; using Spectre.Console; using Spectre.Console.Rendering; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,37 +13,40 @@ namespace N_m3u8DL_RE.Column { internal sealed class DownloadSpeedColumn : ProgressColumn { - private string DateTimeString = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - private string Speed = "0Bps"; + private ConcurrentDictionary DateTimeStringDic = new(); + private ConcurrentDictionary SpeedDic = new(); protected override bool NoWrap => true; - public SpeedContainer SpeedContainer { get; set; } + public ConcurrentDictionary SpeedContainerDic { get; set; } - public DownloadSpeedColumn(SpeedContainer SpeedContainer) + public DownloadSpeedColumn(ConcurrentDictionary SpeedContainerDic) { - this.SpeedContainer = SpeedContainer; + this.SpeedContainerDic = SpeedContainerDic; } public Style MyStyle { get; set; } = new Style(foreground: Color.Green); public override IRenderable Render(RenderContext context, ProgressTask task, TimeSpan deltaTime) { + var taskId = task.Id; + var speedContainer = SpeedContainerDic[taskId]; var now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var flag = task.IsFinished || !task.IsStarted; //单文件下载汇报进度 - if (!flag && SpeedContainer.SingleSegment && SpeedContainer.ResponseLength != null) + if (!flag && speedContainer.SingleSegment && speedContainer.ResponseLength != null) { - task.MaxValue = (double)SpeedContainer.ResponseLength; - task.Value = SpeedContainer.RDownloaded; + task.MaxValue = (double)speedContainer.ResponseLength; + task.Value = speedContainer.RDownloaded; } //一秒汇报一次即可 - if (DateTimeString != now) + if (DateTimeStringDic.TryGetValue(taskId, out var oldTime) && oldTime != now) { - Speed = FormatFileSize(SpeedContainer.Downloaded); - SpeedContainer.Reset(); - DateTimeString = now; + SpeedDic[taskId] = FormatFileSize(speedContainer.Downloaded); + speedContainer.Reset(); } + DateTimeStringDic[taskId] = now; var style = flag ? Style.Plain : MyStyle; - return flag ? new Text("-", style).Centered() : new Text(Speed, style).Centered(); + SpeedDic.TryGetValue(taskId, out var speed); + return flag ? new Text("-", style).Centered() : new Text(speed ?? "0Bps", style).Centered(); } private static string FormatFileSize(double fileSize) diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs index c176804..1925972 100644 --- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs +++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs @@ -42,6 +42,7 @@ namespace N_m3u8DL_RE.CommandLine private readonly static Option DecryptionBinaryPath = new(new string[] { "--decryption-binary-path" }, description: ResString.cmd_decryptionBinaryPath); private readonly static Option FFmpegBinaryPath = new(new string[] { "--ffmpeg-binary-path" }, description: ResString.cmd_ffmpegBinaryPath); private readonly static Option BaseUrl = new(new string[] { "--base-url" }, description: ResString.cmd_baseUrl); + private readonly static Option ConcurrentDownload = new(new string[] { "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false); //复杂命令行如下 private readonly static Option MuxAfterDone = new(new string[] { "-M", "--mux-after-done" }, description: ResString.cmd_muxAfterDone, parseArgument: ParseMuxAfterDone) { ArgumentHelpName = "OPTIONS" }; @@ -187,6 +188,7 @@ namespace N_m3u8DL_RE.CommandLine DownloadRetryCount = bindingContext.ParseResult.GetValueForOption(DownloadRetryCount), BaseUrl = bindingContext.ParseResult.GetValueForOption(BaseUrl), MuxImports = bindingContext.ParseResult.GetValueForOption(MuxImports), + ConcurrentDownload = bindingContext.ParseResult.GetValueForOption(ConcurrentDownload), }; @@ -218,10 +220,10 @@ namespace N_m3u8DL_RE.CommandLine public static async Task InvokeArgs(string[] args, Func action) { - var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220825") + var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220826") { Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount, - BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix, + BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix, FFmpegBinaryPath, LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption, MuxAfterDone, MuxImports diff --git a/src/N_m3u8DL-RE/CommandLine/MyOption.cs b/src/N_m3u8DL-RE/CommandLine/MyOption.cs index 13ef95f..1403f3b 100644 --- a/src/N_m3u8DL-RE/CommandLine/MyOption.cs +++ b/src/N_m3u8DL-RE/CommandLine/MyOption.cs @@ -103,6 +103,10 @@ namespace N_m3u8DL_RE.CommandLine /// public bool UseMkvmerge { get; set; } /// + /// See: . + /// + public bool ConcurrentDownload { get; set; } + /// /// See: . /// public SubtitleFormat SubtitleFormat { get; set; } diff --git a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs index 6b42ad5..957e22c 100644 --- a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs +++ b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs @@ -110,6 +110,7 @@ namespace N_m3u8DL_RE.DownloadManager } } + private async Task DownloadStreamAsync(StreamSpec streamSpec, ProgressTask task, SpeedContainer speedContainer) { speedContainer.ResetVars(); @@ -549,7 +550,7 @@ namespace N_m3u8DL_RE.DownloadManager public async Task StartDownloadAsync(IEnumerable streamSpecs) { - SpeedContainer speedContainer = new SpeedContainer(); //速度计算 + ConcurrentDictionary SpeedContainerDic = new(); //速度计算 ConcurrentDictionary Results = new(); var progress = AnsiConsole.Progress().AutoClear(true); @@ -560,7 +561,7 @@ namespace N_m3u8DL_RE.DownloadManager new TaskDescriptionColumn() { Alignment = Justify.Left }, new ProgressBarColumn(), new PercentageColumn(), - new DownloadSpeedColumn(speedContainer), //速度计算 + new DownloadSpeedColumn(SpeedContainerDic), //速度计算 new RemainingTimeColumn(), new SpinnerColumn(), }); @@ -571,14 +572,29 @@ namespace N_m3u8DL_RE.DownloadManager var dic = streamSpecs.Select(item => { var task = ctx.AddTask(item.ToShortString(), autoStart: false); + SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算 return (item, task); }).ToDictionary(item => item.item, item => item.task); - //遍历,顺序下载 - foreach (var kp in dic) + + if (!DownloaderConfig.MyOptions.ConcurrentDownload) { - var task = kp.Value; - var result = await DownloadStreamAsync(kp.Key, task, speedContainer); - Results[kp.Key] = result; + //遍历,顺序下载 + foreach (var kp in dic) + { + var task = kp.Value; + var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id]); + Results[kp.Key] = result; + } + } + else + { + //并发下载 + await Parallel.ForEachAsync(dic, async (kp, _) => + { + var task = kp.Value; + var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id]); + Results[kp.Key] = result; + }); } }); diff --git a/src/N_m3u8DL-RE/Util/MergeUtil.cs b/src/N_m3u8DL-RE/Util/MergeUtil.cs index 1dcf9e5..53ff963 100644 --- a/src/N_m3u8DL-RE/Util/MergeUtil.cs +++ b/src/N_m3u8DL-RE/Util/MergeUtil.cs @@ -238,6 +238,10 @@ namespace N_m3u8DL_RE.Util break; } } + //有的播放器不识别zho,统一转为chi + if (outputFile.LangCode == "zho") outputFile.LangCode = "chi"; + if (outputFile.LangCode == "cmn") outputFile.LangCode = "chi"; + if (outputFile.LangCode == "yue") outputFile.LangCode = "chi"; } } }