增加`--key-text-file`
This commit is contained in:
parent
0ec23ba3ea
commit
658efdfb00
|
@ -188,6 +188,15 @@ namespace N_m3u8DL_RE.Common.Resource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Set the kid-key file, the program will search the KEY with KID from the file.(Very large file are not recommended) 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string cmd_keyText {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("cmd_keyText", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Failed to get KEY, ignore. 的本地化字符串。
|
/// 查找类似 Failed to get KEY, ignore. 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -494,6 +503,15 @@ namespace N_m3u8DL_RE.Common.Resource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Trying to search for KEY from text file... 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string searchKey {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("searchKey", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Segment count check not pass, total: {}, downloaded: {}. 的本地化字符串。
|
/// 查找类似 Segment count check not pass, total: {}, downloaded: {}. 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -258,4 +258,10 @@
|
||||||
<data name="ffmpegMerge" xml:space="preserve">
|
<data name="ffmpegMerge" xml:space="preserve">
|
||||||
<value>ffmpeg merging...</value>
|
<value>ffmpeg merging...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="cmd_keyText" xml:space="preserve">
|
||||||
|
<value>Set the kid-key file, the program will search the KEY with KID from the file.(Very large file are not recommended)</value>
|
||||||
|
</data>
|
||||||
|
<data name="searchKey" xml:space="preserve">
|
||||||
|
<value>Trying to search for KEY from text file...</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -278,4 +278,10 @@
|
||||||
<data name="ffmpegMerge" xml:space="preserve">
|
<data name="ffmpegMerge" xml:space="preserve">
|
||||||
<value>调用ffmpeg合并中...</value>
|
<value>调用ffmpeg合并中...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="cmd_keyText" xml:space="preserve">
|
||||||
|
<value>设置密钥文件,程序将从文件中按KID搜寻KEY以解密.(不建议使用特大文件)</value>
|
||||||
|
</data>
|
||||||
|
<data name="searchKey" xml:space="preserve">
|
||||||
|
<value>正在尝试从文本文件搜索KEY...</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -255,4 +255,10 @@
|
||||||
<data name="ffmpegMerge" xml:space="preserve">
|
<data name="ffmpegMerge" xml:space="preserve">
|
||||||
<value>調用ffmpeg合併中...</value>
|
<value>調用ffmpeg合併中...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="cmd_keyText" xml:space="preserve">
|
||||||
|
<value>設置密鑰文件,程序將從文件中按KID搜尋KEY以解密.(不建議使用特大文件)</value>
|
||||||
|
</data>
|
||||||
|
<data name="searchKey" xml:space="preserve">
|
||||||
|
<value>正在嘗試從文本文件搜尋KEY...</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -18,6 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
private readonly static Option<string?> UILanguage = new(new string[] { "--ui-language" }, description: ResString.cmd_uiLanguage);
|
private readonly static Option<string?> UILanguage = new(new string[] { "--ui-language" }, description: ResString.cmd_uiLanguage);
|
||||||
private readonly static Option<string?> UrlProcessorArgs = new(new string[] { "--urlprocessor-args" }, description: ResString.cmd_urlProcessorArgs);
|
private readonly static Option<string?> UrlProcessorArgs = new(new string[] { "--urlprocessor-args" }, description: ResString.cmd_urlProcessorArgs);
|
||||||
private readonly static Option<string[]?> Keys = new(new string[] { "--key" }, description: ResString.cmd_keys) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
|
private readonly static Option<string[]?> Keys = new(new string[] { "--key" }, description: ResString.cmd_keys) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
|
||||||
|
private readonly static Option<string> KeyTextFile = new(new string[] { "--key-text-file" }, description: ResString.cmd_keyText);
|
||||||
private readonly static Option<string[]?> Headers = new(new string[] { "-H", "--header" }, description: ResString.cmd_header) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
|
private readonly static Option<string[]?> Headers = new(new string[] { "-H", "--header" }, description: ResString.cmd_header) { Arity = ArgumentArity.ZeroOrMore, AllowMultipleArgumentsPerToken = false };
|
||||||
private readonly static Option<LogLevel> LogLevel = new(name: "--log-level", description: ResString.cmd_logLevel, getDefaultValue: () => Common.Log.LogLevel.INFO);
|
private readonly static Option<LogLevel> LogLevel = new(name: "--log-level", description: ResString.cmd_logLevel, getDefaultValue: () => Common.Log.LogLevel.INFO);
|
||||||
private readonly static Option<SubtitleFormat> SubtitleFormat = new(name: "--sub-format", description: ResString.cmd_subFormat, getDefaultValue: () => Enum.SubtitleFormat.VTT);
|
private readonly static Option<SubtitleFormat> 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),
|
UseShakaPackager = bindingContext.ParseResult.GetValueForOption(UseShakaPackager),
|
||||||
DecryptionBinaryPath = bindingContext.ParseResult.GetValueForOption(DecryptionBinaryPath),
|
DecryptionBinaryPath = bindingContext.ParseResult.GetValueForOption(DecryptionBinaryPath),
|
||||||
FFmpegBinaryPath = bindingContext.ParseResult.GetValueForOption(FFmpegBinaryPath),
|
FFmpegBinaryPath = bindingContext.ParseResult.GetValueForOption(FFmpegBinaryPath),
|
||||||
|
KeyTextFile = bindingContext.ParseResult.GetValueForOption(KeyTextFile),
|
||||||
};
|
};
|
||||||
|
|
||||||
//在这里设置语言
|
//在这里设置语言
|
||||||
|
@ -93,12 +95,12 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
|
|
||||||
public static async Task<int> InvokeArgs(string[] args, Func<MyOption, Task> action)
|
public static async Task<int> InvokeArgs(string[] args, Func<MyOption, Task> 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,
|
Input, TmpDir, SaveDir, SaveName, ThreadCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
|
||||||
BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
||||||
FFmpegBinaryPath,
|
FFmpegBinaryPath,
|
||||||
LogLevel, UILanguage, UrlProcessorArgs, Keys, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption
|
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption
|
||||||
};
|
};
|
||||||
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
||||||
rootCommand.SetHandler(async (myOption) => await action(myOption), new MyOptionBinder());
|
rootCommand.SetHandler(async (myOption) => await action(myOption), new MyOptionBinder());
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[]? Keys { get; set; }
|
public string[]? Keys { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.KeyTextFile"/>.
|
||||||
|
/// </summary>
|
||||||
|
public string? KeyTextFile { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// See: <see cref="CommandInvoker.UrlProcessorArgs"/>.
|
/// See: <see cref="CommandInvoker.UrlProcessorArgs"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? UrlProcessorArgs { get; set; }
|
public string? UrlProcessorArgs { get; set; }
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace N_m3u8DL_RE.Config
|
||||||
UseShakaPackager = option.UseShakaPackager;
|
UseShakaPackager = option.UseShakaPackager;
|
||||||
DecryptionBinaryPath = option.DecryptionBinaryPath;
|
DecryptionBinaryPath = option.DecryptionBinaryPath;
|
||||||
FFmpegBinaryPath = option.FFmpegBinaryPath;
|
FFmpegBinaryPath = option.FFmpegBinaryPath;
|
||||||
|
KeyTextFile = option.KeyTextFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -105,6 +106,10 @@ namespace N_m3u8DL_RE.Config
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[]? Keys { get; set; }
|
public string[]? Keys { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// KID-KEY文件
|
||||||
|
/// </summary>
|
||||||
|
public string? KeyTextFile { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// ffmpeg路径
|
/// ffmpeg路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FFmpegBinaryPath { get; set; }
|
public string? FFmpegBinaryPath { get; set; }
|
||||||
|
|
|
@ -105,6 +105,15 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
{
|
{
|
||||||
var data = File.ReadAllBytes(result.ActualFilePath);
|
var data = File.ReadAllBytes(result.ActualFilePath);
|
||||||
currentKID = ReadInit(data);
|
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)
|
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
|
var header = new byte[4096]; //4KB
|
||||||
fs.Read(header);
|
fs.Read(header);
|
||||||
currentKID = ReadInit(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;
|
var enc = output;
|
||||||
|
|
|
@ -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))
|
if (string.IsNullOrEmpty(option.DecryptionBinaryPath))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
namespace N_m3u8DL_RE.Util
|
||||||
{
|
{
|
||||||
|
@ -60,6 +63,8 @@ namespace N_m3u8DL_RE.Util
|
||||||
|
|
||||||
private static async Task RunCommandAsync(string name, string arg)
|
private static async Task RunCommandAsync(string name, string arg)
|
||||||
{
|
{
|
||||||
|
Logger.DebugMarkUp($"FileName: {name}");
|
||||||
|
Logger.DebugMarkUp($"Arguments: {arg}");
|
||||||
await Process.Start(new ProcessStartInfo()
|
await Process.Start(new ProcessStartInfo()
|
||||||
{
|
{
|
||||||
FileName = name,
|
FileName = name,
|
||||||
|
@ -69,5 +74,32 @@ namespace N_m3u8DL_RE.Util
|
||||||
UseShellExecute = false
|
UseShellExecute = false
|
||||||
})!.WaitForExitAsync();
|
})!.WaitForExitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<string?> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue