diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.cs b/src/N_m3u8DL-RE.Common/Resource/ResString.cs index cfe59a7..d65babe 100644 --- a/src/N_m3u8DL-RE.Common/Resource/ResString.cs +++ b/src/N_m3u8DL-RE.Common/Resource/ResString.cs @@ -12,6 +12,7 @@ namespace N_m3u8DL_RE.Common.Resource public readonly static string ReLiveTs = ""; public static string customRangeWarn { get => GetText("customRangeWarn"); } public static string customRangeFound { get => GetText("customRangeFound"); } + public static string customAdKeywordsFound { get => GetText("customAdKeywordsFound"); } public static string customRangeInvalid { get => GetText("customRangeInvalid"); } public static string autoBinaryMerge { get => GetText("autoBinaryMerge"); } public static string autoBinaryMerge2 { get => GetText("autoBinaryMerge2"); } @@ -31,6 +32,7 @@ namespace N_m3u8DL_RE.Common.Resource public static string cmd_ffmpegBinaryPath { get => GetText("cmd_ffmpegBinaryPath"); } public static string cmd_mkvmergeBinaryPath { get => GetText("cmd_mkvmergeBinaryPath"); } public static string cmd_baseUrl { get => GetText("cmd_baseUrl"); } + public static string cmd_adKeyword { get => GetText("cmd_adKeyword"); } public static string cmd_moreHelp { get => GetText("cmd_moreHelp"); } public static string cmd_header { get => GetText("cmd_header"); } public static string cmd_muxImport { get => GetText("cmd_muxImport"); } diff --git a/src/N_m3u8DL-RE.Common/Resource/StaticText.cs b/src/N_m3u8DL-RE.Common/Resource/StaticText.cs index 7f5c3cf..e97ce6b 100644 --- a/src/N_m3u8DL-RE.Common/Resource/StaticText.cs +++ b/src/N_m3u8DL-RE.Common/Resource/StaticText.cs @@ -22,6 +22,12 @@ namespace N_m3u8DL_RE.Common.Resource zhTW: "自定義下載範圍無效", enUS: "User customed range invalid" ), + ["customAdKeywordsFound"] = new TextContainer + ( + zhCN: "用户自定义广告分片URL关键字:", + zhTW: "用戶自定義廣告分片URL關鍵字:", + enUS: "User customed Ad keyword: " + ), ["customRangeFound"] = new TextContainer ( zhCN: "用户自定义下载范围:", @@ -346,6 +352,12 @@ namespace N_m3u8DL_RE.Common.Resource zhTW: "手動設置直播列表刷新間隔", enUS: "Manually set the live playlist refresh interval" ), + ["cmd_adKeyword"] = new TextContainer + ( + zhCN: "设置广告分片的URL关键字(正则表达式)", + zhTW: "設置廣告分片的URL關鍵字(正則表達式)", + enUS: "Set URL keywords (regular expressions) for AD segments" + ), ["cmd_liveTakeCount"] = new TextContainer ( zhCN: "手动设置录制直播时首次获取分片的数量", diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs index d292bdd..68742f5 100644 --- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs +++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs @@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine { internal partial class CommandInvoker { - public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230707"; + public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230712"; [GeneratedRegex("((best|worst)\\d*|all)")] private static partial Regex ForStrRegex(); @@ -57,6 +57,8 @@ namespace N_m3u8DL_RE.CommandLine private readonly static Option BaseUrl = new(new string[] { "--base-url" }, description: ResString.cmd_baseUrl); private readonly static Option ConcurrentDownload = new(new string[] { "-mt", "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false); private readonly static Option NoLog = new(new string[] { "--no-log" }, description: ResString.cmd_noLog, getDefaultValue: () => false); + private readonly static Option AdKeywords = new(new string[] { "--ad-keyword" }, description: ResString.cmd_adKeyword) { ArgumentHelpName = "REG" }; + //代理选项 private readonly static Option UseSystemProxy = new(new string[] { "--use-system-proxy" }, description: ResString.cmd_useSystemProxy, getDefaultValue: () => true); @@ -499,6 +501,7 @@ namespace N_m3u8DL_RE.CommandLine LiveTakeCount = bindingContext.ParseResult.GetValueForOption(LiveTakeCount), NoDateInfo = bindingContext.ParseResult.GetValueForOption(NoDateInfo), NoLog = bindingContext.ParseResult.GetValueForOption(NoLog), + AdKeywords = bindingContext.ParseResult.GetValueForOption(AdKeywords), }; if (bindingContext.ParseResult.HasOption(CustomHLSMethod)) option.CustomHLSMethod = bindingContext.ParseResult.GetValueForOption(CustomHLSMethod); @@ -564,7 +567,7 @@ namespace N_m3u8DL_RE.CommandLine MuxAfterDone, CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, CustomRange, TaskStartAt, LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveFixVttByAudio, LiveRecordLimit, LiveWaitTime, LiveTakeCount, - MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, MoreHelp + MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, AdKeywords, MoreHelp }; rootCommand.TreatUnmatchedTokensAsErrors = true; diff --git a/src/N_m3u8DL-RE/CommandLine/MyOption.cs b/src/N_m3u8DL-RE/CommandLine/MyOption.cs index c346fa1..e4f19c4 100644 --- a/src/N_m3u8DL-RE/CommandLine/MyOption.cs +++ b/src/N_m3u8DL-RE/CommandLine/MyOption.cs @@ -17,6 +17,10 @@ namespace N_m3u8DL_RE.CommandLine /// public Dictionary Headers { get; set; } = new Dictionary(); /// + /// See: . + /// + public string[]? AdKeywords { get; set; } + /// /// See: . /// public string[]? Keys { get; set; } diff --git a/src/N_m3u8DL-RE/Program.cs b/src/N_m3u8DL-RE/Program.cs index 10f8ed6..b522fb5 100644 --- a/src/N_m3u8DL-RE/Program.cs +++ b/src/N_m3u8DL-RE/Program.cs @@ -304,6 +304,9 @@ namespace N_m3u8DL_RE if (!livingFlag) FilterUtil.ApplyCustomRange(selectedStreams, option.CustomRange); + //应用用户自定义的广告分片关键字 + FilterUtil.CleanAd(selectedStreams, option.AdKeywords); + //记录文件 extractor.RawFiles["meta_selected.json"] = GlobalUtil.ConvertToJson(selectedStreams); diff --git a/src/N_m3u8DL-RE/Util/FilterUtil.cs b/src/N_m3u8DL-RE/Util/FilterUtil.cs index 0ad664d..0f57a53 100644 --- a/src/N_m3u8DL-RE/Util/FilterUtil.cs +++ b/src/N_m3u8DL-RE/Util/FilterUtil.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace N_m3u8DL_RE.Util @@ -227,5 +228,41 @@ namespace N_m3u8DL_RE.Util stream.SkippedDuration = skippedDur; } } + + /// + /// 根据用户输入,清除广告分片 + /// + /// + /// + public static void CleanAd(List selectedSteams, string[]? keywords) + { + if (keywords == null) return; + var regList = keywords.Select(s => new Regex(s)); + foreach ( var reg in regList) + { + Logger.InfoMarkUp($"{ResString.customAdKeywordsFound}[Cyan underline]{reg}[/]"); + } + + foreach (var stream in selectedSteams) + { + if (stream.Playlist == null) continue; + foreach (var part in stream.Playlist.MediaParts) + { + //没有找到广告分片 + if (part.MediaSegments.All(x => regList.All(reg => !reg.IsMatch(x.Url)))) + { + continue; + } + //找到广告分片 清理 + else + { + part.MediaSegments = part.MediaSegments.Where(x => regList.All(reg => !reg.IsMatch(x.Url))).ToList(); + } + } + + //清理已经为空的 part + stream.Playlist.MediaParts = stream.Playlist.MediaParts.Where(x => x.MediaSegments.Count > 0).ToList(); + } + } } }