支持通过分片数量选择流; 支持过滤不需要的流
This commit is contained in:
parent
9cd8cec5cd
commit
66daf00b5a
|
@ -54,6 +54,14 @@ namespace N_m3u8DL_RE.Common.Entity
|
||||||
|
|
||||||
public Playlist? Playlist { get; set; }
|
public Playlist? Playlist { get; set; }
|
||||||
|
|
||||||
|
public int SegmentsCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Playlist != null ? Playlist.MediaParts.Sum(x => x.MediaSegments.Count) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string ToShortString()
|
public string ToShortString()
|
||||||
{
|
{
|
||||||
var prefixStr = "";
|
var prefixStr = "";
|
||||||
|
@ -93,8 +101,7 @@ namespace N_m3u8DL_RE.Common.Entity
|
||||||
var prefixStr = "";
|
var prefixStr = "";
|
||||||
var returnStr = "";
|
var returnStr = "";
|
||||||
var encStr = string.Empty;
|
var encStr = string.Empty;
|
||||||
var segmentsCount = Playlist != null ? Playlist.MediaParts.Sum(x => x.MediaSegments.Count) : 0;
|
var segmentsCountStr = SegmentsCount == 0 ? "" : (SegmentsCount > 1 ? $"{SegmentsCount} Segments" : $"{SegmentsCount} Segment");
|
||||||
var segmentsCountStr = segmentsCount == 0 ? "" : (segmentsCount > 1 ? $"{segmentsCount} Segments" : $"{segmentsCount} Segment");
|
|
||||||
|
|
||||||
//增加加密标志
|
//增加加密标志
|
||||||
if (Playlist != null && Playlist.MediaParts.Any(m => m.MediaSegments.Any(s => s.EncryptInfo.Method != EncryptMethod.NONE)))
|
if (Playlist != null && Playlist.MediaParts.Any(m => m.MediaSegments.Any(s => s.EncryptInfo.Method != EncryptMethod.NONE)))
|
||||||
|
|
|
@ -32,10 +32,13 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
public static string cmd_muxImport { get => GetText("cmd_muxImport"); }
|
public static string cmd_muxImport { get => GetText("cmd_muxImport"); }
|
||||||
public static string cmd_muxImport_more { get => GetText("cmd_muxImport_more"); }
|
public static string cmd_muxImport_more { get => GetText("cmd_muxImport_more"); }
|
||||||
public static string cmd_selectVideo { get => GetText("cmd_selectVideo"); }
|
public static string cmd_selectVideo { get => GetText("cmd_selectVideo"); }
|
||||||
|
public static string cmd_dropVideo { get => GetText("cmd_dropVideo"); }
|
||||||
public static string cmd_selectVideo_more { get => GetText("cmd_selectVideo_more"); }
|
public static string cmd_selectVideo_more { get => GetText("cmd_selectVideo_more"); }
|
||||||
public static string cmd_selectAudio { get => GetText("cmd_selectAudio"); }
|
public static string cmd_selectAudio { get => GetText("cmd_selectAudio"); }
|
||||||
|
public static string cmd_dropAudio { get => GetText("cmd_dropAudio"); }
|
||||||
public static string cmd_selectAudio_more { get => GetText("cmd_selectAudio_more"); }
|
public static string cmd_selectAudio_more { get => GetText("cmd_selectAudio_more"); }
|
||||||
public static string cmd_selectSubtitle { get => GetText("cmd_selectSubtitle"); }
|
public static string cmd_selectSubtitle { get => GetText("cmd_selectSubtitle"); }
|
||||||
|
public static string cmd_dropSubtitle { get => GetText("cmd_dropSubtitle"); }
|
||||||
public static string cmd_selectSubtitle_more { get => GetText("cmd_selectSubtitle_more"); }
|
public static string cmd_selectSubtitle_more { get => GetText("cmd_selectSubtitle_more"); }
|
||||||
public static string cmd_customHLSMethod { get => GetText("cmd_customHLSMethod"); }
|
public static string cmd_customHLSMethod { get => GetText("cmd_customHLSMethod"); }
|
||||||
public static string cmd_customHLSKey { get => GetText("cmd_customHLSKey"); }
|
public static string cmd_customHLSKey { get => GetText("cmd_customHLSKey"); }
|
||||||
|
|
|
@ -334,11 +334,17 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
zhTW: "通過正則表達式選擇符合要求的影片軌. 輸入 \"--morehelp select-video\" 以查看詳細訊息",
|
zhTW: "通過正則表達式選擇符合要求的影片軌. 輸入 \"--morehelp select-video\" 以查看詳細訊息",
|
||||||
enUS: "Select video streams by regular expressions. Use \"--morehelp select-video\" for more details"
|
enUS: "Select video streams by regular expressions. Use \"--morehelp select-video\" for more details"
|
||||||
),
|
),
|
||||||
|
["cmd_dropVideo"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "通过正则表达式去除符合要求的视频流.",
|
||||||
|
zhTW: "通過正則表達式去除符合要求的影片串流.",
|
||||||
|
enUS: "Drop video streams by regular expressions."
|
||||||
|
),
|
||||||
["cmd_selectVideo_more"] = new TextContainer
|
["cmd_selectVideo_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
|
zhCN: "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
|
||||||
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX\r\n" +
|
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
||||||
"frame=REGEX:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
|
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
|
||||||
"* for=FOR: 选择方式. best[number], worst[number], all (默认: best)\r\n\r\n" +
|
"* for=FOR: 选择方式. best[number], worst[number], all (默认: best)\r\n\r\n" +
|
||||||
"例如: \r\n" +
|
"例如: \r\n" +
|
||||||
"# 选择最佳视频\r\n" +
|
"# 选择最佳视频\r\n" +
|
||||||
|
@ -370,6 +376,12 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
zhTW: "通過正則表達式選擇符合要求的音軌. 輸入 \"--morehelp select-audio\" 以查看詳細訊息",
|
zhTW: "通過正則表達式選擇符合要求的音軌. 輸入 \"--morehelp select-audio\" 以查看詳細訊息",
|
||||||
enUS: "Select audio streams by regular expressions. Use \"--morehelp select-audio\" for more details"
|
enUS: "Select audio streams by regular expressions. Use \"--morehelp select-audio\" for more details"
|
||||||
),
|
),
|
||||||
|
["cmd_dropAudio"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "通过正则表达式去除符合要求的音频流.",
|
||||||
|
zhTW: "通過正則表達式去除符合要求的音軌.",
|
||||||
|
enUS: "Drop audio streams by regular expressions."
|
||||||
|
),
|
||||||
["cmd_selectAudio_more"] = new TextContainer
|
["cmd_selectAudio_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的音频流. 参考 --select-video\r\n\r\n" +
|
zhCN: "通过正则表达式选择符合要求的音频流. 参考 --select-video\r\n\r\n" +
|
||||||
|
@ -403,6 +415,12 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
zhTW: "通過正則表達式選擇符合要求的字幕流. 輸入 \"--morehelp select-subtitle\" 以查看詳細訊息",
|
zhTW: "通過正則表達式選擇符合要求的字幕流. 輸入 \"--morehelp select-subtitle\" 以查看詳細訊息",
|
||||||
enUS: "Select subtitle streams by regular expressions. Use \"--morehelp select-subtitle\" for more details"
|
enUS: "Select subtitle streams by regular expressions. Use \"--morehelp select-subtitle\" for more details"
|
||||||
),
|
),
|
||||||
|
["cmd_dropSubtitle"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "通过正则表达式去除符合要求的字幕流.",
|
||||||
|
zhTW: "通過正則表達式去除符合要求的字幕流.",
|
||||||
|
enUS: "Drop subtitle streams by regular expressions."
|
||||||
|
),
|
||||||
["cmd_selectSubtitle_more"] = new TextContainer
|
["cmd_selectSubtitle_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的字幕流. 参考 --select-video\r\n\r\n" +
|
zhCN: "通过正则表达式选择符合要求的字幕流. 参考 --select-video\r\n\r\n" +
|
||||||
|
|
|
@ -84,6 +84,10 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
private readonly static Option<StreamFilter?> AudioFilter = new(new string[] { "-sa", "--select-audio" }, description: ResString.cmd_selectAudio, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
|
private readonly static Option<StreamFilter?> AudioFilter = new(new string[] { "-sa", "--select-audio" }, description: ResString.cmd_selectAudio, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
|
||||||
private readonly static Option<StreamFilter?> SubtitleFilter = new(new string[] { "-ss", "--select-subtitle" }, description: ResString.cmd_selectSubtitle, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
|
private readonly static Option<StreamFilter?> SubtitleFilter = new(new string[] { "-ss", "--select-subtitle" }, description: ResString.cmd_selectSubtitle, parseArgument: ParseStreamFilter) { ArgumentHelpName = "OPTIONS" };
|
||||||
|
|
||||||
|
private readonly static Option<StreamFilter?> DropVideoFilter = new(new string[] { "-dv", "--drop-video" }, description: ResString.cmd_dropVideo, 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" };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解析用户代理
|
/// 解析用户代理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -236,6 +240,14 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
if (!string.IsNullOrEmpty(url))
|
if (!string.IsNullOrEmpty(url))
|
||||||
streamFilter.UrlReg = new Regex(url);
|
streamFilter.UrlReg = new Regex(url);
|
||||||
|
|
||||||
|
var segsMin = p.GetValue("segsMin");
|
||||||
|
if (!string.IsNullOrEmpty(segsMin))
|
||||||
|
streamFilter.SegmentsMinCount = long.Parse(segsMin);
|
||||||
|
|
||||||
|
var segsMax = p.GetValue("segsMax");
|
||||||
|
if (!string.IsNullOrEmpty(segsMax))
|
||||||
|
streamFilter.SegmentsMaxCount = long.Parse(segsMax);
|
||||||
|
|
||||||
return streamFilter;
|
return streamFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +385,9 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
VideoFilter = bindingContext.ParseResult.GetValueForOption(VideoFilter),
|
VideoFilter = bindingContext.ParseResult.GetValueForOption(VideoFilter),
|
||||||
AudioFilter = bindingContext.ParseResult.GetValueForOption(AudioFilter),
|
AudioFilter = bindingContext.ParseResult.GetValueForOption(AudioFilter),
|
||||||
SubtitleFilter = bindingContext.ParseResult.GetValueForOption(SubtitleFilter),
|
SubtitleFilter = bindingContext.ParseResult.GetValueForOption(SubtitleFilter),
|
||||||
|
DropVideoFilter = bindingContext.ParseResult.GetValueForOption(DropVideoFilter),
|
||||||
|
DropAudioFilter = bindingContext.ParseResult.GetValueForOption(DropAudioFilter),
|
||||||
|
DropSubtitleFilter = bindingContext.ParseResult.GetValueForOption(DropSubtitleFilter),
|
||||||
LiveRealTimeMerge = bindingContext.ParseResult.GetValueForOption(LiveRealTimeMerge),
|
LiveRealTimeMerge = bindingContext.ParseResult.GetValueForOption(LiveRealTimeMerge),
|
||||||
LiveKeepSegments = bindingContext.ParseResult.GetValueForOption(LiveKeepSegments),
|
LiveKeepSegments = bindingContext.ParseResult.GetValueForOption(LiveKeepSegments),
|
||||||
LiveRecordLimit = bindingContext.ParseResult.GetValueForOption(LiveRecordLimit),
|
LiveRecordLimit = bindingContext.ParseResult.GetValueForOption(LiveRecordLimit),
|
||||||
|
@ -447,7 +462,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
MuxAfterDone,
|
MuxAfterDone,
|
||||||
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy,
|
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy,
|
||||||
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LiveRecordLimit, LiveWaitTime,
|
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LiveRecordLimit, LiveWaitTime,
|
||||||
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, MoreHelp
|
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, MoreHelp
|
||||||
};
|
};
|
||||||
|
|
||||||
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace N_m3u8DL_RE.Entity
|
||||||
public Regex? ChannelsReg { get; set; }
|
public Regex? ChannelsReg { get; set; }
|
||||||
public Regex? VideoRangeReg { get; set; }
|
public Regex? VideoRangeReg { get; set; }
|
||||||
public Regex? UrlReg { get; set; }
|
public Regex? UrlReg { get; set; }
|
||||||
|
public long? SegmentsMinCount { get; set; }
|
||||||
|
public long? SegmentsMaxCount { get; set; }
|
||||||
|
|
||||||
public string For { get; set; } = "best";
|
public string For { get; set; } = "best";
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,14 @@ namespace N_m3u8DL_RE
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedStreams = new List<StreamSpec>();
|
var selectedStreams = new List<StreamSpec>();
|
||||||
|
if (option.DropVideoFilter != null || option.DropAudioFilter != null || option.DropSubtitleFilter != null)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if (option.AutoSelect)
|
if (option.AutoSelect)
|
||||||
{
|
{
|
||||||
if (basicStreams.Any())
|
if (basicStreams.Any())
|
||||||
|
@ -215,9 +223,9 @@ namespace N_m3u8DL_RE
|
||||||
}
|
}
|
||||||
else if (option.VideoFilter != null || option.AudioFilter != null || option.SubtitleFilter != null)
|
else if (option.VideoFilter != null || option.AudioFilter != null || option.SubtitleFilter != null)
|
||||||
{
|
{
|
||||||
basicStreams = FilterUtil.DoFilter(basicStreams, option.VideoFilter);
|
basicStreams = FilterUtil.DoFilterKeep(basicStreams, option.VideoFilter);
|
||||||
audios = FilterUtil.DoFilter(audios, option.AudioFilter);
|
audios = FilterUtil.DoFilterKeep(audios, option.AudioFilter);
|
||||||
subs = FilterUtil.DoFilter(subs, option.SubtitleFilter);
|
subs = FilterUtil.DoFilterKeep(subs, option.SubtitleFilter);
|
||||||
selectedStreams = basicStreams.Concat(audios).Concat(subs).ToList();
|
selectedStreams = basicStreams.Concat(audios).Concat(subs).ToList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace N_m3u8DL_RE.Util
|
||||||
{
|
{
|
||||||
public class FilterUtil
|
public class FilterUtil
|
||||||
{
|
{
|
||||||
public static List<StreamSpec> DoFilter(IEnumerable<StreamSpec> lists, StreamFilter? filter)
|
public static List<StreamSpec> DoFilterKeep(IEnumerable<StreamSpec> lists, StreamFilter? filter)
|
||||||
{
|
{
|
||||||
if (filter == null) return new List<StreamSpec>();
|
if (filter == null) return new List<StreamSpec>();
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ namespace N_m3u8DL_RE.Util
|
||||||
inputs = inputs.Where(i => i.VideoRange != null && filter.VideoRangeReg.IsMatch(i.VideoRange));
|
inputs = inputs.Where(i => i.VideoRange != null && filter.VideoRangeReg.IsMatch(i.VideoRange));
|
||||||
if (filter.UrlReg != null)
|
if (filter.UrlReg != null)
|
||||||
inputs = inputs.Where(i => i.Url != null && filter.UrlReg.IsMatch(i.Url));
|
inputs = inputs.Where(i => i.Url != null && filter.UrlReg.IsMatch(i.Url));
|
||||||
|
if (filter.SegmentsMaxCount != null && inputs.All(i => i.SegmentsCount > 0))
|
||||||
|
inputs = inputs.Where(i => i.SegmentsCount < filter.SegmentsMaxCount);
|
||||||
|
if (filter.SegmentsMinCount != null && inputs.All(i => i.SegmentsCount > 0))
|
||||||
|
inputs = inputs.Where(i => i.SegmentsCount > filter.SegmentsMinCount);
|
||||||
|
|
||||||
var bestNumberStr = filter.For.Replace("best", "");
|
var bestNumberStr = filter.For.Replace("best", "");
|
||||||
var worstNumberStr = filter.For.Replace("worst", "");
|
var worstNumberStr = filter.For.Replace("worst", "");
|
||||||
|
@ -52,6 +56,18 @@ namespace N_m3u8DL_RE.Util
|
||||||
return inputs.ToList();
|
return inputs.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<StreamSpec> DoFilterDrop(IEnumerable<StreamSpec> lists, StreamFilter? filter)
|
||||||
|
{
|
||||||
|
if (filter == null) return new List<StreamSpec>();
|
||||||
|
|
||||||
|
var inputs = lists.Where(_ => true);
|
||||||
|
var selected = DoFilterKeep(lists, filter);
|
||||||
|
|
||||||
|
inputs = inputs.SkipWhile(i => selected.Any(s => s.ToString() == i.ToString()));
|
||||||
|
|
||||||
|
return inputs.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public static List<StreamSpec> SelectStreams(IEnumerable<StreamSpec> lists)
|
public static List<StreamSpec> SelectStreams(IEnumerable<StreamSpec> lists)
|
||||||
{
|
{
|
||||||
if (lists.Count() == 1)
|
if (lists.Count() == 1)
|
||||||
|
|
Loading…
Reference in New Issue