新增`--allow-hls-multi-ext-map` (#503)
This commit is contained in:
parent
0c73b730bb
commit
e8e92b6337
|
@ -65,6 +65,7 @@ public class ResString
|
|||
public static string cmd_skipDownload => GetText("cmd_skipDownload");
|
||||
public static string cmd_noDateInfo => GetText("cmd_noDateInfo");
|
||||
public static string cmd_noLog => GetText("cmd_noLog");
|
||||
public static string cmd_allowHlsMultiExtMap => GetText("cmd_allowHlsMultiExtMap");
|
||||
public static string cmd_skipMerge => GetText("cmd_skipMerge");
|
||||
public static string cmd_subFormat => GetText("cmd_subFormat");
|
||||
public static string cmd_subOnly => GetText("cmd_subOnly");
|
||||
|
@ -111,6 +112,7 @@ public class ResString
|
|||
public static string liveFound => GetText("liveFound");
|
||||
public static string loadingUrl => GetText("loadingUrl");
|
||||
public static string masterM3u8Found => GetText("masterM3u8Found");
|
||||
public static string allowHlsMultiExtMap => GetText("allowHlsMultiExtMap");
|
||||
public static string matchDASH => GetText("matchDASH");
|
||||
public static string matchMSS => GetText("matchMSS");
|
||||
public static string matchTS => GetText("matchTS");
|
||||
|
|
|
@ -172,6 +172,12 @@ internal class StaticText
|
|||
zhTW: "關閉日誌文件輸出",
|
||||
enUS: "Disable log file output"
|
||||
),
|
||||
["cmd_allowHlsMultiExtMap"] = new TextContainer
|
||||
(
|
||||
zhCN: "允许HLS中的多个#EXT-X-MAP(实验性)",
|
||||
zhTW: "允許HLS中的多個#EXT-X-MAP(實驗性)",
|
||||
enUS: "Allow multiple #EXT-X-MAP in HLS (experimental)"
|
||||
),
|
||||
["cmd_appendUrlParams"] = new TextContainer
|
||||
(
|
||||
zhCN: "将输入Url的Params添加至分片, 对某些网站很有用, 例如 kakao.com",
|
||||
|
@ -820,6 +826,12 @@ internal class StaticText
|
|||
zhTW: "檢測到Master列表,開始解析全部流訊息",
|
||||
enUS: "Master List detected, try parse all streams"
|
||||
),
|
||||
["allowHlsMultiExtMap"] = new TextContainer
|
||||
(
|
||||
zhCN: "已经允许识别多个#EXT-X-MAP标签, 本软件可能无法正确处理, 请手动确认内容完整性",
|
||||
zhTW: "已經允許識別多個#EXT-X-MAP標籤, 本軟件可能無法正確處理, 請手動確認內容完整性",
|
||||
enUS: "Multiple #EXT-X-MAP tags are now allowed for detection. However, this software may not handle them correctly. Please manually verify the content's integrity"
|
||||
),
|
||||
["matchTS"] = new TextContainer
|
||||
(
|
||||
zhCN: "内容匹配: [white on green3]HTTP Live MPEG2-TS[/]",
|
||||
|
|
|
@ -13,7 +13,9 @@ public class ParserConfig
|
|||
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> CustomParserArgs { get; } = new();
|
||||
|
||||
public Dictionary<string, string> Headers { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 内容前置处理器. 调用顺序与列表顺序相同
|
||||
|
|
|
@ -221,6 +221,12 @@ internal class HLSExtractor : IExtractor
|
|||
{
|
||||
// 标记是否已清除广告分片
|
||||
bool hasAd = false;
|
||||
;
|
||||
bool allowHlsMultiExtMap = ParserConfig.CustomParserArgs.TryGetValue("AllowHlsMultiExtMap", out var allMultiExtMap) && allMultiExtMap == "true";
|
||||
if (allowHlsMultiExtMap)
|
||||
{
|
||||
Logger.WarnMarkUp($"[darkorange3_1]{ResString.allowHlsMultiExtMap}[/]");
|
||||
}
|
||||
|
||||
using StringReader sr = new StringReader(M3u8Content);
|
||||
string? line;
|
||||
|
@ -395,10 +401,13 @@ internal class HLSExtractor : IExtractor
|
|||
});
|
||||
}
|
||||
segments = new();
|
||||
if (!allowHlsMultiExtMap)
|
||||
{
|
||||
isEndlist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 评论行不解析
|
||||
else if (line.StartsWith("#")) continue;
|
||||
// 空白行不解析
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace N_m3u8DL_RE.CommandLine;
|
|||
|
||||
internal partial class CommandInvoker
|
||||
{
|
||||
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20241117";
|
||||
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20241123";
|
||||
|
||||
[GeneratedRegex("((best|worst)\\d*|all)")]
|
||||
private static partial Regex ForStrRegex();
|
||||
|
@ -61,6 +61,7 @@ internal partial class CommandInvoker
|
|||
private static readonly Option<string?> BaseUrl = new(["--base-url"], description: ResString.cmd_baseUrl);
|
||||
private static readonly Option<bool> ConcurrentDownload = new(["-mt", "--concurrent-download"], description: ResString.cmd_concurrentDownload, getDefaultValue: () => false);
|
||||
private static readonly Option<bool> NoLog = new(["--no-log"], description: ResString.cmd_noLog, getDefaultValue: () => false);
|
||||
private static readonly Option<bool> AllowHlsMultiExtMap = new(["--allow-hls-multi-ext-map"], description: ResString.cmd_allowHlsMultiExtMap, getDefaultValue: () => false);
|
||||
private static readonly Option<string[]?> AdKeywords = new(["--ad-keyword"], description: ResString.cmd_adKeyword) { ArgumentHelpName = "REG" };
|
||||
private static readonly Option<long?> MaxSpeed = new(["-R", "--max-speed"], description: ResString.cmd_maxSpeed, parseArgument: ParseSpeedLimit) { ArgumentHelpName = "SPEED" };
|
||||
|
||||
|
@ -550,6 +551,7 @@ internal partial class CommandInvoker
|
|||
LiveTakeCount = bindingContext.ParseResult.GetValueForOption(LiveTakeCount),
|
||||
NoDateInfo = bindingContext.ParseResult.GetValueForOption(NoDateInfo),
|
||||
NoLog = bindingContext.ParseResult.GetValueForOption(NoLog),
|
||||
AllowHlsMultiExtMap = bindingContext.ParseResult.GetValueForOption(AllowHlsMultiExtMap),
|
||||
AdKeywords = bindingContext.ParseResult.GetValueForOption(AdKeywords),
|
||||
MaxSpeed = bindingContext.ParseResult.GetValueForOption(MaxSpeed),
|
||||
};
|
||||
|
@ -618,7 +620,7 @@ internal partial class CommandInvoker
|
|||
MuxAfterDone,
|
||||
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, CustomRange, TaskStartAt,
|
||||
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveFixVttByAudio, LiveRecordLimit, LiveWaitTime, LiveTakeCount,
|
||||
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, AdKeywords, DisableUpdateCheck, MoreHelp
|
||||
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, AdKeywords, DisableUpdateCheck, AllowHlsMultiExtMap, MoreHelp
|
||||
};
|
||||
|
||||
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
||||
|
|
|
@ -53,6 +53,10 @@ internal class MyOption
|
|||
/// </summary>
|
||||
public bool NoLog { get; set; }
|
||||
/// <summary>
|
||||
/// See: <see cref="CommandInvoker.AllowHlsMultiExtMap"/>.
|
||||
/// </summary>
|
||||
public bool AllowHlsMultiExtMap { get; set; }
|
||||
/// <summary>
|
||||
/// See: <see cref="CommandInvoker.AutoSelect"/>.
|
||||
/// </summary>
|
||||
public bool AutoSelect { get; set; }
|
||||
|
|
|
@ -106,21 +106,20 @@ internal class Program
|
|||
|
||||
// 检查互斥的选项
|
||||
|
||||
if (!option.MuxAfterDone && option.MuxImports != null && option.MuxImports.Count > 0)
|
||||
if (option is { MuxAfterDone: false, MuxImports.Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("MuxAfterDone disabled, MuxImports not allowed!");
|
||||
}
|
||||
|
||||
// LivePipeMux开启时 LiveRealTimeMerge必须开启
|
||||
if (option.LivePipeMux && !option.LiveRealTimeMerge)
|
||||
if (option is { LivePipeMux: true, LiveRealTimeMerge: false })
|
||||
{
|
||||
Logger.WarnMarkUp("LivePipeMux detected, forced enable LiveRealTimeMerge");
|
||||
option.LiveRealTimeMerge = true;
|
||||
}
|
||||
|
||||
// 预先检查ffmpeg
|
||||
if (option.FFmpegBinaryPath == null)
|
||||
option.FFmpegBinaryPath = GlobalUtil.FindExecutable("ffmpeg");
|
||||
option.FFmpegBinaryPath ??= GlobalUtil.FindExecutable("ffmpeg");
|
||||
|
||||
if (string.IsNullOrEmpty(option.FFmpegBinaryPath) || !File.Exists(option.FFmpegBinaryPath))
|
||||
{
|
||||
|
@ -132,8 +131,7 @@ internal class Program
|
|||
// 预先检查mkvmerge
|
||||
if (option.MuxOptions != null && option.MuxOptions.UseMkvmerge && option.MuxAfterDone)
|
||||
{
|
||||
if (option.MkvmergeBinaryPath == null)
|
||||
option.MkvmergeBinaryPath = GlobalUtil.FindExecutable("mkvmerge");
|
||||
option.MkvmergeBinaryPath ??= GlobalUtil.FindExecutable("mkvmerge");
|
||||
if (string.IsNullOrEmpty(option.MkvmergeBinaryPath) || !File.Exists(option.MkvmergeBinaryPath))
|
||||
{
|
||||
throw new FileNotFoundException("mkvmerge not found");
|
||||
|
@ -142,7 +140,7 @@ internal class Program
|
|||
}
|
||||
|
||||
// 预先检查
|
||||
if ((option.Keys != null && option.Keys.Length > 0) || option.KeyTextFile != null)
|
||||
if (option.Keys is { Length: > 0 } || option.KeyTextFile != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(option.DecryptionBinaryPath))
|
||||
{
|
||||
|
@ -193,6 +191,11 @@ internal class Program
|
|||
CustomeIV = option.CustomHLSIv,
|
||||
};
|
||||
|
||||
if (option.AllowHlsMultiExtMap)
|
||||
{
|
||||
parserConfig.CustomParserArgs.Add("AllowHlsMultiExtMap", "true");
|
||||
}
|
||||
|
||||
// demo1
|
||||
parserConfig.ContentProcessors.Insert(0, new DemoProcessor());
|
||||
// demo2
|
||||
|
@ -225,13 +228,13 @@ internal class Program
|
|||
|
||||
|
||||
// 全部媒体
|
||||
var lists = streams.OrderBy(p => p.MediaType).ThenByDescending(p => p.Bandwidth).ThenByDescending(GetOrder);
|
||||
var lists = streams.OrderBy(p => p.MediaType).ThenByDescending(p => p.Bandwidth).ThenByDescending(GetOrder).ToList();
|
||||
// 基本流
|
||||
var basicStreams = lists.Where(x => x.MediaType == null || x.MediaType == MediaType.VIDEO);
|
||||
var basicStreams = lists.Where(x => x.MediaType is null or MediaType.VIDEO).ToList();
|
||||
// 可选音频轨道
|
||||
var audios = lists.Where(x => x.MediaType == MediaType.AUDIO);
|
||||
var audios = lists.Where(x => x.MediaType == MediaType.AUDIO).ToList();
|
||||
// 可选字幕轨道
|
||||
var subs = lists.Where(x => x.MediaType == MediaType.SUBTITLES);
|
||||
var subs = lists.Where(x => x.MediaType == MediaType.SUBTITLES).ToList();
|
||||
|
||||
// 尝试从URL或文件读取文件名
|
||||
if (string.IsNullOrEmpty(option.SaveName))
|
||||
|
@ -246,7 +249,7 @@ internal class Program
|
|||
// 写出文件
|
||||
await WriteRawFilesAsync(option, extractor, tmpDir);
|
||||
|
||||
Logger.Info(ResString.streamsInfo, lists.Count(), basicStreams.Count(), audios.Count(), subs.Count());
|
||||
Logger.Info(ResString.streamsInfo, lists.Count, basicStreams.Count, audios.Count, subs.Count);
|
||||
|
||||
foreach (var item in lists)
|
||||
{
|
||||
|
@ -259,7 +262,7 @@ internal class Program
|
|||
basicStreams = FilterUtil.DoFilterDrop(basicStreams, option.DropVideoFilter);
|
||||
audios = FilterUtil.DoFilterDrop(audios, option.DropAudioFilter);
|
||||
subs = FilterUtil.DoFilterDrop(subs, option.DropSubtitleFilter);
|
||||
lists = basicStreams.Concat(audios).Concat(subs).OrderBy(x => true);
|
||||
lists = basicStreams.Concat(audios).Concat(subs).ToList();
|
||||
}
|
||||
|
||||
if (option.DropVideoFilter != null) Logger.Extra($"DropVideoFilter => {option.DropVideoFilter}");
|
||||
|
|
Loading…
Reference in New Issue