支持限速功能 `--max-speed` #220

This commit is contained in:
nilaoda 2023-07-30 01:43:04 +08:00
parent 9ab8f3cf72
commit eb85df8b4d
8 changed files with 57 additions and 1 deletions

View File

@ -34,6 +34,7 @@ namespace N_m3u8DL_RE.Common.Resource
public static string cmd_ffmpegBinaryPath { get => GetText("cmd_ffmpegBinaryPath"); } public static string cmd_ffmpegBinaryPath { get => GetText("cmd_ffmpegBinaryPath"); }
public static string cmd_mkvmergeBinaryPath { get => GetText("cmd_mkvmergeBinaryPath"); } public static string cmd_mkvmergeBinaryPath { get => GetText("cmd_mkvmergeBinaryPath"); }
public static string cmd_baseUrl { get => GetText("cmd_baseUrl"); } public static string cmd_baseUrl { get => GetText("cmd_baseUrl"); }
public static string cmd_maxSpeed { get => GetText("cmd_maxSpeed"); }
public static string cmd_adKeyword { get => GetText("cmd_adKeyword"); } public static string cmd_adKeyword { get => GetText("cmd_adKeyword"); }
public static string cmd_moreHelp { get => GetText("cmd_moreHelp"); } public static string cmd_moreHelp { get => GetText("cmd_moreHelp"); }
public static string cmd_header { get => GetText("cmd_header"); } public static string cmd_header { get => GetText("cmd_header"); }

View File

@ -136,6 +136,12 @@ namespace N_m3u8DL_RE.Common.Resource
zhTW: "設置BaseURL", zhTW: "設置BaseURL",
enUS: "Set BaseURL" enUS: "Set BaseURL"
), ),
["cmd_maxSpeed"] = new TextContainer
(
zhCN: "设置限速,单位支持 Mbps 或 Kbps15M 100K",
zhTW: "設置限速,單位支持 Mbps 或 Kbps15M 100K",
enUS: "Set speed limit, Mbps or Kbps, for example: 15M 100K."
),
["cmd_noDateInfo"] = new TextContainer ["cmd_noDateInfo"] = new TextContainer
( (
zhCN: "混流时不写入日期信息", zhCN: "混流时不写入日期信息",

View File

@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
{ {
internal partial class CommandInvoker internal partial class CommandInvoker
{ {
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230728"; public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230730";
[GeneratedRegex("((best|worst)\\d*|all)")] [GeneratedRegex("((best|worst)\\d*|all)")]
private static partial Regex ForStrRegex(); private static partial Regex ForStrRegex();
@ -58,6 +58,7 @@ namespace N_m3u8DL_RE.CommandLine
private readonly static Option<bool> ConcurrentDownload = new(new string[] { "-mt", "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false); private readonly static Option<bool> ConcurrentDownload = new(new string[] { "-mt", "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false);
private readonly static Option<bool> NoLog = new(new string[] { "--no-log" }, description: ResString.cmd_noLog, getDefaultValue: () => false); private readonly static Option<bool> NoLog = new(new string[] { "--no-log" }, description: ResString.cmd_noLog, getDefaultValue: () => false);
private readonly static Option<string[]?> AdKeywords = new(new string[] { "--ad-keyword" }, description: ResString.cmd_adKeyword) { ArgumentHelpName = "REG" }; private readonly static Option<string[]?> AdKeywords = new(new string[] { "--ad-keyword" }, description: ResString.cmd_adKeyword) { ArgumentHelpName = "REG" };
private readonly static Option<long?> MaxSpeed = new(new string[] { "-R", "--max-speed" }, description: ResString.cmd_maxSpeed, parseArgument: ParseSpeedLimit) { ArgumentHelpName = "SPEED" };
//代理选项 //代理选项
@ -102,6 +103,32 @@ namespace N_m3u8DL_RE.CommandLine
private readonly static Option<StreamFilter?> DropAudioFilter = new(new string[] { "-da", "--drop-audio" }, description: ResString.cmd_dropAudio, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" }; private readonly static Option<StreamFilter?> DropAudioFilter = new(new string[] { "-da", "--drop-audio" }, description: ResString.cmd_dropAudio, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
private readonly static Option<StreamFilter?> DropSubtitleFilter = new(new string[] { "-ds", "--drop-subtitle" }, description: ResString.cmd_dropSubtitle, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" }; private readonly static Option<StreamFilter?> DropSubtitleFilter = new(new string[] { "-ds", "--drop-subtitle" }, description: ResString.cmd_dropSubtitle, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
/// <summary>
/// 解析录制直播时长限制
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
private static long? ParseSpeedLimit(ArgumentResult result)
{
var input = result.Tokens.First().Value.ToUpper();
try
{
var reg = new Regex("([\\d\\\\.]+)(M|K)");
if (!reg.IsMatch(input)) throw new ArgumentException();
var number = double.Parse(reg.Match(input).Groups[1].Value);
if (reg.Match(input).Groups[2].Value == "M")
return (long)(number * 1024 * 1024);
else
return (long)(number * 1024);
}
catch (Exception)
{
result.ErrorMessage = "error in parse SpeedLimit: " + input;
return null;
}
}
/// <summary> /// <summary>
/// 解析用户定义的下载范围 /// 解析用户定义的下载范围
/// </summary> /// </summary>
@ -502,6 +529,7 @@ namespace N_m3u8DL_RE.CommandLine
NoDateInfo = bindingContext.ParseResult.GetValueForOption(NoDateInfo), NoDateInfo = bindingContext.ParseResult.GetValueForOption(NoDateInfo),
NoLog = bindingContext.ParseResult.GetValueForOption(NoLog), NoLog = bindingContext.ParseResult.GetValueForOption(NoLog),
AdKeywords = bindingContext.ParseResult.GetValueForOption(AdKeywords), AdKeywords = bindingContext.ParseResult.GetValueForOption(AdKeywords),
MaxSpeed = bindingContext.ParseResult.GetValueForOption(MaxSpeed),
}; };
if (bindingContext.ParseResult.HasOption(CustomHLSMethod)) option.CustomHLSMethod = bindingContext.ParseResult.GetValueForOption(CustomHLSMethod); if (bindingContext.ParseResult.HasOption(CustomHLSMethod)) option.CustomHLSMethod = bindingContext.ParseResult.GetValueForOption(CustomHLSMethod);
@ -564,6 +592,7 @@ namespace N_m3u8DL_RE.CommandLine
BinaryMerge, DelAfterDone, NoDateInfo, NoLog, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix, BinaryMerge, DelAfterDone, NoDateInfo, NoLog, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
FFmpegBinaryPath, FFmpegBinaryPath,
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption, LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
MaxSpeed,
MuxAfterDone, MuxAfterDone,
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, CustomRange, TaskStartAt, CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, CustomRange, TaskStartAt,
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveFixVttByAudio, LiveRecordLimit, LiveWaitTime, LiveTakeCount, LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveFixVttByAudio, LiveRecordLimit, LiveWaitTime, LiveTakeCount,

View File

@ -21,6 +21,10 @@ namespace N_m3u8DL_RE.CommandLine
/// </summary> /// </summary>
public string[]? AdKeywords { get; set; } public string[]? AdKeywords { get; set; }
/// <summary> /// <summary>
/// See: <see cref="CommandInvoker.MaxSpeed"/>.
/// </summary>
public long? MaxSpeed { get; set; }
/// <summary>
/// See: <see cref="CommandInvoker.Keys"/>. /// See: <see cref="CommandInvoker.Keys"/>.
/// </summary> /// </summary>
public string[]? Keys { get; set; } public string[]? Keys { get; set; }

View File

@ -662,6 +662,11 @@ namespace N_m3u8DL_RE.DownloadManager
var description = item.ToShortShortString(); var description = item.ToShortShortString();
var task = ctx.AddTask(description, autoStart: false); var task = ctx.AddTask(description, autoStart: false);
SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算 SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算
//限速设置
if (DownloaderConfig.MyOptions.MaxSpeed != null)
{
SpeedContainerDic[task.Id].SpeedLimit = DownloaderConfig.MyOptions.MaxSpeed.Value;
}
return (item, task); return (item, task);
}).ToDictionary(item => item.item, item => item.task); }).ToDictionary(item => item.item, item => item.task);

View File

@ -840,6 +840,11 @@ namespace N_m3u8DL_RE.DownloadManager
{ {
var task = ctx.AddTask(item.ToShortShortString(), autoStart: false, maxValue: 0); var task = ctx.AddTask(item.ToShortShortString(), autoStart: false, maxValue: 0);
SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算 SpeedContainerDic[task.Id] = new SpeedContainer(); //速度计算
//限速设置
if (DownloaderConfig.MyOptions.MaxSpeed != null)
{
SpeedContainerDic[task.Id].SpeedLimit = DownloaderConfig.MyOptions.MaxSpeed.Value;
}
LastFileNameDic[task.Id] = ""; LastFileNameDic[task.Id] = "";
RecordLimitReachedDic[task.Id] = false; RecordLimitReachedDic[task.Id] = false;
DateTimeDic[task.Id] = 0L; DateTimeDic[task.Id] = 0L;

View File

@ -13,6 +13,7 @@ namespace N_m3u8DL_RE.Entity
{ {
public bool SingleSegment { get; set; } = false; public bool SingleSegment { get; set; } = false;
public long NowSpeed { get; set; } = 0L; //当前每秒速度 public long NowSpeed { get; set; } = 0L; //当前每秒速度
public long SpeedLimit { get; set; } = long.MaxValue; //限速设置
public long? ResponseLength { get; set; } public long? ResponseLength { get; set; }
public long RDownloaded { get => _Rdownloaded; } public long RDownloaded { get => _Rdownloaded; }
private int _zeroSpeedCount = 0; private int _zeroSpeedCount = 0;

View File

@ -120,6 +120,11 @@ namespace N_m3u8DL_RE.Util
{ {
speedContainer.Add(size); speedContainer.Add(size);
await stream.WriteAsync(buffer, 0, size); await stream.WriteAsync(buffer, 0, size);
//限速策略
while (speedContainer.Downloaded > speedContainer.SpeedLimit)
{
await Task.Delay(1);
}
} }
return new DownloadResult() return new DownloadResult()