diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.Designer.cs b/src/N_m3u8DL-RE.Common/Resource/ResString.Designer.cs
index aed0669..64017c1 100644
--- a/src/N_m3u8DL-RE.Common/Resource/ResString.Designer.cs
+++ b/src/N_m3u8DL-RE.Common/Resource/ResString.Designer.cs
@@ -188,6 +188,15 @@ namespace N_m3u8DL_RE.Common.Resource {
}
}
+ ///
+ /// 查找类似 Set the kid-key file, the program will search the KEY with KID from the file.(Very large file are not recommended) 的本地化字符串。
+ ///
+ public static string cmd_keyText {
+ get {
+ return ResourceManager.GetString("cmd_keyText", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Failed to get KEY, ignore. 的本地化字符串。
///
@@ -494,6 +503,15 @@ namespace N_m3u8DL_RE.Common.Resource {
}
}
+ ///
+ /// 查找类似 Trying to search for KEY from text file... 的本地化字符串。
+ ///
+ public static string searchKey {
+ get {
+ return ResourceManager.GetString("searchKey", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Segment count check not pass, total: {}, downloaded: {}. 的本地化字符串。
///
diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.resx b/src/N_m3u8DL-RE.Common/Resource/ResString.resx
index 2e06829..59b6000 100644
--- a/src/N_m3u8DL-RE.Common/Resource/ResString.resx
+++ b/src/N_m3u8DL-RE.Common/Resource/ResString.resx
@@ -258,4 +258,10 @@
ffmpeg merging...
+
+ Set the kid-key file, the program will search the KEY with KID from the file.(Very large file are not recommended)
+
+
+ Trying to search for KEY from text file...
+
\ No newline at end of file
diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hans.resx b/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hans.resx
index f86d071..aad8e88 100644
--- a/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hans.resx
+++ b/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hans.resx
@@ -278,4 +278,10 @@
调用ffmpeg合并中...
+
+ 设置密钥文件,程序将从文件中按KID搜寻KEY以解密.(不建议使用特大文件)
+
+
+ 正在尝试从文本文件搜索KEY...
+
\ No newline at end of file
diff --git a/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hant.resx b/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hant.resx
index adbd381..57d407f 100644
--- a/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hant.resx
+++ b/src/N_m3u8DL-RE.Common/Resource/ResString.zh-Hant.resx
@@ -255,4 +255,10 @@
調用ffmpeg合併中...
+
+ 設置密鑰文件,程序將從文件中按KID搜尋KEY以解密.(不建議使用特大文件)
+
+
+ 正在嘗試從文本文件搜尋KEY...
+
\ No newline at end of file
diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs
index 2510f47..e651b05 100644
--- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs
+++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs
@@ -18,6 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
private readonly static Option UILanguage = new(new string[] { "--ui-language" }, description: ResString.cmd_uiLanguage);
private readonly static Option UrlProcessorArgs = new(new string[] { "--urlprocessor-args" }, description: ResString.cmd_urlProcessorArgs);
private readonly static Option Keys = new(new string[] { "--key" }, description: ResString.cmd_keys) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
+ private readonly static Option KeyTextFile = new(new string[] { "--key-text-file" }, description: ResString.cmd_keyText);
private readonly static Option Headers = new(new string[] { "-H", "--header" }, description: ResString.cmd_header) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
private readonly static Option LogLevel = new(name: "--log-level", description: ResString.cmd_logLevel, getDefaultValue: () => Common.Log.LogLevel.INFO);
private readonly static Option SubtitleFormat = new(name: "--sub-format", description: ResString.cmd_subFormat, getDefaultValue: () => Enum.SubtitleFormat.VTT);
@@ -69,6 +70,7 @@ namespace N_m3u8DL_RE.CommandLine
UseShakaPackager = bindingContext.ParseResult.GetValueForOption(UseShakaPackager),
DecryptionBinaryPath = bindingContext.ParseResult.GetValueForOption(DecryptionBinaryPath),
FFmpegBinaryPath = bindingContext.ParseResult.GetValueForOption(FFmpegBinaryPath),
+ KeyTextFile = bindingContext.ParseResult.GetValueForOption(KeyTextFile),
};
//在这里设置语言
@@ -93,12 +95,12 @@ namespace N_m3u8DL_RE.CommandLine
public static async Task InvokeArgs(string[] args, Func action)
{
- var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220808")
+ var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220811")
{
Input, TmpDir, SaveDir, SaveName, ThreadCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
FFmpegBinaryPath,
- LogLevel, UILanguage, UrlProcessorArgs, Keys, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption
+ LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption
};
rootCommand.TreatUnmatchedTokensAsErrors = true;
rootCommand.SetHandler(async (myOption) => await action(myOption), new MyOptionBinder());
diff --git a/src/N_m3u8DL-RE/CommandLine/MyOption.cs b/src/N_m3u8DL-RE/CommandLine/MyOption.cs
index 9e37bae..93a6685 100644
--- a/src/N_m3u8DL-RE/CommandLine/MyOption.cs
+++ b/src/N_m3u8DL-RE/CommandLine/MyOption.cs
@@ -18,6 +18,10 @@ namespace N_m3u8DL_RE.CommandLine
///
public string[]? Keys { get; set; }
///
+ /// See: .
+ ///
+ public string? KeyTextFile { get; set; }
+ ///
/// See: .
///
public string? UrlProcessorArgs { get; set; }
diff --git a/src/N_m3u8DL-RE/Config/DownloaderConfig.cs b/src/N_m3u8DL-RE/Config/DownloaderConfig.cs
index 290f9de..fba4eb4 100644
--- a/src/N_m3u8DL-RE/Config/DownloaderConfig.cs
+++ b/src/N_m3u8DL-RE/Config/DownloaderConfig.cs
@@ -31,6 +31,7 @@ namespace N_m3u8DL_RE.Config
UseShakaPackager = option.UseShakaPackager;
DecryptionBinaryPath = option.DecryptionBinaryPath;
FFmpegBinaryPath = option.FFmpegBinaryPath;
+ KeyTextFile = option.KeyTextFile;
}
///
@@ -105,6 +106,10 @@ namespace N_m3u8DL_RE.Config
///
public string[]? Keys { get; set; }
///
+ /// KID-KEY文件
+ ///
+ public string? KeyTextFile { get; set; }
+ ///
/// ffmpeg路径
///
public string? FFmpegBinaryPath { get; set; }
diff --git a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs
index 0306248..a1797d9 100644
--- a/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs
+++ b/src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs
@@ -105,6 +105,15 @@ namespace N_m3u8DL_RE.DownloadManager
{
var data = File.ReadAllBytes(result.ActualFilePath);
currentKID = ReadInit(data);
+ //从文件读取KEY
+ var _key = await MP4DecryptUtil.SearchKeyFromFile(DownloaderConfig.KeyTextFile, currentKID);
+ if (_key != null)
+ {
+ if (DownloaderConfig.Keys == null)
+ DownloaderConfig.Keys = new string[] { _key };
+ else
+ DownloaderConfig.Keys = DownloaderConfig.Keys.Concat(new string[] { _key }).ToArray();
+ }
//实时解密
if (DownloaderConfig.MP4RealTimeDecryption && streamSpec.Playlist.MediaInit.EncryptInfo.Method != Common.Enum.EncryptMethod.NONE)
{
@@ -387,6 +396,15 @@ namespace N_m3u8DL_RE.DownloadManager
var header = new byte[4096]; //4KB
fs.Read(header);
currentKID = ReadInit(header);
+ //从文件读取KEY
+ var _key = await MP4DecryptUtil.SearchKeyFromFile(DownloaderConfig.KeyTextFile, currentKID);
+ if (_key != null)
+ {
+ if (DownloaderConfig.Keys == null)
+ DownloaderConfig.Keys = new string[] { _key };
+ else
+ DownloaderConfig.Keys = DownloaderConfig.Keys.Concat(new string[] { _key }).ToArray();
+ }
}
}
var enc = output;
diff --git a/src/N_m3u8DL-RE/Program.cs b/src/N_m3u8DL-RE/Program.cs
index de8ff25..bfe87dc 100644
--- a/src/N_m3u8DL-RE/Program.cs
+++ b/src/N_m3u8DL-RE/Program.cs
@@ -49,7 +49,7 @@ namespace N_m3u8DL_RE
}
//预先检查
- if (option.Keys != null && option.Keys.Length > 0)
+ if ((option.Keys != null && option.Keys.Length > 0) || option.KeyTextFile != null)
{
if (string.IsNullOrEmpty(option.DecryptionBinaryPath))
{
diff --git a/src/N_m3u8DL-RE/Util/MP4DecryptUtil.cs b/src/N_m3u8DL-RE/Util/MP4DecryptUtil.cs
index 1676acc..218f7ad 100644
--- a/src/N_m3u8DL-RE/Util/MP4DecryptUtil.cs
+++ b/src/N_m3u8DL-RE/Util/MP4DecryptUtil.cs
@@ -1,4 +1,7 @@
-using System.Diagnostics;
+using N_m3u8DL_RE.Common.Log;
+using N_m3u8DL_RE.Common.Resource;
+using N_m3u8DL_RE.Config;
+using System.Diagnostics;
namespace N_m3u8DL_RE.Util
{
@@ -60,6 +63,8 @@ namespace N_m3u8DL_RE.Util
private static async Task RunCommandAsync(string name, string arg)
{
+ Logger.DebugMarkUp($"FileName: {name}");
+ Logger.DebugMarkUp($"Arguments: {arg}");
await Process.Start(new ProcessStartInfo()
{
FileName = name,
@@ -69,5 +74,32 @@ namespace N_m3u8DL_RE.Util
UseShellExecute = false
})!.WaitForExitAsync();
}
+
+ public static async Task SearchKeyFromFile(string? file, string? kid)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(file) || !File.Exists(file) || string.IsNullOrEmpty(kid))
+ return null;
+
+ Logger.InfoMarkUp(ResString.searchKey);
+ using var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var reader = new StreamReader(stream);
+ var line = "";
+ while (!string.IsNullOrEmpty(line = await reader.ReadLineAsync()))
+ {
+ if (line.Trim().StartsWith(kid))
+ {
+ Logger.InfoMarkUp($"[green]OK[/] [grey]{line.Trim()}[/]");
+ return line.Trim();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorMarkUp(ex.Message);
+ }
+ return null;
+ }
}
}