优化语言代码识别转换; 支持自动混流为mp4
This commit is contained in:
parent
4859c288ed
commit
ba9fd870e2
|
@ -48,6 +48,7 @@ namespace N_m3u8DL_RE.Common.Resource
|
|||
public static string cmd_useShakaPackager { get => GetText("cmd_useShakaPackager"); }
|
||||
public static string cmd_useMkvmerge { get => GetText("cmd_useMkvmerge"); }
|
||||
public static string cmd_muxAfterDone { get => GetText("cmd_muxAfterDone"); }
|
||||
public static string cmd_muxToMp4 { get => GetText("cmd_muxToMp4"); }
|
||||
public static string cmd_writeMetaJson { get => GetText("cmd_writeMetaJson"); }
|
||||
public static string fetch { get => GetText("fetch"); }
|
||||
public static string ffmpegMerge { get => GetText("ffmpegMerge"); }
|
||||
|
|
|
@ -240,9 +240,15 @@ namespace N_m3u8DL_RE.Common.Resource
|
|||
),
|
||||
["cmd_muxAfterDone"] = new TextContainer
|
||||
(
|
||||
zhCN: "所有工作完成时尝试使用ffmpeg混流分离的音视频(mkv)",
|
||||
zhTW: "所有工作完成時嘗試使用ffmpeg混流分離的影音(mkv)",
|
||||
enUS: "When all works is done, try to use ffmpeg to mux the separated audio(s) and video.(mkv)"
|
||||
zhCN: "所有工作完成时尝试使用ffmpeg混流分离的音视频(默认容器: mkv)",
|
||||
zhTW: "所有工作完成時嘗試使用ffmpeg混流分離的影音(默認容器: mkv)",
|
||||
enUS: "When all works is done, try to use ffmpeg to mux the separated streams.(Default: mkv)"
|
||||
),
|
||||
["cmd_muxToMp4"] = new TextContainer
|
||||
(
|
||||
zhCN: "混流时使用mp4容器而非mkv",
|
||||
zhTW: "混流時使用mp4容器而非mkv",
|
||||
enUS: "Use mp4 container instead of mkv when muxing"
|
||||
),
|
||||
["cmd_writeMetaJson"] = new TextContainer
|
||||
(
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace N_m3u8DL_RE.CommandLine
|
|||
private readonly static Option<bool> MP4RealTimeDecryption = new (new string[] { "--mp4-real-time-decryption" }, description: ResString.cmd_MP4RealTimeDecryption, getDefaultValue: () => false);
|
||||
private readonly static Option<bool> UseShakaPackager = new (new string[] { "--use-shaka-packager" }, description: ResString.cmd_useShakaPackager, getDefaultValue: () => false);
|
||||
private readonly static Option<bool> MuxAfterDone = new (new string[] { "--mux-after-done" }, description: ResString.cmd_muxAfterDone, getDefaultValue: () => false);
|
||||
private readonly static Option<bool> MuxToMp4 = new (new string[] { "--mux-to-mp4" }, description: ResString.cmd_muxToMp4, getDefaultValue: () => false);
|
||||
private readonly static Option<bool> UseMkvmerge = new(new string[] { "--use-mkvmerge" }, description: ResString.cmd_useMkvmerge, getDefaultValue: () => false);
|
||||
private readonly static Option<string?> DecryptionBinaryPath = new(new string[] { "--decryption-binary-path" }, description: ResString.cmd_decryptionBinaryPath);
|
||||
private readonly static Option<string?> FFmpegBinaryPath = new(new string[] { "--ffmpeg-binary-path" }, description: ResString.cmd_ffmpegBinaryPath);
|
||||
|
@ -80,6 +81,7 @@ namespace N_m3u8DL_RE.CommandLine
|
|||
MuxAfterDone = bindingContext.ParseResult.GetValueForOption(MuxAfterDone),
|
||||
UseMkvmerge = bindingContext.ParseResult.GetValueForOption(UseMkvmerge),
|
||||
BaseUrl = bindingContext.ParseResult.GetValueForOption(BaseUrl),
|
||||
MuxToMp4 = bindingContext.ParseResult.GetValueForOption(MuxToMp4),
|
||||
};
|
||||
|
||||
|
||||
|
@ -101,9 +103,9 @@ namespace N_m3u8DL_RE.CommandLine
|
|||
var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220822")
|
||||
{
|
||||
Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
|
||||
BinaryMerge, DelAfterDone, WriteMetaJson, MuxAfterDone, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
||||
BinaryMerge, DelAfterDone, WriteMetaJson, MuxAfterDone, MuxToMp4, UseMkvmerge, AppendUrlParams, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
||||
FFmpegBinaryPath, MkvmergeBinaryPath,
|
||||
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, UseMkvmerge, MP4RealTimeDecryption
|
||||
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption
|
||||
};
|
||||
rootCommand.TreatUnmatchedTokensAsErrors = true;
|
||||
rootCommand.SetHandler(async (myOption) => await action(myOption), new MyOptionBinder());
|
||||
|
|
|
@ -94,6 +94,10 @@ namespace N_m3u8DL_RE.CommandLine
|
|||
/// </summary>
|
||||
public bool MuxAfterDone { get; set; }
|
||||
/// <summary>
|
||||
/// See: <see cref="CommandInvoker.MuxToMp4"/>.
|
||||
/// </summary>
|
||||
public bool MuxToMp4 { get; set; }
|
||||
/// <summary>
|
||||
/// See: <see cref="CommandInvoker.UseMkvmerge"/>.
|
||||
/// </summary>
|
||||
public bool UseMkvmerge { get; set; }
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace N_m3u8DL_RE.Config
|
|||
MuxAfterDone = option.MuxAfterDone;
|
||||
UseMkvmerge = option.UseMkvmerge;
|
||||
MkvmergeBinaryPath = option.MkvmergeBinaryPath;
|
||||
MuxToMp4 = option.MuxToMp4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -99,6 +100,10 @@ namespace N_m3u8DL_RE.Config
|
|||
/// </summary>
|
||||
public bool MuxAfterDone { get; set; }
|
||||
/// <summary>
|
||||
/// 自动混流音视频容器使用mp4
|
||||
/// </summary>
|
||||
public bool MuxToMp4 { get; set; }
|
||||
/// <summary>
|
||||
/// 使用mkvmerge混流
|
||||
/// </summary>
|
||||
public bool UseMkvmerge { get; set; }
|
||||
|
|
|
@ -280,7 +280,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
|||
//检测目标文件是否存在
|
||||
while (File.Exists(output))
|
||||
{
|
||||
Logger.WarnMarkUp($"{output} => {output = Path.ChangeExtension(output, $"copy" + Path.GetExtension(output))}");
|
||||
Logger.WarnMarkUp($"{Path.GetFileName(output)} => {Path.GetFileName(output = Path.ChangeExtension(output, $"copy" + Path.GetExtension(output)))}");
|
||||
}
|
||||
|
||||
if (DownloaderConfig.MP4RealTimeDecryption && mp4InitFile != "")
|
||||
|
@ -492,7 +492,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
|||
//检测目标文件是否存在
|
||||
while (File.Exists(ffOut))
|
||||
{
|
||||
Logger.WarnMarkUp($"{ffOut} => {ffOut = Path.ChangeExtension(ffOut, $"copy" + Path.GetExtension(ffOut))}");
|
||||
Logger.WarnMarkUp($"{Path.GetFileName(ffOut)} => {Path.GetFileName(ffOut = Path.ChangeExtension(ffOut, $"copy" + Path.GetExtension(ffOut)))}");
|
||||
}
|
||||
mergeSuccess = MergeUtil.MergeByFFmpeg(DownloaderConfig.FFmpegBinaryPath!, files, Path.ChangeExtension(ffOut, null), ext, useAACFilter);
|
||||
if (mergeSuccess) output = ffOut;
|
||||
|
@ -582,10 +582,10 @@ namespace N_m3u8DL_RE.DownloadManager
|
|||
var saveDir = DownloaderConfig.SaveDir ?? Environment.CurrentDirectory;
|
||||
var outName = $"{DownloaderConfig.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}";
|
||||
var outPath = Path.Combine(saveDir, outName);
|
||||
Logger.WarnMarkUp($"Muxing to [grey]{outName.EscapeMarkup()}.mkv[/]");
|
||||
Logger.WarnMarkUp($"Muxing to [grey]{outName.EscapeMarkup()}.{(DownloaderConfig.MuxToMp4 ? "mp4" : "mkv")}[/]");
|
||||
var result = false;
|
||||
if (DownloaderConfig.UseMkvmerge) result = MergeUtil.MuxInputsByMkvmerge(DownloaderConfig.MkvmergeBinaryPath!, OutputFiles.ToArray(), outPath);
|
||||
else result = MergeUtil.MuxInputsByFFmpeg(DownloaderConfig.FFmpegBinaryPath!, OutputFiles.ToArray(), outPath);
|
||||
else result = MergeUtil.MuxInputsByFFmpeg(DownloaderConfig.FFmpegBinaryPath!, OutputFiles.ToArray(), outPath, DownloaderConfig.MuxToMp4);
|
||||
//完成后删除各轨道文件
|
||||
if (result)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ using N_m3u8DL_RE.Config;
|
|||
using N_m3u8DL_RE.Util;
|
||||
using N_m3u8DL_RE.DownloadManager;
|
||||
using N_m3u8DL_RE.CommandLine;
|
||||
using N_m3u8DL_RE.Entity;
|
||||
|
||||
namespace N_m3u8DL_RE
|
||||
{
|
||||
|
@ -20,6 +21,7 @@ namespace N_m3u8DL_RE
|
|||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
Console.CursorVisible = true;
|
||||
string loc = "en-US";
|
||||
string currLoc = Thread.CurrentThread.CurrentUICulture.Name;
|
||||
if (currLoc == "zh-CN" || currLoc == "zh-SG") loc = "zh-CN";
|
||||
|
@ -47,6 +49,12 @@ namespace N_m3u8DL_RE
|
|||
|
||||
try
|
||||
{
|
||||
//检查互斥的选项
|
||||
if (option.UseMkvmerge && option.MuxToMp4)
|
||||
{
|
||||
throw new ArgumentException("Can't use mkvmerge to make mp4!");
|
||||
}
|
||||
|
||||
//预先检查ffmpeg
|
||||
if (option.FFmpegBinaryPath == null)
|
||||
option.FFmpegBinaryPath = GlobalUtil.FindExecutable("ffmpeg");
|
||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -142,8 +143,9 @@ namespace N_m3u8DL_RE.Util
|
|||
return false;
|
||||
}
|
||||
|
||||
public static bool MuxInputsByFFmpeg(string binary, OutputFile[] files, string outputPath)
|
||||
public static bool MuxInputsByFFmpeg(string binary, OutputFile[] files, string outputPath, bool mp4)
|
||||
{
|
||||
var ext = mp4 ? "mp4" : "mkv";
|
||||
string dateString = DateTime.Now.ToString("o");
|
||||
StringBuilder command = new StringBuilder("-loglevel warning -y ");
|
||||
|
||||
|
@ -159,22 +161,35 @@ namespace N_m3u8DL_RE.Util
|
|||
command.Append($" -map {i} ");
|
||||
}
|
||||
|
||||
if (mp4)
|
||||
command.Append($" -c:a copy -c:v copy -c:s mov_text "); //mp4不支持vtt/srt字幕,必须转换格式
|
||||
else
|
||||
command.Append($" -c copy ");
|
||||
|
||||
//CLEAN
|
||||
command.Append(" -map_metadata -1 ");
|
||||
|
||||
//LANG and NAME
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
command.Append($" -metadata:s:{i} language={files[i].LangCode ?? "und"} ");
|
||||
//转换语言代码
|
||||
ConvertLangCodeAndDisplayName(files[i]);
|
||||
command.Append($" -metadata:s:{i} language=\"{files[i].LangCode ?? "und"}\" ");
|
||||
if (!string.IsNullOrEmpty(files[i].Description))
|
||||
command.Append($" -metadata:s:{i} title={files[i].Description} ");
|
||||
{
|
||||
if(mp4)
|
||||
command.Append($" -metadata:s:{i} handler_name=\"{files[i].Description}\" -metadata:s:{i} handler=\"{files[i].Description}\" ");
|
||||
else
|
||||
command.Append($" -metadata:s:{i} title=\"{files[i].Description}\" ");
|
||||
}
|
||||
}
|
||||
|
||||
command.Append($" -metadata date=\"{dateString}\" -ignore_unknown -copy_unknown -c copy \"{outputPath}.mkv\"");
|
||||
command.Append($" -metadata date=\"{dateString}\" -ignore_unknown -copy_unknown ");
|
||||
command.Append($" \"{outputPath}.{ext}\"");
|
||||
|
||||
InvokeFFmpeg(binary, command.ToString(), Environment.CurrentDirectory);
|
||||
|
||||
if (File.Exists($"{outputPath}.mkv") && new FileInfo($"{outputPath}.mkv").Length > 1024)
|
||||
if (File.Exists($"{outputPath}.{ext}") && new FileInfo($"{outputPath}.{ext}").Length > 1024)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -189,7 +204,9 @@ namespace N_m3u8DL_RE.Util
|
|||
//LANG and NAME
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
command.Append($" --language 0:{files[i].LangCode ?? "und"} ");
|
||||
//转换语言代码
|
||||
ConvertLangCodeAndDisplayName(files[i]);
|
||||
command.Append($" --language 0:\"{files[i].LangCode ?? "und"}\" ");
|
||||
if (!string.IsNullOrEmpty(files[i].Description))
|
||||
command.Append($" --track-name 0:\"{files[i].Description}\" ");
|
||||
command.Append($" \"{files[i].FilePath}\" ");
|
||||
|
@ -202,5 +219,28 @@ namespace N_m3u8DL_RE.Util
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换 ISO 639-1 => ISO 639-2
|
||||
/// 且当Description为空时将DisplayName写入
|
||||
/// </summary>
|
||||
/// <param name="outputFile"></param>
|
||||
private static void ConvertLangCodeAndDisplayName(OutputFile outputFile)
|
||||
{
|
||||
if (string.IsNullOrEmpty(outputFile.LangCode)) return;
|
||||
CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
foreach (var c in cultures)
|
||||
{
|
||||
if (outputFile.LangCode.Split('-')[0] == c.TwoLetterISOLanguageName)
|
||||
{
|
||||
outputFile.LangCode = c.ThreeLetterISOLanguageName;
|
||||
if (string.IsNullOrEmpty(outputFile.Description))
|
||||
{
|
||||
outputFile.Description = c.DisplayName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue