增加代理、自定义HLS KEY选项
This commit is contained in:
parent
0b02ecd2c8
commit
e84558d908
|
@ -36,6 +36,9 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
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_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_customHLSKey { get => GetText("cmd_customHLSKey"); }
|
||||||
|
public static string cmd_customHLSIv { get => GetText("cmd_customHLSIv"); }
|
||||||
public static string cmd_Input { get => GetText("cmd_Input"); }
|
public static string cmd_Input { get => GetText("cmd_Input"); }
|
||||||
public static string cmd_keys { get => GetText("cmd_keys"); }
|
public static string cmd_keys { get => GetText("cmd_keys"); }
|
||||||
public static string cmd_keyText { get => GetText("cmd_keyText"); }
|
public static string cmd_keyText { get => GetText("cmd_keyText"); }
|
||||||
|
@ -57,6 +60,7 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
public static string cmd_urlProcessorArgs { get => GetText("cmd_urlProcessorArgs"); }
|
public static string cmd_urlProcessorArgs { get => GetText("cmd_urlProcessorArgs"); }
|
||||||
public static string cmd_useShakaPackager { get => GetText("cmd_useShakaPackager"); }
|
public static string cmd_useShakaPackager { get => GetText("cmd_useShakaPackager"); }
|
||||||
public static string cmd_concurrentDownload { get => GetText("cmd_concurrentDownload"); }
|
public static string cmd_concurrentDownload { get => GetText("cmd_concurrentDownload"); }
|
||||||
|
public static string cmd_useSystemProxy { get => GetText("cmd_useSystemProxy"); }
|
||||||
public static string cmd_liveKeepSegments { get => GetText("cmd_liveKeepSegments"); }
|
public static string cmd_liveKeepSegments { get => GetText("cmd_liveKeepSegments"); }
|
||||||
public static string cmd_liveRecordLimit { get => GetText("cmd_liveRecordLimit"); }
|
public static string cmd_liveRecordLimit { get => GetText("cmd_liveRecordLimit"); }
|
||||||
public static string cmd_liveRealTimeMerge { get => GetText("cmd_liveRealTimeMerge"); }
|
public static string cmd_liveRealTimeMerge { get => GetText("cmd_liveRealTimeMerge"); }
|
||||||
|
|
|
@ -244,17 +244,41 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
zhTW: "錄製直播時即時合併",
|
zhTW: "錄製直播時即時合併",
|
||||||
enUS: "Real-time merge into file when recording live"
|
enUS: "Real-time merge into file when recording live"
|
||||||
),
|
),
|
||||||
|
["cmd_useSystemProxy"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "使用系统默认代理",
|
||||||
|
zhTW: "使用系統默認代理",
|
||||||
|
enUS: "Use system default proxy"
|
||||||
|
),
|
||||||
["cmd_livePerformAsVod"] = new TextContainer
|
["cmd_livePerformAsVod"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "以点播方式下载直播流",
|
zhCN: "以点播方式下载直播流",
|
||||||
zhTW: "以點播方式下載直播流",
|
zhTW: "以點播方式下載直播流",
|
||||||
enUS: "Download live streams as vod"
|
enUS: "Download live streams as vod"
|
||||||
),
|
),
|
||||||
|
["cmd_customHLSMethod"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
||||||
|
zhTW: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
||||||
|
enUS: "Set HLS encryption method (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)"
|
||||||
|
),
|
||||||
|
["cmd_customHLSKey"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "指定HLS解密KEY. 可以是文件, HEX或Base64",
|
||||||
|
zhTW: "指定HLS解密KEY. 可以是文件, HEX或Base64",
|
||||||
|
enUS: "Set the HLS decryption key. Can be file, HEX or Base64"
|
||||||
|
),
|
||||||
|
["cmd_customHLSIv"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "指定HLS解密IV. 可以是文件, HEX或Base64",
|
||||||
|
zhTW: "指定HLS解密IV. 可以是文件, HEX或Base64",
|
||||||
|
enUS: "Set the HLS decryption iv. Can be file, HEX or Base64"
|
||||||
|
),
|
||||||
["cmd_liveKeepSegments"] = new TextContainer
|
["cmd_liveKeepSegments"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "录制直播并开启实时合并时依然保留分片",
|
zhCN: "录制直播并开启实时合并时依然保留分片",
|
||||||
zhTW: "錄製直播並開啟即時合併時依然保留分片",
|
zhTW: "錄製直播並開啟即時合併時依然保留分片",
|
||||||
enUS: "Keep segments when recording a live broadcast and enable liveRealTimeMerge"
|
enUS: "Keep segments when recording a live (liveRealTimeMerge enabled)"
|
||||||
),
|
),
|
||||||
["cmd_liveRecordLimit"] = new TextContainer
|
["cmd_liveRecordLimit"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
@ -276,9 +300,9 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
),
|
),
|
||||||
["cmd_selectVideo"] = new TextContainer
|
["cmd_selectVideo"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的视频流. 输入 \"--morehelp select-video\" 以查看详细信息.",
|
zhCN: "通过正则表达式选择符合要求的视频流. 输入 \"--morehelp select-video\" 以查看详细信息",
|
||||||
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_selectVideo_more"] = new TextContainer
|
["cmd_selectVideo_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
@ -312,9 +336,9 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
),
|
),
|
||||||
["cmd_selectAudio"] = new TextContainer
|
["cmd_selectAudio"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的音频流. 输入 \"--morehelp select-audio\" 以查看详细信息.",
|
zhCN: "通过正则表达式选择符合要求的音频流. 输入 \"--morehelp select-audio\" 以查看详细信息",
|
||||||
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_selectAudio_more"] = new TextContainer
|
["cmd_selectAudio_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
@ -345,9 +369,9 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
),
|
),
|
||||||
["cmd_selectSubtitle"] = new TextContainer
|
["cmd_selectSubtitle"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的字幕流. 输入 \"--morehelp select-subtitle\" 以查看详细信息.",
|
zhCN: "通过正则表达式选择符合要求的字幕流. 输入 \"--morehelp select-subtitle\" 以查看详细信息",
|
||||||
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_selectSubtitle_more"] = new TextContainer
|
["cmd_selectSubtitle_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
@ -411,15 +435,15 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
),
|
),
|
||||||
["cmd_muxAfterDone"] = new TextContainer
|
["cmd_muxAfterDone"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "所有工作完成时尝试混流分离的音视频. 输入 \"--morehelp mux-after-done\" 以查看详细信息.",
|
zhCN: "所有工作完成时尝试混流分离的音视频. 输入 \"--morehelp mux-after-done\" 以查看详细信息",
|
||||||
zhTW: "所有工作完成時嘗試混流分離的影音. 輸入 \"--morehelp mux-after-done\" 以查看詳細訊息.",
|
zhTW: "所有工作完成時嘗試混流分離的影音. 輸入 \"--morehelp mux-after-done\" 以查看詳細訊息",
|
||||||
enUS: "When all works is done, try to mux the downloaded streams. Use \"--morehelp mux-after-done\" for more details."
|
enUS: "When all works is done, try to mux the downloaded streams. Use \"--morehelp mux-after-done\" for more details"
|
||||||
),
|
),
|
||||||
["cmd_muxImport"] = new TextContainer
|
["cmd_muxImport"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "混流时引入外部媒体文件. 输入 \"--morehelp mux-import\" 以查看详细信息.",
|
zhCN: "混流时引入外部媒体文件. 输入 \"--morehelp mux-import\" 以查看详细信息",
|
||||||
zhTW: "混流時引入外部媒體檔案. 輸入 \"--morehelp mux-import\" 以查看詳細訊息.",
|
zhTW: "混流時引入外部媒體檔案. 輸入 \"--morehelp mux-import\" 以查看詳細訊息",
|
||||||
enUS: "When MuxAfterDone enabled, allow to import local media files. Use \"--morehelp mux-import\" for more details."
|
enUS: "When MuxAfterDone enabled, allow to import local media files. Use \"--morehelp mux-import\" for more details"
|
||||||
),
|
),
|
||||||
["cmd_muxImport_more"] = new TextContainer
|
["cmd_muxImport_more"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
|
|
@ -23,13 +23,14 @@ namespace N_m3u8DL_RE.Common.Util
|
||||||
{
|
{
|
||||||
public class HTTPUtil
|
public class HTTPUtil
|
||||||
{
|
{
|
||||||
|
public static readonly HttpClientHandler HttpClientHandler = new()
|
||||||
public static readonly HttpClient AppHttpClient = new(new HttpClientHandler
|
|
||||||
{
|
{
|
||||||
AllowAutoRedirect = false,
|
AllowAutoRedirect = false,
|
||||||
AutomaticDecompression = DecompressionMethods.All,
|
AutomaticDecompression = DecompressionMethods.All,
|
||||||
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
|
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
|
||||||
})
|
};
|
||||||
|
|
||||||
|
public static readonly HttpClient AppHttpClient = new(HttpClientHandler)
|
||||||
{
|
{
|
||||||
Timeout = TimeSpan.FromMinutes(2)
|
Timeout = TimeSpan.FromMinutes(2)
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,25 @@ namespace N_m3u8DL_RE.Common.Util
|
||||||
return BitConverter.ToString(data).Replace("-", split);
|
return BitConverter.ToString(data).Replace("-", split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是不是HEX字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParseHexString(string input, out byte[]? bytes)
|
||||||
|
{
|
||||||
|
bytes = null;
|
||||||
|
input = input.ToUpper();
|
||||||
|
if (input.StartsWith("0X"))
|
||||||
|
input = input[2..];
|
||||||
|
if (input.Length % 2 != 0)
|
||||||
|
return false;
|
||||||
|
if (input.Any(c => !"0123456789ABCDEF".Contains(c)))
|
||||||
|
return false;
|
||||||
|
bytes = HexToBytes(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] HexToBytes(string hex)
|
public static byte[] HexToBytes(string hex)
|
||||||
{
|
{
|
||||||
hex = hex.Trim();
|
hex = hex.Trim();
|
||||||
|
|
|
@ -318,18 +318,6 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
//解析KEY
|
//解析KEY
|
||||||
else if (line.StartsWith(HLSTags.ext_x_key))
|
else if (line.StartsWith(HLSTags.ext_x_key))
|
||||||
{
|
{
|
||||||
//自定义KEY情况 不读取当前行的KEY信息.
|
|
||||||
//对于IV,没自定义且当前行有IV的话 就用
|
|
||||||
if (ParserConfig.CustomeKey != null)
|
|
||||||
{
|
|
||||||
currentEncryptInfo.Key = ParserConfig.CustomeKey;
|
|
||||||
if (ParserConfig.CustomeIV == null && line.Contains("IV=0x"))
|
|
||||||
currentEncryptInfo.IV = HexUtil.HexToBytes(ParserUtil.GetAttribute(line, "IV"));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var iv = ParserUtil.GetAttribute(line, "IV");
|
|
||||||
var method = ParserUtil.GetAttribute(line, "METHOD");
|
|
||||||
var uri = ParserUtil.GetAttribute(line, "URI");
|
var uri = ParserUtil.GetAttribute(line, "URI");
|
||||||
var uri_last = ParserUtil.GetAttribute(lastKeyLine, "URI");
|
var uri_last = ParserUtil.GetAttribute(lastKeyLine, "URI");
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,21 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
|
||||||
Logger.Debug("METHOD:{},URI:{},IV:{}", method, uri, iv);
|
Logger.Debug("METHOD:{},URI:{},IV:{}", method, uri, iv);
|
||||||
|
|
||||||
var encryptInfo = new EncryptInfo(method);
|
var encryptInfo = new EncryptInfo(method);
|
||||||
|
|
||||||
|
//处理自定义加密方式
|
||||||
|
if (parserConfig.CustomMethod != null)
|
||||||
|
{
|
||||||
|
encryptInfo.Method = parserConfig.CustomMethod.Value;
|
||||||
|
Logger.Warn("METHOD changed to {}", method, encryptInfo.Method);
|
||||||
|
}
|
||||||
|
|
||||||
//IV
|
//IV
|
||||||
if (!string.IsNullOrEmpty(iv))
|
if (!string.IsNullOrEmpty(iv))
|
||||||
{
|
{
|
||||||
encryptInfo.IV = HexUtil.HexToBytes(iv);
|
encryptInfo.IV = HexUtil.HexToBytes(iv);
|
||||||
}
|
}
|
||||||
if (parserConfig.CustomeIV != null)
|
//自定义IV
|
||||||
|
if (parserConfig.CustomeIV != null && parserConfig.CustomeIV.Length > 0)
|
||||||
{
|
{
|
||||||
encryptInfo.IV = parserConfig.CustomeIV;
|
encryptInfo.IV = parserConfig.CustomeIV;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +50,7 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
|
||||||
//KEY
|
//KEY
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (parserConfig.CustomeKey != null)
|
if (parserConfig.CustomeKey != null && parserConfig.CustomeKey.Length > 0)
|
||||||
{
|
{
|
||||||
encryptInfo.Key = parserConfig.CustomeKey;
|
encryptInfo.Key = parserConfig.CustomeKey;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +84,7 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
|
||||||
{
|
{
|
||||||
Logger.WarnMarkUp($"[grey]{_ex.Message.EscapeMarkup()} retryCount: {retryCount}[/]");
|
Logger.WarnMarkUp($"[grey]{_ex.Message.EscapeMarkup()} retryCount: {retryCount}[/]");
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
if (retryCount > 0) goto getHttpKey;
|
if (retryCount-- > 0) goto getHttpKey;
|
||||||
else throw;
|
else throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using N_m3u8DL_RE.Common.Log;
|
using N_m3u8DL_RE.Common.Enum;
|
||||||
|
using N_m3u8DL_RE.Common.Log;
|
||||||
using N_m3u8DL_RE.Common.Resource;
|
using N_m3u8DL_RE.Common.Resource;
|
||||||
|
using N_m3u8DL_RE.Common.Util;
|
||||||
using N_m3u8DL_RE.Entity;
|
using N_m3u8DL_RE.Entity;
|
||||||
using N_m3u8DL_RE.Enum;
|
using N_m3u8DL_RE.Enum;
|
||||||
using N_m3u8DL_RE.Util;
|
using N_m3u8DL_RE.Util;
|
||||||
|
@ -48,9 +50,18 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
private readonly static Option<string?> BaseUrl = new(new string[] { "--base-url" }, description: ResString.cmd_baseUrl);
|
private readonly static Option<string?> BaseUrl = new(new string[] { "--base-url" }, description: ResString.cmd_baseUrl);
|
||||||
private readonly static Option<bool> ConcurrentDownload = new(new string[] { "-mt", "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false);
|
private readonly static Option<bool> ConcurrentDownload = new(new string[] { "-mt", "--concurrent-download" }, description: ResString.cmd_concurrentDownload, getDefaultValue: () => false);
|
||||||
|
|
||||||
|
//代理选项
|
||||||
|
private readonly static Option<bool> UseSystemProxy = new(new string[] { "--use-system-proxy" }, description: ResString.cmd_useSystemProxy, getDefaultValue: () => true);
|
||||||
|
|
||||||
//morehelp
|
//morehelp
|
||||||
private readonly static Option<string?> MoreHelp = new(new string[] { "--morehelp" }, description: ResString.cmd_moreHelp) { ArgumentHelpName = "OPTION" };
|
private readonly static Option<string?> MoreHelp = new(new string[] { "--morehelp" }, description: ResString.cmd_moreHelp) { ArgumentHelpName = "OPTION" };
|
||||||
|
|
||||||
|
//自定义KEY等
|
||||||
|
private readonly static Option<EncryptMethod?> CustomHLSMethod = new(name: "--custom-hls-method", description: ResString.cmd_customHLSMethod) { ArgumentHelpName = "METHOD" };
|
||||||
|
private readonly static Option<byte[]?> CustomHLSKey = new(name: "--custom-hls-key", description: ResString.cmd_customHLSKey, parseArgument: ParseHLSCustomKey) { ArgumentHelpName = "FILE|HEX|BASE64" };
|
||||||
|
private readonly static Option<byte[]?> CustomHLSIv = new(name: "--custom-hls-iv", description: ResString.cmd_customHLSIv, parseArgument: ParseHLSCustomKey) { ArgumentHelpName = "FILE|HEX|BASE64" };
|
||||||
|
|
||||||
|
|
||||||
//直播相关
|
//直播相关
|
||||||
private readonly static Option<bool> LivePerformAsVod = new(new string[] { "--live-perform-as-vod" }, description: ResString.cmd_livePerformAsVod, getDefaultValue: () => false);
|
private readonly static Option<bool> LivePerformAsVod = new(new string[] { "--live-perform-as-vod" }, description: ResString.cmd_livePerformAsVod, getDefaultValue: () => false);
|
||||||
private readonly static Option<bool> LiveRealTimeMerge = new(new string[] { "--live-real-time-merge" }, description: ResString.cmd_liveRealTimeMerge, getDefaultValue: () => false);
|
private readonly static Option<bool> LiveRealTimeMerge = new(new string[] { "--live-real-time-merge" }, description: ResString.cmd_liveRealTimeMerge, getDefaultValue: () => false);
|
||||||
|
@ -65,6 +76,32 @@ 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" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解析自定义KEY
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static byte[]? ParseHLSCustomKey(ArgumentResult result)
|
||||||
|
{
|
||||||
|
var input = result.Tokens.First().Value;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
return null;
|
||||||
|
if (File.Exists(input))
|
||||||
|
return File.ReadAllBytes(input);
|
||||||
|
else if (HexUtil.TryParseHexString(input, out byte[]? bytes))
|
||||||
|
return bytes;
|
||||||
|
else
|
||||||
|
return Convert.FromBase64String(input);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
result.ErrorMessage = "error in parse hls custom key: " + input;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解析录制直播时长限制
|
/// 解析录制直播时长限制
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -302,6 +339,10 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
LiveKeepSegments = bindingContext.ParseResult.GetValueForOption(LiveKeepSegments),
|
LiveKeepSegments = bindingContext.ParseResult.GetValueForOption(LiveKeepSegments),
|
||||||
LiveRecordLimit = bindingContext.ParseResult.GetValueForOption(LiveRecordLimit),
|
LiveRecordLimit = bindingContext.ParseResult.GetValueForOption(LiveRecordLimit),
|
||||||
LivePerformAsVod = bindingContext.ParseResult.GetValueForOption(LivePerformAsVod),
|
LivePerformAsVod = bindingContext.ParseResult.GetValueForOption(LivePerformAsVod),
|
||||||
|
UseSystemProxy = bindingContext.ParseResult.GetValueForOption(UseSystemProxy),
|
||||||
|
CustomHLSMethod = bindingContext.ParseResult.GetValueForOption(CustomHLSMethod),
|
||||||
|
CustomHLSKey = bindingContext.ParseResult.GetValueForOption(CustomHLSKey),
|
||||||
|
CustomHLSIv = bindingContext.ParseResult.GetValueForOption(CustomHLSIv),
|
||||||
};
|
};
|
||||||
|
|
||||||
var parsedHeaders = bindingContext.ParseResult.GetValueForOption(Headers);
|
var parsedHeaders = bindingContext.ParseResult.GetValueForOption(Headers);
|
||||||
|
@ -362,6 +403,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
FFmpegBinaryPath,
|
FFmpegBinaryPath,
|
||||||
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
|
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
|
||||||
MuxAfterDone,
|
MuxAfterDone,
|
||||||
|
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy,
|
||||||
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LiveRecordLimit,
|
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LiveRecordLimit,
|
||||||
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, MoreHelp
|
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, MoreHelp
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using N_m3u8DL_RE.Common.Log;
|
using N_m3u8DL_RE.Common.Enum;
|
||||||
|
using N_m3u8DL_RE.Common.Log;
|
||||||
using N_m3u8DL_RE.Entity;
|
using N_m3u8DL_RE.Entity;
|
||||||
using N_m3u8DL_RE.Enum;
|
using N_m3u8DL_RE.Enum;
|
||||||
|
|
||||||
|
@ -123,6 +124,10 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool LivePerformAsVod { get; set; }
|
public bool LivePerformAsVod { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.UseSystemProxy"/>.
|
||||||
|
/// </summary>
|
||||||
|
public bool UseSystemProxy { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// See: <see cref="CommandInvoker.SubtitleFormat"/>.
|
/// See: <see cref="CommandInvoker.SubtitleFormat"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SubtitleFormat SubtitleFormat { get; set; }
|
public SubtitleFormat SubtitleFormat { get; set; }
|
||||||
|
@ -174,6 +179,18 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
/// See: <see cref="CommandInvoker.SubtitleFilter"/>.
|
/// See: <see cref="CommandInvoker.SubtitleFilter"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StreamFilter? SubtitleFilter { get; set; }
|
public StreamFilter? SubtitleFilter { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.CustomHLSMethod"/>.
|
||||||
|
/// </summary>
|
||||||
|
public EncryptMethod? CustomHLSMethod { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.CustomHLSKey"/>.
|
||||||
|
/// </summary>
|
||||||
|
public byte[]? CustomHLSKey { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.CustomHLSIv"/>.
|
||||||
|
/// </summary>
|
||||||
|
public byte[]? CustomHLSIv { get; set; }
|
||||||
public bool MuxKeepFiles { get; set; }
|
public bool MuxKeepFiles { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -58,6 +58,11 @@ namespace N_m3u8DL_RE
|
||||||
{
|
{
|
||||||
Logger.LogLevel = option.LogLevel;
|
Logger.LogLevel = option.LogLevel;
|
||||||
|
|
||||||
|
if (option.UseSystemProxy == false)
|
||||||
|
{
|
||||||
|
HTTPUtil.HttpClientHandler.UseProxy = false;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//检查互斥的选项
|
//检查互斥的选项
|
||||||
|
@ -130,7 +135,10 @@ namespace N_m3u8DL_RE
|
||||||
AppendUrlParams = option.AppendUrlParams,
|
AppendUrlParams = option.AppendUrlParams,
|
||||||
UrlProcessorArgs = option.UrlProcessorArgs,
|
UrlProcessorArgs = option.UrlProcessorArgs,
|
||||||
BaseUrl = option.BaseUrl!,
|
BaseUrl = option.BaseUrl!,
|
||||||
Headers = headers
|
Headers = headers,
|
||||||
|
CustomMethod = option.CustomHLSMethod,
|
||||||
|
CustomeKey = option.CustomHLSKey,
|
||||||
|
CustomeIV = option.CustomHLSIv,
|
||||||
};
|
};
|
||||||
|
|
||||||
//demo1
|
//demo1
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using N_m3u8DL_RE.Common.Log;
|
using N_m3u8DL_RE.Common.Log;
|
||||||
using N_m3u8DL_RE.Common.Resource;
|
using N_m3u8DL_RE.Common.Resource;
|
||||||
|
using N_m3u8DL_RE.Common.Util;
|
||||||
using N_m3u8DL_RE.Entity;
|
using N_m3u8DL_RE.Entity;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -14,15 +15,7 @@ namespace N_m3u8DL_RE.Util
|
||||||
{
|
{
|
||||||
internal class DownloadUtil
|
internal class DownloadUtil
|
||||||
{
|
{
|
||||||
private static readonly HttpClient AppHttpClient = new(new HttpClientHandler
|
private static readonly HttpClient AppHttpClient = HTTPUtil.AppHttpClient;
|
||||||
{
|
|
||||||
AllowAutoRedirect = false,
|
|
||||||
AutomaticDecompression = DecompressionMethods.All,
|
|
||||||
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromMinutes(2)
|
|
||||||
};
|
|
||||||
|
|
||||||
public static async Task<DownloadResult> DownloadToFileAsync(string url, string path, SpeedContainer speedContainer, Dictionary<string, string>? headers = null, long? fromPosition = null, long? toPosition = null)
|
public static async Task<DownloadResult> DownloadToFileAsync(string url, string path, SpeedContainer speedContainer, Dictionary<string, string>? headers = null, long? fromPosition = null, long? toPosition = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,9 +8,9 @@ namespace N_m3u8DL_RE.Util
|
||||||
{
|
{
|
||||||
internal class OtherUtil
|
internal class OtherUtil
|
||||||
{
|
{
|
||||||
public static Dictionary<string,string> SplitHeaderArrayToDic(string[]? headers)
|
public static Dictionary<string, string> SplitHeaderArrayToDic(string[]? headers)
|
||||||
{
|
{
|
||||||
Dictionary<string,string> dic = new();
|
Dictionary<string, string> dic = new();
|
||||||
|
|
||||||
if (headers != null)
|
if (headers != null)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue