支持限速功能 `--max-speed` #220
This commit is contained in:
parent
9ab8f3cf72
commit
eb85df8b4d
|
@ -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"); }
|
||||||
|
|
|
@ -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 或 Kbps,如:15M 100K",
|
||||||
|
zhTW: "設置限速,單位支持 Mbps 或 Kbps,如:15M 100K",
|
||||||
|
enUS: "Set speed limit, Mbps or Kbps, for example: 15M 100K."
|
||||||
|
),
|
||||||
["cmd_noDateInfo"] = new TextContainer
|
["cmd_noDateInfo"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "混流时不写入日期信息",
|
zhCN: "混流时不写入日期信息",
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue