Skip to content

Commit 77f10b3

Browse files
committed
默认使用ffmpeg进行mp4解密 (#504)
BREAKING CHANGE
1 parent e8e92b6 commit 77f10b3

File tree

11 files changed

+101
-49
lines changed

11 files changed

+101
-49
lines changed

src/N_m3u8DL-RE.Common/Resource/ResString.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public class ResString
7777
public static string cmd_uiLanguage => GetText("cmd_uiLanguage");
7878
public static string cmd_urlProcessorArgs => GetText("cmd_urlProcessorArgs");
7979
public static string cmd_useShakaPackager => GetText("cmd_useShakaPackager");
80+
public static string cmd_useMp4decrypt => GetText("cmd_useMp4decrypt");
8081
public static string cmd_concurrentDownload => GetText("cmd_concurrentDownload");
8182
public static string cmd_useSystemProxy => GetText("cmd_useSystemProxy");
8283
public static string cmd_customProxy => GetText("cmd_customProxy");

src/N_m3u8DL-RE.Common/Resource/StaticText.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,9 @@ internal class StaticText
270270
),
271271
["cmd_keys"] = new TextContainer
272272
(
273-
zhCN: "设置解密密钥, 程序调用mp4decrpyt/shaka-packager进行解密. 格式:\r\n--key KID1:KEY1 --key KID2:KEY2\r\n对于KEY相同的情况可以直接输入 --key KEY",
274-
zhTW: "設置解密密鑰, 程序調用mp4decrpyt/shaka-packager進行解密. 格式:\r\n--key KID1:KEY1 --key KID2:KEY2\r\n對於KEY相同的情況可以直接輸入 --key KEY",
275-
enUS: "Set decryption key(s) to mp4decrypt/shaka-packager. format:\r\n--key KID1:KEY1 --key KID2:KEY2\r\nor use --key KEY if all tracks share the same key."
273+
zhCN: "设置解密密钥, 程序调用mp4decrpyt/shaka-packager/ffmpeg进行解密. 格式:\r\n--key KID1:KEY1 --key KID2:KEY2\r\n对于KEY相同的情况可以直接输入 --key KEY",
274+
zhTW: "設置解密密鑰, 程序調用mp4decrpyt/shaka-packager/ffmpeg進行解密. 格式:\r\n--key KID1:KEY1 --key KID2:KEY2\r\n對於KEY相同的情況可以直接輸入 --key KEY",
275+
enUS: "Set decryption key(s) to mp4decrypt/shaka-packager/ffmpeg. format:\r\n--key KID1:KEY1 --key KID2:KEY2\r\nor use --key KEY if all tracks share the same key."
276276
),
277277
["cmd_keyText"] = new TextContainer
278278
(
@@ -468,9 +468,15 @@ internal class StaticText
468468
),
469469
["cmd_useShakaPackager"] = new TextContainer
470470
(
471-
zhCN: "解密时使用shaka-packager替代mp4decrypt",
472-
zhTW: "解密時使用shaka-packager替代mp4decrypt",
473-
enUS: "Use shaka-packager instead of mp4decrypt to decrypt"
471+
zhCN: "解密时使用shaka-packager替代ffmpeg",
472+
zhTW: "解密時使用shaka-packager替代ffmpeg",
473+
enUS: "Use shaka-packager instead of ffmpeg to decrypt"
474+
),
475+
["cmd_useMp4decrypt"] = new TextContainer
476+
(
477+
zhCN: "解密时使用mp4decrypt替代ffmpeg",
478+
zhTW: "解密時使用mp4decrypt替代ffmpeg",
479+
enUS: "Use mp4decrypt instead of ffmpeg to decrypt"
474480
),
475481
["cmd_concurrentDownload"] = new TextContainer
476482
(
@@ -744,9 +750,9 @@ internal class StaticText
744750
),
745751
["realTimeDecMessage"] = new TextContainer
746752
(
747-
zhCN: "启用实时解密时,建议用shaka-packager而非mp4decrypt",
748-
zhTW: "啟用即時解密時,建議用shaka-packager而非mp4decrypt",
749-
enUS: "When enabling real-time decryption, it is recommended to use shaka-packager instead of mp4decrypt"
753+
zhCN: "启用实时解密时,建议用shaka-packager而非mp4decrypt/ffmpeg",
754+
zhTW: "啟用即時解密時,建議用shaka-packager而非mp4decrypt/ffmpeg",
755+
enUS: "When enabling real-time decryption, it is recommended to use shaka-packager instead of mp4decrypt/ffmpeg"
750756
),
751757
["liveLimitReached"] = new TextContainer
752758
(

src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ internal partial class CommandInvoker
5454
private static readonly Option<bool> AppendUrlParams = new(["--append-url-params"], description: ResString.cmd_appendUrlParams, getDefaultValue: () => false);
5555
private static readonly Option<bool> MP4RealTimeDecryption = new (["--mp4-real-time-decryption"], description: ResString.cmd_MP4RealTimeDecryption, getDefaultValue: () => false);
5656
private static readonly Option<bool> UseShakaPackager = new (["--use-shaka-packager"], description: ResString.cmd_useShakaPackager, getDefaultValue: () => false);
57+
private static readonly Option<bool> UseMp4Decrypt = new (["--use-mp4decrypt"], description: ResString.cmd_useMp4decrypt, getDefaultValue: () => false);
5758
private static readonly Option<bool> ForceAnsiConsole = new(["--force-ansi-console"], description: ResString.cmd_forceAnsiConsole);
5859
private static readonly Option<bool> NoAnsiColor = new(["--no-ansi-color"], description: ResString.cmd_noAnsiColor);
5960
private static readonly Option<string?> DecryptionBinaryPath = new(["--decryption-binary-path"], description: ResString.cmd_decryptionBinaryPath) { ArgumentHelpName = "PATH" };
@@ -523,6 +524,7 @@ protected override MyOption GetBoundValue(BindingContext bindingContext)
523524
UrlProcessorArgs = bindingContext.ParseResult.GetValueForOption(UrlProcessorArgs),
524525
MP4RealTimeDecryption = bindingContext.ParseResult.GetValueForOption(MP4RealTimeDecryption),
525526
UseShakaPackager = bindingContext.ParseResult.GetValueForOption(UseShakaPackager),
527+
UseMp4Decrypt = bindingContext.ParseResult.GetValueForOption(UseMp4Decrypt),
526528
DecryptionBinaryPath = bindingContext.ParseResult.GetValueForOption(DecryptionBinaryPath),
527529
FFmpegBinaryPath = bindingContext.ParseResult.GetValueForOption(FFmpegBinaryPath),
528530
KeyTextFile = bindingContext.ParseResult.GetValueForOption(KeyTextFile),
@@ -615,7 +617,7 @@ public static async Task<int> InvokeArgs(string[] args, Func<MyOption, Task> act
615617
Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, HttpRequestTimeout, ForceAnsiConsole, NoAnsiColor,AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
616618
BinaryMerge, UseFFmpegConcatDemuxer, DelAfterDone, NoDateInfo, NoLog, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
617619
FFmpegBinaryPath,
618-
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
620+
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, UseMp4Decrypt, MP4RealTimeDecryption,
619621
MaxSpeed,
620622
MuxAfterDone,
621623
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, CustomRange, TaskStartAt,

src/N_m3u8DL-RE/CommandLine/MyOption.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ internal class MyOption
141141
/// </summary>
142142
public bool UseShakaPackager { get; set; }
143143
/// <summary>
144+
/// See: <see cref="CommandInvoker.UseMp4Decrypt"/>.
145+
/// </summary>
146+
public bool UseMp4Decrypt { get; set; }
147+
/// <summary>
144148
/// See: <see cref="CommandInvoker.MuxAfterDone"/>.
145149
/// </summary>
146150
public bool MuxAfterDone { get; set; }
@@ -266,4 +270,13 @@ internal class MyOption
266270
/// See: <see cref="CommandInvoker.LiveFixVttByAudio"/>.
267271
/// </summary>
268272
public bool LiveFixVttByAudio { get; set; }
273+
274+
public DecryptEngine GetDecryptEngine()
275+
{
276+
if (UseShakaPackager)
277+
return DecryptEngine.SHAKA_PACKAGE;
278+
if (UseMp4Decrypt)
279+
return DecryptEngine.MP4DECRYPT;
280+
return DecryptEngine.FFMPEG;
281+
}
269282
}

src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Spectre.Console;
1414
using System.Collections.Concurrent;
1515
using System.Text;
16+
using N_m3u8DL_RE.Enum;
1617

1718
namespace N_m3u8DL_RE.DownloadManager;
1819

@@ -39,9 +40,9 @@ private async Task SearchKeyAsync(string? currentKID)
3940
if (_key != null)
4041
{
4142
if (DownloaderConfig.MyOptions.Keys == null)
42-
DownloaderConfig.MyOptions.Keys = new string[] { _key };
43+
DownloaderConfig.MyOptions.Keys = [_key];
4344
else
44-
DownloaderConfig.MyOptions.Keys = DownloaderConfig.MyOptions.Keys.Concat(new string[] { _key }).ToArray();
45+
DownloaderConfig.MyOptions.Keys = [..DownloaderConfig.MyOptions.Keys, _key];
4546
}
4647
}
4748

@@ -109,8 +110,8 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
109110
var saveName = DownloaderConfig.MyOptions.SaveName != null ? $"{DownloaderConfig.MyOptions.SaveName}.{streamSpec.Language}".TrimEnd('.') : dirName;
110111
var headers = DownloaderConfig.Headers;
111112

112-
// mp4decrypt
113-
var mp4decrypt = DownloaderConfig.MyOptions.DecryptionBinaryPath!;
113+
var decryptionBinaryPath = DownloaderConfig.MyOptions.DecryptionBinaryPath!;
114+
var decryptEngine = DownloaderConfig.MyOptions.GetDecryptEngine();
114115
var mp4InitFile = "";
115116
var currentKID = "";
116117
var readInfo = false; // 是否读取过
@@ -171,7 +172,7 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
171172
currentKID = mp4Info.KID;
172173
// try shaka packager, which can handle WebM
173174
if (string.IsNullOrEmpty(currentKID) && DownloaderConfig.MyOptions.UseShakaPackager) {
174-
currentKID = MP4DecryptUtil.ReadInitShaka(result.ActualFilePath, mp4decrypt);
175+
currentKID = MP4DecryptUtil.ReadInitShaka(result.ActualFilePath, decryptionBinaryPath);
175176
}
176177
// 从文件读取KEY
177178
await SearchKeyAsync(currentKID);
@@ -180,7 +181,7 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
180181
{
181182
var enc = result.ActualFilePath;
182183
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
183-
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, isMultiDRM: mp4Info.isMultiDRM);
184+
var dResult = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, isMultiDRM: mp4Info.isMultiDRM);
184185
if (dResult)
185186
{
186187
FileDic[streamSpec.Playlist.MediaInit]!.ActualFilePath = dec;
@@ -229,7 +230,7 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
229230
// 需要重新解密init
230231
var enc = FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath;
231232
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
232-
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID);
233+
var dResult = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID);
233234
if (dResult)
234235
{
235236
FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath = dec;
@@ -243,7 +244,7 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
243244
}
244245
// try shaka packager, which can handle WebM
245246
if (string.IsNullOrEmpty(currentKID) && DownloaderConfig.MyOptions.UseShakaPackager) {
246-
currentKID = MP4DecryptUtil.ReadInitShaka(result.ActualFilePath, mp4decrypt);
247+
currentKID = MP4DecryptUtil.ReadInitShaka(result.ActualFilePath, decryptionBinaryPath);
247248
}
248249
// 从文件读取KEY
249250
await SearchKeyAsync(currentKID);
@@ -253,7 +254,7 @@ private async Task<bool> DownloadStreamAsync(StreamSpec streamSpec, ProgressTask
253254
var enc = result.ActualFilePath;
254255
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
255256
mp4Info = MP4DecryptUtil.GetMP4Info(enc);
256-
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, mp4InitFile, isMultiDRM: mp4Info.isMultiDRM);
257+
var dResult = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, mp4InitFile, isMultiDRM: mp4Info.isMultiDRM);
257258
if (dResult)
258259
{
259260
File.Delete(enc);
@@ -291,7 +292,7 @@ await Parallel.ForEachAsync(segments, options, async (seg, _) =>
291292
var enc = result.ActualFilePath;
292293
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
293294
mp4Info = MP4DecryptUtil.GetMP4Info(enc);
294-
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, mp4InitFile, isMultiDRM: mp4Info.isMultiDRM);
295+
var dResult = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, mp4InitFile, isMultiDRM: mp4Info.isMultiDRM);
295296
if (dResult)
296297
{
297298
File.Delete(enc);
@@ -322,8 +323,8 @@ await Parallel.ForEachAsync(segments, options, async (seg, _) =>
322323
if (!string.IsNullOrEmpty(currentKID) && DownloaderConfig.MyOptions.MP4RealTimeDecryption && DownloaderConfig.MyOptions.Keys != null && DownloaderConfig.MyOptions.Keys.Length > 0 && mp4InitFile != "")
323324
{
324325
File.Delete(mp4InitFile);
325-
// shaka实时解密不需要init文件用于合并
326-
if (DownloaderConfig.MyOptions.UseShakaPackager)
326+
// shaka/ffmpeg实时解密不需要init文件用于合并
327+
if (decryptEngine != DecryptEngine.MP4DECRYPT)
327328
{
328329
FileDic!.Remove(streamSpec.Playlist!.MediaInit, out _);
329330
}
@@ -590,7 +591,7 @@ await Parallel.ForEachAsync(segments, options, async (seg, _) =>
590591
currentKID = MP4DecryptUtil.GetMP4Info(output).KID;
591592
// try shaka packager, which can handle WebM
592593
if (string.IsNullOrEmpty(currentKID) && DownloaderConfig.MyOptions.UseShakaPackager) {
593-
currentKID = MP4DecryptUtil.ReadInitShaka(output, mp4decrypt);
594+
currentKID = MP4DecryptUtil.ReadInitShaka(output, decryptionBinaryPath);
594595
}
595596
// 从文件读取KEY
596597
await SearchKeyAsync(currentKID);
@@ -602,8 +603,8 @@ await Parallel.ForEachAsync(segments, options, async (seg, _) =>
602603
var enc = output;
603604
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
604605
mp4Info = MP4DecryptUtil.GetMP4Info(enc);
605-
Logger.InfoMarkUp($"[grey]Decrypting...[/]");
606-
var result = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, isMultiDRM: mp4Info.isMultiDRM);
606+
Logger.InfoMarkUp($"[grey]Decrypting using {decryptEngine}...[/]");
607+
var result = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID, isMultiDRM: mp4Info.isMultiDRM);
607608
if (result)
608609
{
609610
File.Delete(enc);
@@ -653,8 +654,7 @@ public async Task<bool> StartDownloadAsync()
653654
}
654655
progress.Columns(progressColumns);
655656

656-
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !DownloaderConfig.MyOptions.UseShakaPackager
657-
&& DownloaderConfig.MyOptions.Keys != null && DownloaderConfig.MyOptions.Keys.Length > 0)
657+
if (DownloaderConfig.MyOptions is { MP4RealTimeDecryption: true, UseShakaPackager: false, Keys.Length: > 0 })
658658
Logger.WarnMarkUp($"[darkorange3_1]{ResString.realTimeDecMessage}[/]");
659659

660660
await progress.StartAsync(async ctx =>

0 commit comments

Comments
 (0)