diff --git a/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs b/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs index 131741e..c1c2442 100644 --- a/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs +++ b/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs @@ -96,6 +96,40 @@ namespace N_m3u8DL_RE.Common.Entity return returnStr.TrimEnd().TrimEnd('|').TrimEnd(); } + public string ToShortShortString() + { + var prefixStr = ""; + var returnStr = ""; + var encStr = string.Empty; + + if (MediaType == Enum.MediaType.AUDIO) + { + prefixStr = $"[deepskyblue3]Aud[/] {encStr}"; + var d = $"{(Bandwidth != null ? (Bandwidth / 1000) + " Kbps" : "")} | {Name} | {Language} | {(Channels != null ? Channels + "CH" : "")}"; + returnStr = d.EscapeMarkup(); + } + else if (MediaType == Enum.MediaType.SUBTITLES) + { + prefixStr = $"[deepskyblue3_1]Sub[/] {encStr}"; + var d = $"{Language} | {Name} | {Codecs}"; + returnStr = d.EscapeMarkup(); + } + else + { + prefixStr = $"[aqua]Vid[/] {encStr}"; + var d = $"{Resolution} | {Bandwidth / 1000} Kbps | {FrameRate} | {VideoRange}"; + returnStr = d.EscapeMarkup(); + } + + returnStr = prefixStr + returnStr.Trim().Trim('|').Trim(); + while (returnStr.Contains("| |")) + { + returnStr = returnStr.Replace("| |", "|"); + } + + return returnStr.TrimEnd().TrimEnd('|').TrimEnd(); + } + public override string ToString() { var prefixStr = ""; diff --git a/src/N_m3u8DL-RE.Common/Log/Logger.cs b/src/N_m3u8DL-RE.Common/Log/Logger.cs index c35bdb7..77dc2e9 100644 --- a/src/N_m3u8DL-RE.Common/Log/Logger.cs +++ b/src/N_m3u8DL-RE.Common/Log/Logger.cs @@ -59,7 +59,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.INFO) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : "; + var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : "; HandleLog(write, data); } } @@ -69,7 +69,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.INFO) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : " + data; + var write = GetCurrTime() + " " + "[underline #548c26]INFO[/] : " + data; HandleLog(write); } } @@ -79,7 +79,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.DEBUG) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline grey]DEBUG[/] : "; + var write = GetCurrTime() + " " + "[underline grey]DEBUG[/]: "; HandleLog(write, data); } } @@ -89,7 +89,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.DEBUG) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline grey]DEBUG[/] : " + data; + var write = GetCurrTime() + " " + "[underline grey]DEBUG[/]: " + data; HandleLog(write); } } @@ -99,7 +99,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.WARN) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : "; + var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : "; HandleLog(write, data); } } @@ -109,7 +109,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.WARN) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : " + data; + var write = GetCurrTime() + " " + "[underline #a89022]WARN[/] : " + data; HandleLog(write); } } @@ -119,7 +119,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.ERROR) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline red1]ERROR[/] : "; + var write = GetCurrTime() + " " + "[underline red1]ERROR[/]: "; HandleLog(write, data); } } @@ -129,7 +129,7 @@ namespace N_m3u8DL_RE.Common.Log if (LogLevel >= LogLevel.ERROR) { data = ReplaceVars(data, ps); - var write = GetCurrTime() + " " + "[underline red1]ERROR[/] : " + data; + var write = GetCurrTime() + " " + "[underline red1]ERROR[/]: " + data; HandleLog(write); } } diff --git a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs index 69f2235..556bdcc 100644 --- a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs +++ b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs @@ -73,7 +73,7 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS var bytes = HTTPUtil.GetBytesAsync(segUrl, parserConfig.Headers).Result; encryptInfo.Key = bytes; } - catch (Exception _ex) + catch (Exception _ex) when (!_ex.Message.Contains("scheme is not supported.")) { Logger.WarnMarkUp($"[grey]{_ex.Message.EscapeMarkup()} retryCount: {retryCount}[/]"); Thread.Sleep(1000); diff --git a/src/N_m3u8DL-RE/Column/DownloadStatusColumn.cs b/src/N_m3u8DL-RE/Column/DownloadStatusColumn.cs new file mode 100644 index 0000000..7c22b57 --- /dev/null +++ b/src/N_m3u8DL-RE/Column/DownloadStatusColumn.cs @@ -0,0 +1,36 @@ +using N_m3u8DL_RE.Common.Util; +using Spectre.Console; +using Spectre.Console.Rendering; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace N_m3u8DL_RE.Column +{ + internal class DownloadStatusColumn : ProgressColumn + { + protected override bool NoWrap => true; + private ConcurrentDictionary DownloadedSizeDic = new(); + public Style MyStyle { get; set; } = new Style(foreground: Color.DarkCyan); + public Style FinishedStyle { get; set; } = new Style(foreground: Color.Green); + + public DownloadStatusColumn(ConcurrentDictionary downloadedSizeDic) + { + this.DownloadedSizeDic = downloadedSizeDic; + } + + public override IRenderable Render(RenderContext context, ProgressTask task, TimeSpan deltaTime) + { + var done = task.IsFinished; + var flag = DownloadedSizeDic.TryGetValue(task.Id, out var size); + var totalSize = flag ? (size / (task.Value / task.MaxValue)) : 0; + var sizeStr = size == 0 ? "" : $"{GlobalUtil.FormatFileSize(flag ? size : 0)}/{GlobalUtil.FormatFileSize(totalSize)}"; + if (done) sizeStr = GlobalUtil.FormatFileSize(totalSize); + + return new Markup(sizeStr, MyStyle).RightAligned(); + } + } +} diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs index 7920113..261b708 100644 --- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs +++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs @@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine { internal partial class CommandInvoker { - public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221202"; + public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221203"; [GeneratedRegex("((best|worst)\\d*|all)")] private static partial Regex ForStrRegex(); diff --git a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs index facc79a..073ad55 100644 --- a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs +++ b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs @@ -98,7 +98,7 @@ namespace N_m3u8DL_RE.DownloadManager } - private async Task DownloadStreamAsync(StreamSpec streamSpec, ProgressTask task, SpeedContainer speedContainer) + private async Task DownloadStreamAsync(StreamSpec streamSpec, ProgressTask task, SpeedContainer speedContainer, ConcurrentDictionary sizeDic) { speedContainer.ResetVars(); bool useAACFilter = false; //ffmpeg合并flag @@ -166,6 +166,7 @@ namespace N_m3u8DL_RE.DownloadManager } mp4InitFile = result.ActualFilePath; task.Increment(1); + sizeDic[task.Id] += result.ActualContentLength ?? 0; //读取mp4信息 if (result != null && result.Success) @@ -214,6 +215,7 @@ namespace N_m3u8DL_RE.DownloadManager throw new Exception("Download first segment failed!"); } task.Increment(1); + sizeDic[task.Id] += result.ActualContentLength ?? 0; if (result != null && result.Success) { //修复MSS init @@ -277,6 +279,7 @@ namespace N_m3u8DL_RE.DownloadManager var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers); FileDic[seg] = result; task.Increment(1); + sizeDic[task.Id] += result.ActualContentLength ?? 0; //实时解密 if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && result != null && result.Success && !string.IsNullOrEmpty(currentKID)) { @@ -630,6 +633,7 @@ namespace N_m3u8DL_RE.DownloadManager public async Task StartDownloadAsync() { + ConcurrentDictionary DownloadedSizeDic = new(); //大小计算 ConcurrentDictionary SpeedContainerDic = new(); //速度计算 ConcurrentDictionary Results = new(); @@ -639,12 +643,13 @@ namespace N_m3u8DL_RE.DownloadManager progress.Columns(new ProgressColumn[] { new TaskDescriptionColumn() { Alignment = Justify.Left }, - new ProgressBarColumn(), + new ProgressBarColumn() { Width = 30 }, new PercentageColumn(), + new DownloadStatusColumn(DownloadedSizeDic), new DownloadSpeedColumn(SpeedContainerDic), //速度计算 new RemainingTimeColumn(), new SpinnerColumn(), - }); + }) ; if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !DownloaderConfig.MyOptions.UseShakaPackager && DownloaderConfig.MyOptions.Keys != null && DownloaderConfig.MyOptions.Keys.Length > 0) @@ -655,8 +660,10 @@ namespace N_m3u8DL_RE.DownloadManager //创建任务 var dic = SelectedSteams.Select(item => { - var task = ctx.AddTask(item.ToShortString(), autoStart: false); + var description = item.ToShortShortString(); + var task = ctx.AddTask(description, autoStart: false); SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算 + DownloadedSizeDic[task.Id] = 0; //大小计算 return (item, task); }).ToDictionary(item => item.item, item => item.task); @@ -666,7 +673,7 @@ namespace N_m3u8DL_RE.DownloadManager foreach (var kp in dic) { var task = kp.Value; - var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id]); + var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id], DownloadedSizeDic); Results[kp.Key] = result; } } @@ -676,7 +683,7 @@ namespace N_m3u8DL_RE.DownloadManager await Parallel.ForEachAsync(dic, async (kp, _) => { var task = kp.Value; - var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id]); + var result = await DownloadStreamAsync(kp.Key, task, SpeedContainerDic[task.Id], DownloadedSizeDic); Results[kp.Key] = result; }); }