diff --git a/N_m3u8DL-CLI/DownloadManager.cs b/N_m3u8DL-CLI/DownloadManager.cs index 2b36edf..5a0efb3 100644 --- a/N_m3u8DL-CLI/DownloadManager.cs +++ b/N_m3u8DL-CLI/DownloadManager.cs @@ -15,6 +15,7 @@ class DownloadManager private int stopCount = 0; //速度为零的停止 private int timeOut = 10000; //超时设置 private static double downloadedSize = 0; //已下载大小 + private static bool disableIntegrityCheck = false; //关闭完整性检查 private string jsonFile = string.Empty; private string headers = string.Empty; @@ -58,6 +59,7 @@ class DownloadManager public static int CalcTime { get => calcTime; set => calcTime = value; } public static int Count { get => count; set => count = value; } public static int PartsCount { get => partsCount; set => partsCount = value; } + public static bool DisableIntegrityCheck { get => disableIntegrityCheck; set => disableIntegrityCheck = value; } public void DoDownload() { @@ -335,11 +337,19 @@ public void DoDownload() public void IsComplete(int segCount) { int tsCount = 0; + + if (DisableIntegrityCheck) + { + tsCount = segCount; + goto ll; + } + for (int i = 0; i < PartsCount; i++) { tsCount += Global.GetFileCount(DownDir + "\\Part_" + i.ToString(partsPadZero), ".ts"); } + ll: if (tsCount != segCount) { LOGGER.PrintLine("完成数量 " + tsCount + " / " + segCount); @@ -356,7 +366,7 @@ public void IsComplete(int segCount) } else //开始合并 { - LOGGER.PrintLine("已下载完毕"); + LOGGER.PrintLine("已下载完毕" + (DisableIntegrityCheck ? "(已关闭完整性检查)" : "")); Console.WriteLine(); if (NoMerge == false) { diff --git a/N_m3u8DL-CLI/Global.cs b/N_m3u8DL-CLI/Global.cs index 72bf092..6f3a5f0 100644 --- a/N_m3u8DL-CLI/Global.cs +++ b/N_m3u8DL-CLI/Global.cs @@ -30,8 +30,8 @@ class Global /*===============================================================================*/ - static string nowVer = "2.3.4"; - static string nowDate = "20191018"; + static string nowVer = "2.4.0"; + static string nowDate = "20191024"; public static void WriteInit() { Console.Clear(); diff --git a/N_m3u8DL-CLI/Parser.cs b/N_m3u8DL-CLI/Parser.cs index 9d11ad2..3b112e4 100644 --- a/N_m3u8DL-CLI/Parser.cs +++ b/N_m3u8DL-CLI/Parser.cs @@ -27,6 +27,8 @@ class Parser private string m3u8Url = string.Empty; private string downDir = string.Empty; private string downName = string.Empty; + private string keyFile = string.Empty; + private string keyBase64 = string.Empty; private long bestBandwidth = 0; private string bestUrl = string.Empty; private string bestUrlAudio = string.Empty; @@ -57,6 +59,8 @@ class Parser public static bool DelAd { get => delAd; set => delAd = value; } public static string DurStart { get => durStart; set => durStart = value; } public static string DurEnd { get => durEnd; set => durEnd = value; } + public string KeyFile { get => keyFile; set => keyFile = value; } + public string KeyBase64 { get => keyBase64; set => keyBase64 = value; } public void Parse() { @@ -110,10 +114,28 @@ public void Parse() //如果BaseUrl为空则截取字符串充当 if (BaseUrl == "") - BaseUrl = GetBaseUrl(M3u8Url, headers); + { + if (new Regex("#YUMING\\|(.*)").IsMatch(m3u8Content)) + BaseUrl = new Regex("#YUMING\\|(.*)").Match(m3u8Content).Groups[1].Value; + else + BaseUrl = GetBaseUrl(M3u8Url, headers); + } LOGGER.WriteLine("Parsing Content"); LOGGER.PrintLine("解析m3u8内容"); + + if (!string.IsNullOrEmpty(keyBase64)) + { + string line = $"#EXT-X-KEY:METHOD=AES-128,URI=\"base64:{keyBase64}\""; + m3u8CurrentKey = ParseKey(line); + } + if (!string.IsNullOrEmpty(keyFile)) + { + Uri u = new Uri(keyFile); + string line = $"#EXT-X-KEY:METHOD=AES-128,URI=\"{u.ToString()}\""; + m3u8CurrentKey = ParseKey(line); + } + //逐行分析 using (StringReader sr = new StringReader(m3u8Content)) { @@ -192,7 +214,7 @@ public void Parse() else if (line.StartsWith(HLSTags.ext_x_version)) ; else if (line.StartsWith(HLSTags.ext_x_allow_cache)) ; //解析KEY - else if (line.StartsWith(HLSTags.ext_x_key)) + else if (line.StartsWith(HLSTags.ext_x_key) && string.IsNullOrEmpty(keyFile) && string.IsNullOrEmpty(keyBase64)) { m3u8CurrentKey = ParseKey(line); //存储为上一行的key信息 diff --git a/N_m3u8DL-CLI/Program.cs b/N_m3u8DL-CLI/Program.cs index 00e2e01..9125735 100644 --- a/N_m3u8DL-CLI/Program.cs +++ b/N_m3u8DL-CLI/Program.cs @@ -199,6 +199,10 @@ namespace N_m3u8DL_CLI.NetCore /// - 细节优化 /// 2019年10月18日 /// - 去掉了优酷DRM设备参数更改 + /// 2019年10月23日 + /// - 增加disableIntegrityCheck选项 + /// 2019年10月24日 + /// - 捕获Ctrl+C退出,移动光标到正确位置 /// /// @@ -216,11 +220,13 @@ public static bool HandlerRoutine(int CtrlType) LOGGER.WriteLine("Exited: Ctrl + C" + "\r\n\r\nTask End: " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); //Ctrl+C关闭 Console.CursorVisible = true; + Console.SetCursorPosition(0, LOGGER.CursorIndex); break; case 2: LOGGER.WriteLine("Exited: Force" + "\r\n\r\nTask End: " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); //按控制台关闭按钮关闭 Console.CursorVisible = true; + Console.SetCursorPosition(0, LOGGER.CursorIndex); break; } return false; @@ -228,6 +234,7 @@ public static bool HandlerRoutine(int CtrlType) static void Main(string[] args) { + SetConsoleCtrlHandler(cancelHandler, true); try { //goto httplitsen; @@ -281,6 +288,8 @@ static void Main(string[] args) int timeOut = 10; //默认10秒 string baseUrl = ""; string reqHeaders = ""; + string keyFile = ""; + string keyBase64 = ""; string muxSetJson = "MUXSETS.json"; string workDir = CURRENT_PATH + "\\Downloads"; bool muxFastStart = false; @@ -316,6 +325,8 @@ static void Main(string[] args) --retryCount Count 设定程序的重试次数(默认为15) --timeOut Sec 设定程序网络请求的超时时间(单位为秒,默认为10秒) --muxSetJson File 使用外部json文件定义混流选项 + --useKeyFile File 使用外部16字节文件定义AES-128解密KEY + --useKeyBase64 Base64String 使用Base64字符串定义AES-128解密KEY --downloadRange Range 仅下载视频的一部分分片或长度 --stopSpeed Number 当速度低于此值时,重试(单位为KB/s) --maxSpeed Number 设置下载速度上限(单位为KB/s) @@ -326,7 +337,8 @@ static void Main(string[] args) --enableAudioOnly 合并时仅封装音频轨道 --disableDateInfo 关闭混流中的日期写入 --noMerge 禁用自动合并 - --noProxy 不自动使用系统代理"); + --noProxy 不自动使用系统代理 + --disableIntegrityCheck 不检测分片数量是否完整"); return; } if (arguments.Has("--enableDelAfterDone")) @@ -361,6 +373,10 @@ static void Main(string[] args) { muxFastStart = true; } + if (arguments.Has("--disableIntegrityCheck")) + { + DownloadManager.DisableIntegrityCheck = true; + } if (arguments.Has("--enableAudioOnly")) { Global.VIDEO_TYPE = "IGNORE"; @@ -378,6 +394,15 @@ static void Main(string[] args) { fileName = arguments.Get("--saveName").Next; } + if (arguments.Has("--useKeyFile")) + { + if (File.Exists(arguments.Get("--useKeyFile").Next)) + keyFile = arguments.Get("--useKeyFile").Next; + } + if (arguments.Has("--useKeyBase64")) + { + keyBase64 = arguments.Get("--useKeyBase64").Next; + } if (arguments.Has("--stopSpeed")) { Global.STOP_SPEED = Convert.ToInt64(arguments.Get("--stopSpeed").Next); @@ -511,6 +536,8 @@ static void Main(string[] args) parser.DownName = fileName; parser.DownDir = Path.Combine(workDir, parser.DownName); parser.M3u8Url = testurl; + parser.KeyBase64 = keyBase64; + parser.KeyFile = keyFile; if (baseUrl != "") parser.BaseUrl = baseUrl; parser.Headers = reqHeaders;