支持通过分片数量选择流; 支持过滤不需要的流

This commit is contained in:
nilaoda 2022-12-02 15:52:16 +08:00
parent 9cd8cec5cd
commit 66daf00b5a
7 changed files with 78 additions and 9 deletions

View File

@ -54,6 +54,14 @@ namespace N_m3u8DL_RE.Common.Entity
public Playlist? Playlist { get; set; }
public int SegmentsCount
{
get
{
return Playlist != null ? Playlist.MediaParts.Sum(x => x.MediaSegments.Count) : 0;
}
}
public string ToShortString()
{
var prefixStr = "";
@ -93,8 +101,7 @@ namespace N_m3u8DL_RE.Common.Entity
var prefixStr = "";
var returnStr = "";
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)))

View File

@ -32,10 +32,13 @@ namespace N_m3u8DL_RE.Common.Resource
public static string cmd_muxImport { get => GetText("cmd_muxImport"); }
public static string cmd_muxImport_more { get => GetText("cmd_muxImport_more"); }
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_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_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_customHLSMethod { get => GetText("cmd_customHLSMethod"); }
public static string cmd_customHLSKey { get => GetText("cmd_customHLSKey"); }

View File

@ -334,11 +334,17 @@ namespace N_m3u8DL_RE.Common.Resource
zhTW: "通過正則表達式選擇符合要求的影片軌. 輸入 \"--morehelp select-video\" 以查看詳細訊息",
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
(
zhCN: "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX\r\n" +
"frame=REGEX:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\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" +
"例如: \r\n" +
"# 选择最佳视频\r\n" +
@ -370,6 +376,12 @@ namespace N_m3u8DL_RE.Common.Resource
zhTW: "通過正則表達式選擇符合要求的音軌. 輸入 \"--morehelp select-audio\" 以查看詳細訊息",
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
(
zhCN: "通过正则表达式选择符合要求的音频流. 参考 --select-video\r\n\r\n" +
@ -403,6 +415,12 @@ namespace N_m3u8DL_RE.Common.Resource
zhTW: "通過正則表達式選擇符合要求的字幕流. 輸入 \"--morehelp select-subtitle\" 以查看詳細訊息",
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
(
zhCN: "通过正则表达式选择符合要求的字幕流. 参考 --select-video\r\n\r\n" +

View File

@ -83,6 +83,10 @@ namespace N_m3u8DL_RE.CommandLine
private readonly static Option<StreamFilter?> VideoFilter = new(new string[] { "-sv", "--select-video" }, description: ResString.cmd_selectVideo, 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?> 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>
/// 解析用户代理
@ -236,6 +240,14 @@ namespace N_m3u8DL_RE.CommandLine
if (!string.IsNullOrEmpty(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;
}
@ -373,6 +385,9 @@ namespace N_m3u8DL_RE.CommandLine
VideoFilter = bindingContext.ParseResult.GetValueForOption(VideoFilter),
AudioFilter = bindingContext.ParseResult.GetValueForOption(AudioFilter),
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),
LiveKeepSegments = bindingContext.ParseResult.GetValueForOption(LiveKeepSegments),
LiveRecordLimit = bindingContext.ParseResult.GetValueForOption(LiveRecordLimit),
@ -447,7 +462,7 @@ namespace N_m3u8DL_RE.CommandLine
MuxAfterDone,
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy,
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LiveRecordLimit, LiveWaitTime,
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, MoreHelp
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, MoreHelp
};
rootCommand.TreatUnmatchedTokensAsErrors = true;

View File

@ -19,6 +19,8 @@ namespace N_m3u8DL_RE.Entity
public Regex? ChannelsReg { get; set; }
public Regex? VideoRangeReg { get; set; }
public Regex? UrlReg { get; set; }
public long? SegmentsMinCount { get; set; }
public long? SegmentsMaxCount { get; set; }
public string For { get; set; } = "best";
}

View File

@ -198,6 +198,14 @@ namespace N_m3u8DL_RE
}
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 (basicStreams.Any())
@ -215,9 +223,9 @@ namespace N_m3u8DL_RE
}
else if (option.VideoFilter != null || option.AudioFilter != null || option.SubtitleFilter != null)
{
basicStreams = FilterUtil.DoFilter(basicStreams, option.VideoFilter);
audios = FilterUtil.DoFilter(audios, option.AudioFilter);
subs = FilterUtil.DoFilter(subs, option.SubtitleFilter);
basicStreams = FilterUtil.DoFilterKeep(basicStreams, option.VideoFilter);
audios = FilterUtil.DoFilterKeep(audios, option.AudioFilter);
subs = FilterUtil.DoFilterKeep(subs, option.SubtitleFilter);
selectedStreams = basicStreams.Concat(audios).Concat(subs).ToList();
}
else

View File

@ -13,7 +13,7 @@ namespace N_m3u8DL_RE.Util
{
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>();
@ -36,6 +36,10 @@ namespace N_m3u8DL_RE.Util
inputs = inputs.Where(i => i.VideoRange != null && filter.VideoRangeReg.IsMatch(i.VideoRange));
if (filter.UrlReg != null)
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 worstNumberStr = filter.For.Replace("worst", "");
@ -52,6 +56,18 @@ namespace N_m3u8DL_RE.Util
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)
{
if (lists.Count() == 1)