支持 ffmpeg concat 分离器 #254
This commit is contained in:
parent
10e67aa14b
commit
836a90800b
|
@ -28,6 +28,7 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
public static string cmd_appendUrlParams { get => GetText("cmd_appendUrlParams"); }
|
public static string cmd_appendUrlParams { get => GetText("cmd_appendUrlParams"); }
|
||||||
public static string cmd_autoSelect { get => GetText("cmd_autoSelect"); }
|
public static string cmd_autoSelect { get => GetText("cmd_autoSelect"); }
|
||||||
public static string cmd_binaryMerge { get => GetText("cmd_binaryMerge"); }
|
public static string cmd_binaryMerge { get => GetText("cmd_binaryMerge"); }
|
||||||
|
public static string cmd_useFFmpegConcatDemuxer { get => GetText("cmd_useFFmpegConcatDemuxer"); }
|
||||||
public static string cmd_checkSegmentsCount { get => GetText("cmd_checkSegmentsCount"); }
|
public static string cmd_checkSegmentsCount { get => GetText("cmd_checkSegmentsCount"); }
|
||||||
public static string cmd_decryptionBinaryPath { get => GetText("cmd_decryptionBinaryPath"); }
|
public static string cmd_decryptionBinaryPath { get => GetText("cmd_decryptionBinaryPath"); }
|
||||||
public static string cmd_delAfterDone { get => GetText("cmd_delAfterDone"); }
|
public static string cmd_delAfterDone { get => GetText("cmd_delAfterDone"); }
|
||||||
|
|
|
@ -172,6 +172,12 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
zhTW: "二進位制合併",
|
zhTW: "二進位制合併",
|
||||||
enUS: "Binary merge"
|
enUS: "Binary merge"
|
||||||
),
|
),
|
||||||
|
["cmd_useFFmpegConcatDemuxer"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "使用 ffmpeg 合并时,使用 concat 分离器而非 concat 协议",
|
||||||
|
zhTW: "使用 ffmpeg 合併時,使用 concat 分離器而非 concat 協議",
|
||||||
|
enUS: "When merging with ffmpeg, use the concat demuxer instead of the concat protocol"
|
||||||
|
),
|
||||||
["cmd_checkSegmentsCount"] = new TextContainer
|
["cmd_checkSegmentsCount"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "检测实际下载的分片数量和预期数量是否匹配",
|
zhCN: "检测实际下载的分片数量和预期数量是否匹配",
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
{
|
{
|
||||||
internal partial class CommandInvoker
|
internal partial class CommandInvoker
|
||||||
{
|
{
|
||||||
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230730";
|
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230820";
|
||||||
|
|
||||||
[GeneratedRegex("((best|worst)\\d*|all)")]
|
[GeneratedRegex("((best|worst)\\d*|all)")]
|
||||||
private static partial Regex ForStrRegex();
|
private static partial Regex ForStrRegex();
|
||||||
|
@ -45,6 +45,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
private readonly static Option<bool> SkipDownload = new(new string[] { "--skip-download" }, description: ResString.cmd_skipDownload, getDefaultValue: () => false);
|
private readonly static Option<bool> SkipDownload = new(new string[] { "--skip-download" }, description: ResString.cmd_skipDownload, getDefaultValue: () => false);
|
||||||
private readonly static Option<bool> NoDateInfo = new(new string[] { "--no-date-info" }, description: ResString.cmd_noDateInfo, getDefaultValue: () => false);
|
private readonly static Option<bool> NoDateInfo = new(new string[] { "--no-date-info" }, description: ResString.cmd_noDateInfo, getDefaultValue: () => false);
|
||||||
private readonly static Option<bool> BinaryMerge = new(new string[] { "--binary-merge" }, description: ResString.cmd_binaryMerge, getDefaultValue: () => false);
|
private readonly static Option<bool> BinaryMerge = new(new string[] { "--binary-merge" }, description: ResString.cmd_binaryMerge, getDefaultValue: () => false);
|
||||||
|
private readonly static Option<bool> UseFFmpegConcatDemuxer = new(new string[] { "--use-ffmpeg-concat-demuxer" }, description: ResString.cmd_useFFmpegConcatDemuxer, getDefaultValue: () => false);
|
||||||
private readonly static Option<bool> DelAfterDone = new(new string[] { "--del-after-done" }, description: ResString.cmd_delAfterDone, getDefaultValue: () => true);
|
private readonly static Option<bool> DelAfterDone = new(new string[] { "--del-after-done" }, description: ResString.cmd_delAfterDone, getDefaultValue: () => true);
|
||||||
private readonly static Option<bool> AutoSubtitleFix = new(new string[] { "--auto-subtitle-fix" }, description: ResString.cmd_subtitleFix, getDefaultValue: () => true);
|
private readonly static Option<bool> AutoSubtitleFix = new(new string[] { "--auto-subtitle-fix" }, description: ResString.cmd_subtitleFix, getDefaultValue: () => true);
|
||||||
private readonly static Option<bool> CheckSegmentsCount = new(new string[] { "--check-segments-count" }, description: ResString.cmd_checkSegmentsCount, getDefaultValue: () => true);
|
private readonly static Option<bool> CheckSegmentsCount = new(new string[] { "--check-segments-count" }, description: ResString.cmd_checkSegmentsCount, getDefaultValue: () => true);
|
||||||
|
@ -483,6 +484,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
AutoSelect = bindingContext.ParseResult.GetValueForOption(AutoSelect),
|
AutoSelect = bindingContext.ParseResult.GetValueForOption(AutoSelect),
|
||||||
SkipMerge = bindingContext.ParseResult.GetValueForOption(SkipMerge),
|
SkipMerge = bindingContext.ParseResult.GetValueForOption(SkipMerge),
|
||||||
BinaryMerge = bindingContext.ParseResult.GetValueForOption(BinaryMerge),
|
BinaryMerge = bindingContext.ParseResult.GetValueForOption(BinaryMerge),
|
||||||
|
UseFFmpegConcatDemuxer = bindingContext.ParseResult.GetValueForOption(UseFFmpegConcatDemuxer),
|
||||||
DelAfterDone = bindingContext.ParseResult.GetValueForOption(DelAfterDone),
|
DelAfterDone = bindingContext.ParseResult.GetValueForOption(DelAfterDone),
|
||||||
AutoSubtitleFix = bindingContext.ParseResult.GetValueForOption(AutoSubtitleFix),
|
AutoSubtitleFix = bindingContext.ParseResult.GetValueForOption(AutoSubtitleFix),
|
||||||
CheckSegmentsCount = bindingContext.ParseResult.GetValueForOption(CheckSegmentsCount),
|
CheckSegmentsCount = bindingContext.ParseResult.GetValueForOption(CheckSegmentsCount),
|
||||||
|
@ -589,7 +591,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
var rootCommand = new RootCommand(VERSION_INFO)
|
var rootCommand = new RootCommand(VERSION_INFO)
|
||||||
{
|
{
|
||||||
Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
|
Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
|
||||||
BinaryMerge, DelAfterDone, NoDateInfo, NoLog, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
BinaryMerge, UseFFmpegConcatDemuxer, DelAfterDone, NoDateInfo, NoLog, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,
|
||||||
FFmpegBinaryPath,
|
FFmpegBinaryPath,
|
||||||
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
|
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
|
||||||
MaxSpeed,
|
MaxSpeed,
|
||||||
|
|
|
@ -85,6 +85,10 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool BinaryMerge { get; set; }
|
public bool BinaryMerge { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// See: <see cref="CommandInvoker.UseFFmpegConcatDemuxer"/>.
|
||||||
|
/// </summary>
|
||||||
|
public bool UseFFmpegConcatDemuxer { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// See: <see cref="CommandInvoker.DelAfterDone"/>.
|
/// See: <see cref="CommandInvoker.DelAfterDone"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DelAfterDone { get; set; }
|
public bool DelAfterDone { get; set; }
|
||||||
|
|
|
@ -557,7 +557,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeSuccess = MergeUtil.MergeByFFmpeg(DownloaderConfig.MyOptions.FFmpegBinaryPath!, files, Path.ChangeExtension(ffOut, null), ext, useAACFilter, writeDate: !DownloaderConfig.MyOptions.NoDateInfo);
|
mergeSuccess = MergeUtil.MergeByFFmpeg(DownloaderConfig.MyOptions.FFmpegBinaryPath!, files, Path.ChangeExtension(ffOut, null), ext, useAACFilter, writeDate: !DownloaderConfig.MyOptions.NoDateInfo, useConcatDemuxer: DownloaderConfig.MyOptions.UseFFmpegConcatDemuxer);
|
||||||
if (mergeSuccess) output = ffOut;
|
if (mergeSuccess) output = ffOut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace N_m3u8DL_RE.Util
|
||||||
|
|
||||||
public static bool MergeByFFmpeg(string binary, string[] files, string outputPath, string muxFormat, bool useAACFilter,
|
public static bool MergeByFFmpeg(string binary, string[] files, string outputPath, string muxFormat, bool useAACFilter,
|
||||||
bool fastStart = false,
|
bool fastStart = false,
|
||||||
bool writeDate = true, string poster = "", string audioName = "", string title = "",
|
bool writeDate = true, bool useConcatDemuxer = false, string poster = "", string audioName = "", string title = "",
|
||||||
string copyright = "", string comment = "", string encodingTool = "", string recTime = "")
|
string copyright = "", string comment = "", string encodingTool = "", string recTime = "")
|
||||||
{
|
{
|
||||||
//改为绝对路径
|
//改为绝对路径
|
||||||
|
@ -118,16 +118,29 @@ namespace N_m3u8DL_RE.Util
|
||||||
|
|
||||||
string dateString = string.IsNullOrEmpty(recTime) ? DateTime.Now.ToString("o") : recTime;
|
string dateString = string.IsNullOrEmpty(recTime) ? DateTime.Now.ToString("o") : recTime;
|
||||||
|
|
||||||
StringBuilder command = new StringBuilder("-loglevel warning -nostdin -i concat:\"");
|
StringBuilder command = new StringBuilder("-loglevel warning -nostdin ");
|
||||||
string ddpAudio = string.Empty;
|
string ddpAudio = string.Empty;
|
||||||
string addPoster = "-map 1 -c:v:1 copy -disposition:v:1 attached_pic";
|
string addPoster = "-map 1 -c:v:1 copy -disposition:v:1 attached_pic";
|
||||||
ddpAudio = (File.Exists($"{Path.GetFileNameWithoutExtension(outputPath + ".mp4")}.txt") ? File.ReadAllText($"{Path.GetFileNameWithoutExtension(outputPath + ".mp4")}.txt") : "");
|
ddpAudio = (File.Exists($"{Path.GetFileNameWithoutExtension(outputPath + ".mp4")}.txt") ? File.ReadAllText($"{Path.GetFileNameWithoutExtension(outputPath + ".mp4")}.txt") : "");
|
||||||
if (!string.IsNullOrEmpty(ddpAudio)) useAACFilter = false;
|
if (!string.IsNullOrEmpty(ddpAudio)) useAACFilter = false;
|
||||||
|
|
||||||
|
if (useConcatDemuxer)
|
||||||
|
{
|
||||||
|
// 使用 concat demuxer合并
|
||||||
|
var text = string.Join(Environment.NewLine, files.Select(f => $"file '{f}'"));
|
||||||
|
var tempFile = Path.GetTempFileName();
|
||||||
|
File.WriteAllText(tempFile, text);
|
||||||
|
command.Append($" -f concat -safe 0 -i \"{tempFile}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command.Append(" -i concat:\"");
|
||||||
foreach (string t in files)
|
foreach (string t in files)
|
||||||
{
|
{
|
||||||
command.Append(Path.GetFileName(t) + "|");
|
command.Append(Path.GetFileName(t) + "|");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (muxFormat.ToUpper())
|
switch (muxFormat.ToUpper())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue