VideoNodes: changed VideoEncode to take in List<string> instead of string. Updated Audio Normalize to use VideoEncode for 2 pass 1st pass

This commit is contained in:
reven
2022-01-30 17:16:07 +13:00
parent 51000b249d
commit 53aa11a238
16 changed files with 278 additions and 200 deletions

View File

@@ -1,5 +1,6 @@
namespace FileFlows.VideoNodes
{
using System.Linq;
internal static class ExtensionMethods
{
public static void AddOrUpdate(this Dictionary<string, object> dict, string key, object value) {
@@ -12,5 +13,44 @@
{
return str == string.Empty ? null : str;
}
public static IEnumerable<string> SplitCommandLine(this string commandLine)
{
bool inQuotes = false;
return commandLine.Split(c =>
{
if (c == '\"')
inQuotes = !inQuotes;
return !inQuotes && c == ' ';
})
.Select(arg => arg.Trim().TrimMatchingQuotes('\"'))
.Where(arg => !string.IsNullOrEmpty(arg));
}
public static IEnumerable<string> Split(this string str,
Func<char, bool> controller)
{
int nextPiece = 0;
for (int c = 0; c < str.Length; c++)
{
if (controller(str[c]))
{
yield return str.Substring(nextPiece, c - nextPiece);
nextPiece = c + 1;
}
}
yield return str.Substring(nextPiece);
}
public static string TrimMatchingQuotes(this string input, char quote)
{
if ((input.Length >= 2) &&
(input[0] == quote) && (input[input.Length - 1] == quote))
return input.Substring(1, input.Length - 2);
return input;
}
}
}

View File

@@ -26,22 +26,31 @@ namespace FileFlows.VideoNodes
this.Logger = logger;
}
public bool Encode(string input, string output, string arguments, bool dontAddInputFile = false)
public (bool successs, string output) Encode(string input, string output, List<string> arguments, bool dontAddInputFile = false)
{
// -y means it will overwrite a file if output already exists
if(dontAddInputFile == false)
arguments = $"-i \"{input}\" -y {arguments} \"{output}\"";
else
arguments = $"{arguments} \"{output}\"";
arguments ??= new List<string> ();
Logger.ILog(new string('=', ("FFMpeg.Arguments: " + arguments).Length));
Logger.ILog("FFMpeg.Arguments: " + arguments);
Logger.ILog(new string('=', ("FFMpeg.Arguments: " + arguments).Length));
// -y means it will overwrite a file if output already exists
if (dontAddInputFile == false) {
arguments.Insert(0, "-i");
arguments.Insert(1, input);
arguments.Insert(2, "-y");
}
if (arguments.Last() != "-")
arguments.Add(output);
else
Logger.ILog("Last argument '-' skipping adding output file");
string argsString = String.Join(" ", arguments.Select(x => x.IndexOf(" ") > 0 ? "\"" + x + "\"" : x));
Logger.ILog(new string('=', ("FFMpeg.Arguments: " + argsString).Length));
Logger.ILog("FFMpeg.Arguments: " + argsString);
Logger.ILog(new string('=', ("FFMpeg.Arguments: " + argsString).Length));
var task = ExecuteShellCommand(ffMpegExe, arguments, 0);
task.Wait();
Logger.ILog("Exit Code: " + task.Result.ExitCode);
return task.Result.ExitCode == 0; // exitcode 0 means it was successful
return (task.Result.ExitCode == 0, task.Result.Output); // exitcode 0 means it was successful
}
internal void Cancel()
@@ -58,7 +67,7 @@ namespace FileFlows.VideoNodes
catch (Exception) { }
}
public async Task<ProcessResult> ExecuteShellCommand(string command, string arguments, int timeout = 0)
public async Task<ProcessResult> ExecuteShellCommand(string command, List<string> arguments, int timeout = 0)
{
var result = new ProcessResult();
@@ -69,7 +78,11 @@ namespace FileFlows.VideoNodes
// To fix it you can try to add '#!/bin/bash' header to the script.
process.StartInfo.FileName = command;
process.StartInfo.Arguments = arguments;
if (arguments?.Any() == true)
{
foreach (string arg in arguments)
process.StartInfo.ArgumentList.Add(arg); ;
}
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
@@ -125,12 +138,7 @@ namespace FileFlows.VideoNodes
{
result.Completed = true;
result.ExitCode = process.ExitCode;
// Adds process output if it was completed with error
if (process.ExitCode != 0)
{
result.Output = $"{outputBuilder}{errorBuilder}";
}
result.Output = $"{outputBuilder}{errorBuilder}";
}
else
{

View File

@@ -30,7 +30,7 @@ namespace VideoNodes.Tests
new VideoFile().Execute(args);
string output = AudioNormalization.DoTwoPass(args, ffmpeg, "0:1");
string output = node.DoTwoPass(args, ffmpeg, "0:1");
Assert.IsFalse(string.IsNullOrWhiteSpace(output));
}

View File

@@ -43,25 +43,27 @@
return 2;
}
List<string> ffArgs = new List<string>();
ffArgs.Add($"-map 0:v");
List<string> ffArgs = new List<string>
{
"-c", "copy",
"-map", "0:v",
};
float volume = this.VolumePercent / 100f;
foreach (var audio in videoInfo.AudioStreams)
{
ffArgs.Add($"-map 0:{audio.Index} -filter:a \"volume={volume.ToString(".0######")}\"");
ffArgs.AddRange(new[] { "-map", $"0:{audio.Index}", "-filter:a", $"volume={volume.ToString(".0######")}" });
}
if (videoInfo.SubtitleStreams?.Any() == true)
ffArgs.Add("-map 0:s -c copy");
ffArgs.AddRange(new[] { "-map", "0:s" });
string ffArgsLine = string.Join(" ", ffArgs);
string extension = new FileInfo(args.WorkingFile).Extension;
if(extension.StartsWith("."))
extension = extension.Substring(1);
if (Encode(args, ffmpegExe, ffArgsLine, extension) == false)
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;

View File

@@ -44,10 +44,10 @@
List<string> ffArgs = new List<string>();
ffArgs.Add("-c copy");
ffArgs.AddRange(new[] { "-c", "copy" });
if(videoInfo.VideoStreams?.Any() == true)
ffArgs.Add($"-map 0:v");
if (videoInfo.VideoStreams?.Any() == true)
ffArgs.AddRange(new[] { "-map", "0:v" });
for (int j = 0; j < videoInfo.AudioStreams.Count;j++)
@@ -59,26 +59,24 @@
if (TwoPass)
{
string twoPass = DoTwoPass(args, ffmpegExe, audio.IndexString);
ffArgs.Add($"-map 0:{audio.Index} -c:a {audio.Codec} -ar {sampleRate} {twoPass}");
ffArgs.AddRange(new[] { "-map", $"0:{audio.Index}", "-c:a", audio.Codec, "-ar", sampleRate.ToString(), "-af", twoPass });
}
else
{
ffArgs.Add($"-map 0:{audio.Index} -c:a {audio.Codec} -ar {sampleRate} -af loudnorm={LOUDNORM_TARGET}");
ffArgs.AddRange(new[] { "-map", $"0:{audio.Index}", "-c:a", audio.Codec, "-ar", sampleRate.ToString(), "-af", $"loudnorm={LOUDNORM_TARGET}" });
}
}
else
ffArgs.Add($"-map 0:{audio.Index}");
}
if (videoInfo.SubtitleStreams?.Any() == true)
ffArgs.Add("-map 0:s");
string ffArgsLine = string.Join(" ", ffArgs);
ffArgs.AddRange(new[] { "-map", "0:s" });
string extension = new FileInfo(args.WorkingFile).Extension;
if (extension.StartsWith("."))
extension = extension.Substring(1);
if (Encode(args, ffmpegExe, ffArgsLine, extension) == false)
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;
@@ -91,10 +89,11 @@
}
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<FileFlows.VideoNodes.AudioNormalization.LoudNormStats>(string, System.Text.Json.JsonSerializerOptions?)")]
public static string DoTwoPass(NodeParameters args,string ffmpegExe, string audioIndex)
public string DoTwoPass(NodeParameters args,string ffmpegExe, string audioIndex)
{
//-af loudnorm=I=-24:LRA=7:TP=-2.0"
var result = args.Execute(ffmpegExe, argumentList: new[]
string output;
var result = Encode(args, ffmpegExe, new List<string>
{
"-hide_banner",
"-i", args.WorkingFile,
@@ -102,20 +101,20 @@
"-af", "loudnorm=" + LOUDNORM_TARGET + ":print_format=json",
"-f", "null",
"-"
});
}, out output, updateWorkingFile: false, dontAddInputFile: true);
if (result.ExitCode != 0)
if (result == false)
throw new Exception("Failed to prcoess audio track");
int index = result.Output.LastIndexOf("{");
int index = output.LastIndexOf("{");
if (index == -1)
throw new Exception("Failed to detected json in output");
string json = result.Output.Substring(index);
string json = output.Substring(index);
json = json.Substring(0, json.IndexOf("}") + 1);
if (string.IsNullOrEmpty(json))
throw new Exception("Failed to parse TwoPass json");
LoudNormStats stats = JsonSerializer.Deserialize<LoudNormStats>(json);
string ar = $"-af loudnorm=print_format=summary:linear=true:{LOUDNORM_TARGET}:measured_I={stats.input_i}:measured_LRA={stats.input_lra}:measured_tp={stats.input_tp}:measured_thresh={stats.input_thresh}:offset={stats.target_offset}";
string ar = $"loudnorm=print_format=summary:linear=true:{LOUDNORM_TARGET}:measured_I={stats.input_i}:measured_LRA={stats.input_lra}:measured_tp={stats.input_tp}:measured_thresh={stats.input_thresh}:offset={stats.target_offset}";
return ar;
}

View File

@@ -98,8 +98,12 @@
if (string.IsNullOrEmpty(ffmpegExe))
return -1;
List<string> ffArgs = new List<string>();
ffArgs.Add($"-map 0:v");
List<string> ffArgs = new List<string>
{
"-c", "copy",
"-map", "0:v",
};
OrderedTracks = OrderedTracks?.Select(x => x.ToLower())?.ToList() ?? new ();
@@ -115,22 +119,20 @@
foreach (var audio in reordered)
{
ffArgs.Add($"-map " + audio.IndexString);
ffArgs.AddRange(new[] { "-map", audio.IndexString });
}
if (videoInfo.SubtitleStreams?.Any() == true)
ffArgs.Add("-map 0:s -c copy");
ffArgs.AddRange(new[] { "-map", "0:s" });
// this makes the first audio track now the default track
ffArgs.Add("-disposition:a:0 default");
string ffArgsLine = string.Join(" ", ffArgs);
ffArgs.AddRange(new[] { "-disposition:a:0", "default" });
string extension = new FileInfo(args.WorkingFile).Extension;
if(extension.StartsWith("."))
extension = extension.Substring(1);
if (Encode(args, ffmpegExe, ffArgsLine, extension) == false)
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;

View File

@@ -35,7 +35,7 @@
{
if (string.IsNullOrEmpty(at.Language))
{
ffArgs.Add($"-metadata:s:a:{index} language={Language.ToLower()}");
ffArgs.AddRange(new[] { $"-metadata:s:a:{index}", $"language={Language.ToLower()}" });
}
++index;
}
@@ -43,9 +43,10 @@
return 2; // nothing to do
ffArgs.Insert(0, $"-map 0 -c copy");
string ffArgsLine = string.Join(" ", ffArgs);
ffArgs.Insert(0, "-map");
ffArgs.Insert(1, "0");
ffArgs.Insert(2, "-c");
ffArgs.Insert(3, "copy");
string extension = new FileInfo(args.WorkingFile).Extension;
if(extension.StartsWith("."))
@@ -53,7 +54,7 @@
args.Logger?.DLog("Working file: " + args.WorkingFile);
args.Logger?.DLog("Extension: " + extension);
if (Encode(args, ffmpegExe, ffArgsLine, extension) == false)
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;

View File

@@ -69,8 +69,8 @@
string tempMetaDataFile = Path.Combine(args.TempPath, Guid.NewGuid().ToString() + ".txt");
File.WriteAllText(tempMetaDataFile, metadata.ToString());
string ffArgs = $"-i \"{tempMetaDataFile}\" -map_metadata 1 -codec copy -max_muxing_queue_size 1024";
if (Encode(args, ffmpegExe, ffArgs))
string[] ffArgs = new[] { "-i", tempMetaDataFile, "-map_metadata", "1", "-codec", "copy", "-max_muxing_queue_size", "1024" };
if (Encode(args, ffmpegExe, ffArgs.ToList()))
{
args.Logger?.ILog($"Adding {chapter} chapters to file");
return 1;

View File

@@ -89,7 +89,15 @@
string concatList = segmentPrefix + "concatlist.txt";
File.WriteAllLines(concatList, segments.Select(x => $"file '{x}'"));
bool concatResult = Encode(args, ffmpegExe, $"-f concat -safe 0 -i \"{concatList}\" -c copy", dontAddInputFile: true, extension: extension);
List<string> ffArgs = new List<string>
{
"-f", "concat",
"-safe", "0",
"-i", "concatList",
"-c", "copy"
};
bool concatResult = Encode(args, ffmpegExe, ffArgs, dontAddInputFile: true, extension: extension);
foreach(string segment in segments.Union(new[] { concatList }))
{
@@ -108,7 +116,13 @@
bool EncodeSegment(float start, float duration)
{
string segment = segmentPrefix + (++count).ToString("D2") + "." + extension;
if (Encode(args, ffmpegExe, $"-ss {start} -t {duration} -c copy", outputFile: segment, updateWorkingFile: false))
List<string> ffArgs = new List<string>
{
"-ss", start.ToString(),
"-t", duration.ToString(),
"-c", "copy"
};
if (Encode(args, ffmpegExe, ffArgs, outputFile: segment, updateWorkingFile: false))
{
segments.Add(segment);
return true;

View File

@@ -18,7 +18,13 @@ namespace FileFlows.VideoNodes
private FFMpegEncoder Encoder;
protected bool Encode(NodeParameters args, string ffmpegExe, string ffmpegParameters, string extension = "mkv", string outputFile = "", bool updateWorkingFile = true, bool dontAddInputFile = false)
protected bool Encode(NodeParameters args, string ffmpegExe, List<string> ffmpegParameters, string extension = "mkv", string outputFile = "", bool updateWorkingFile = true, bool dontAddInputFile = false)
{
string output;
return Encode(args, ffmpegExe, ffmpegParameters, out output, extension, outputFile, updateWorkingFile, dontAddInputFile);
}
protected bool Encode(NodeParameters args, string ffmpegExe, List<string> ffmpegParameters, out string ouput, string extension = "mkv", string outputFile = "", bool updateWorkingFile = true, bool dontAddInputFile = false)
{
if (string.IsNullOrEmpty(extension))
extension = "mkv";
@@ -40,9 +46,9 @@ namespace FileFlows.VideoNodes
}
}
bool success = Encoder.Encode(args.WorkingFile, outputFile, ffmpegParameters, dontAddInputFile: dontAddInputFile);
args.Logger.ILog("Encoding successful: " + success);
if (success && updateWorkingFile)
var success = Encoder.Encode(args.WorkingFile, outputFile, ffmpegParameters, dontAddInputFile: dontAddInputFile);
args.Logger.ILog("Encoding successful: " + success.successs);
if (success.successs && updateWorkingFile)
{
args.SetWorkingFile(outputFile);
@@ -54,7 +60,8 @@ namespace FileFlows.VideoNodes
}
Encoder.AtTime -= AtTimeEvent;
Encoder = null;
return success;
ouput = success.output;
return success.successs;
}
public override Task Cancel()

View File

@@ -44,11 +44,14 @@ namespace FileFlows.VideoNodes
string outputFile = Path.Combine(args.TempPath, Guid.NewGuid().ToString() + "." + Extension);
string cmd = CommandLine.Replace("{WorkingFile}", "\"" + args.WorkingFile + "\"")
.Replace("{Output}", outputFile)
.Replace("{output}", outputFile);
List<string> ffArgs = CommandLine.SplitCommandLine().Select(x =>
{
if (x.ToLower() == "{workingfile}") return args.WorkingFile;
if (x.ToLower() == "{output}") return outputFile;
return x;
}).ToList();
if (Encode(args, ffmpegExe, cmd) == false)
if (Encode(args, ffmpegExe, ffArgs) == false)
return -1;
return 1;

View File

@@ -23,7 +23,7 @@
try
{
if (Encode(args, ffmpegExe, "-c copy -map 0", "mkv") == false)
if (Encode(args, ffmpegExe, new List<string> { "-c", "copy", "-map", "0" }, "mkv") == false)
return -1;
return 1;
@@ -54,7 +54,7 @@
try
{
if (Encode(args, ffmpegExe, "-c copy -map 0", "mp4") == false)
if (Encode(args, ffmpegExe, new List<string> { "-c", "copy", "-map", "0" }, "mp4") == false)
return -1;
return 1;

View File

@@ -55,8 +55,11 @@
if (string.IsNullOrEmpty(ffmpegExe))
return -1;
List<string> ffArgs = new List<string>();
ffArgs.Add($"-map 0:v -map 0:a");
List<string> ffArgs = new List<string>()
{
"-map", "0:v",
"-map", "0:a",
};
var removeCodecs = SubtitlesToRemove?.Where(x => string.IsNullOrWhiteSpace(x) == false)?.Select(x => x.ToLower())?.ToList() ?? new List<string>();
@@ -73,7 +76,7 @@
foundBadSubtitle = true;
continue;
}
ffArgs.Add("-map " + sub.IndexString);
ffArgs.AddRange(new[] { "-map", sub.IndexString});
}
if(foundBadSubtitle == false)
@@ -81,15 +84,14 @@
// nothing to remove
return 2;
}
ffArgs.Add("-c copy");
ffArgs.AddRange(new[] { "-c", "copy" });
string ffArgsLine = string.Join(" ", ffArgs);
string extension = new FileInfo(args.WorkingFile).Extension;
if(extension.StartsWith("."))
extension = extension.Substring(1);
if (Encode(args, ffmpegExe, ffArgsLine, extension) == false)
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;

View File

@@ -140,8 +140,8 @@ namespace FileFlows.VideoNodes
List<string> ffArgs = new List<string>();
ffArgs.Add(encodeVideoParameters?.EmptyAsNull() ?? copyVideoStream);
ffArgs.Add(encodeAudioParameters?.EmptyAsNull() ?? copyAudioStream);
ffArgs.AddRange((encodeVideoParameters?.EmptyAsNull() ?? copyVideoStream).Split(" "));
ffArgs.AddRange((encodeAudioParameters?.EmptyAsNull() ?? copyAudioStream).Split(" "));
TotalTime = videoInfo.VideoStreams[0].Duration;
args.Logger.ILog("### Total Time: " + TotalTime);
@@ -151,9 +151,9 @@ namespace FileFlows.VideoNodes
if (SupportsSubtitles(args, videoInfo, Extension))
{
if (Language != string.Empty)
ffArgs.Add($"-map 0:s:m:language:{Language}? -c:s copy");
ffArgs.AddRange(new[] { "-map", $"0:s:m:language:{Language}?", "-c:s", "copy" });
else
ffArgs.Add($"-map 0:s? -c:s copy");
ffArgs.AddRange(new[] { "-map", "0:s?", "-c:s", "copy" });
}
else
{
@@ -161,9 +161,8 @@ namespace FileFlows.VideoNodes
}
}
string ffArgsLine = string.Join(" ", ffArgs);
if (Encode(args, ffmpegExe, ffArgsLine, Extension) == false)
if (Encode(args, ffmpegExe, ffArgs, Extension) == false)
return -1;
return 1;

View File

@@ -88,14 +88,15 @@ namespace FileFlows.VideoNodes
if (string.IsNullOrEmpty(ffmpegExe))
return -1;
List<string> ffArgs = new List<string>();
string codec = CheckVideoCodec(ffmpegExe, VideoCodec);
ffArgs.Add($"-vf scale={Resolution}:flags=lanczos -c:v {codec}");
List<string> ffArgs = new List<string>()
{
"-vf", $"scale={Resolution}:flags=lanczos",
"-c:v", "codec"
};
string ffArgsLine = string.Join(" ", ffArgs);
if (Encode(args, ffmpegExe, ffArgsLine, Extension) == false)
if (Encode(args, ffmpegExe, ffArgs, Extension) == false)
return -1;
return 1;

View File

@@ -1,140 +1,140 @@
namespace FileFlows.VideoNodes
{
using System.ComponentModel;
using System.Text.RegularExpressions;
using FileFlows.Plugin;
using FileFlows.Plugin.Attributes;
//namespace FileFlows.VideoNodes
//{
// using System.ComponentModel;
// using System.Text.RegularExpressions;
// using FileFlows.Plugin;
// using FileFlows.Plugin.Attributes;
public class Video_H265_AC3 : EncodingNode
{
// public class Video_H265_AC3 : EncodingNode
// {
[DefaultValue("eng")]
[Text(1)]
public string Language { get; set; }
// [DefaultValue("eng")]
// [Text(1)]
// public string Language { get; set; }
[DefaultValue(21)]
[NumberInt(2)]
public int Crf { get; set; }
[DefaultValue(true)]
[Boolean(3)]
public bool NvidiaEncoding { get; set; }
[DefaultValue(0)]
[NumberInt(4)]
public int Threads { get; set; }
// [DefaultValue(21)]
// [NumberInt(2)]
// public int Crf { get; set; }
// [DefaultValue(true)]
// [Boolean(3)]
// public bool NvidiaEncoding { get; set; }
// [DefaultValue(0)]
// [NumberInt(4)]
// public int Threads { get; set; }
[DefaultValue(false)]
[Boolean(5)]
public bool NormalizeAudio { get; set; }
// [DefaultValue(false)]
// [Boolean(5)]
// public bool NormalizeAudio { get; set; }
[DefaultValue(false)]
[Boolean(6)]
public bool ForceRencode { get; set; }
// [DefaultValue(false)]
// [Boolean(6)]
// public bool ForceRencode { get; set; }
public override string Icon => "far fa-file-video";
// public override string Icon => "far fa-file-video";
public override int Execute(NodeParameters args)
{
this.args = args;
try
{
VideoInfo videoInfo = GetVideoInfo(args);
if (videoInfo == null)
return -1;
// public override int Execute(NodeParameters args)
// {
// this.args = args;
// try
// {
// VideoInfo videoInfo = GetVideoInfo(args);
// if (videoInfo == null)
// return -1;
Language = Language?.ToLower() ?? "";
// Language = Language?.ToLower() ?? "";
// ffmpeg is one based for stream index, so video should be 1, audio should be 2
// // ffmpeg is one based for stream index, so video should be 1, audio should be 2
var videoH265 = videoInfo.VideoStreams.FirstOrDefault(x => Regex.IsMatch(x.Codec ?? "", @"^(hevc|h(\.)?265)$", RegexOptions.IgnoreCase));
var videoTrack = videoH265 ?? videoInfo.VideoStreams[0];
args.Logger.ILog("Video: ", videoTrack);
// var videoH265 = videoInfo.VideoStreams.FirstOrDefault(x => Regex.IsMatch(x.Codec ?? "", @"^(hevc|h(\.)?265)$", RegexOptions.IgnoreCase));
// var videoTrack = videoH265 ?? videoInfo.VideoStreams[0];
// args.Logger.ILog("Video: ", videoTrack);
var bestAudio = videoInfo.AudioStreams.Where(x => System.Text.Json.JsonSerializer.Serialize(x).ToLower().Contains("commentary") == false)
.OrderBy(x =>
{
if (Language != string.Empty)
{
args.Logger.ILog("Language: " + x.Language, x);
if (string.IsNullOrEmpty(x.Language))
return 50; // no language specified
if (x.Language?.ToLower() != Language)
return 100; // low priority not the desired language
}
return 0;
})
.ThenByDescending(x => x.Channels)
//.ThenBy(x => x.CodecName.ToLower() == "ac3" ? 0 : 1) // if we do this we can get commentary tracks...
.ThenBy(x => x.Index)
.FirstOrDefault();
// var bestAudio = videoInfo.AudioStreams.Where(x => System.Text.Json.JsonSerializer.Serialize(x).ToLower().Contains("commentary") == false)
// .OrderBy(x =>
// {
// if (Language != string.Empty)
// {
// args.Logger.ILog("Language: " + x.Language, x);
// if (string.IsNullOrEmpty(x.Language))
// return 50; // no language specified
// if (x.Language?.ToLower() != Language)
// return 100; // low priority not the desired language
// }
// return 0;
// })
// .ThenByDescending(x => x.Channels)
// //.ThenBy(x => x.CodecName.ToLower() == "ac3" ? 0 : 1) // if we do this we can get commentary tracks...
// .ThenBy(x => x.Index)
// .FirstOrDefault();
bool firstAc3 = bestAudio?.Codec?.ToLower() == "ac3" && videoInfo.AudioStreams[0] == bestAudio;
args.Logger.ILog("Best Audio: ", bestAudio == null ? (object)"null" : (object)bestAudio);
// bool firstAc3 = bestAudio?.Codec?.ToLower() == "ac3" && videoInfo.AudioStreams[0] == bestAudio;
// args.Logger.ILog("Best Audio: ", bestAudio == null ? (object)"null" : (object)bestAudio);
string crop = args.GetParameter<string>(DetectBlackBars.CROP_KEY) ?? "";
if (crop != string.Empty)
crop = " -vf crop=" + crop;
// string crop = args.GetParameter<string>(DetectBlackBars.CROP_KEY) ?? "";
// if (crop != string.Empty)
// crop = " -vf crop=" + crop;
if (ForceRencode == false && firstAc3 == true && videoH265 != null)
{
if (crop == string.Empty)
{
args.Logger.DLog("File is hevc with the first audio track being AC3");
return 2;
}
else
{
args.Logger.ILog("Video is hevc and ac3 but needs to be cropped");
}
}
// if (ForceRencode == false && firstAc3 == true && videoH265 != null)
// {
// if (crop == string.Empty)
// {
// args.Logger.DLog("File is hevc with the first audio track being AC3");
// return 2;
// }
// else
// {
// args.Logger.ILog("Video is hevc and ac3 but needs to be cropped");
// }
// }
string ffmpegExe = GetFFMpegExe(args);
if (string.IsNullOrEmpty(ffmpegExe))
return -1;
// string ffmpegExe = GetFFMpegExe(args);
// if (string.IsNullOrEmpty(ffmpegExe))
// return -1;
List<string> ffArgs = new List<string>();
// List<string> ffArgs = new List<string>();
if (NvidiaEncoding == false && Threads > 0)
ffArgs.Add($"-threads {Math.Min(Threads, 16)}");
// if (NvidiaEncoding == false && Threads > 0)
// ffArgs.AddRange(new[] { "-threads", Math.Min(Threads, 16).ToString() });
if (videoH265 == null || crop != string.Empty)
ffArgs.Add($"-map 0:v:0 -c:v {(NvidiaEncoding ? "hevc_nvenc -preset hq" : "libx265")} -crf " + (Crf > 0 ? Crf : 21) + crop);
else
ffArgs.Add($"-map 0:v:0 -c:v copy");
// if (videoH265 == null || crop != string.Empty)
// ffArgs.AddRange(new[] { "-map", "0:v:0", "-c:v", NvidiaEncoding ? "hevc_nvenc - preset hq" : "libx265")} -crf " + (Crf > 0 ? Crf : 21) + crop);
// "
// else
// ffArgs.Add($"-map 0:v:0 -c:v copy");
TotalTime = videoInfo.VideoStreams[0].Duration;
// TotalTime = videoInfo.VideoStreams[0].Duration;
if (NormalizeAudio)
{
int sampleRate = bestAudio.SampleRate > 0 ? bestAudio.SampleRate : 48_000;
ffArgs.Add($"-map 0:{bestAudio.Index} -c:a ac3 -ar {sampleRate} -af loudnorm=I=-24:LRA=7:TP=-2.0");
}
else if (bestAudio.Codec.ToLower() != "ac3")
ffArgs.Add($"-map 0:{bestAudio.Index} -c:a ac3");
else
ffArgs.Add($"-map 0:{bestAudio.Index} -c:a copy");
// if (NormalizeAudio)
// {
// int sampleRate = bestAudio.SampleRate > 0 ? bestAudio.SampleRate : 48_000;
// ffArgs.Add($"-map 0:{bestAudio.Index} -c:a ac3 -ar {sampleRate} -af loudnorm=I=-24:LRA=7:TP=-2.0");
// }
// else if (bestAudio.Codec.ToLower() != "ac3")
// ffArgs.Add($"-map 0:{bestAudio.Index} -c:a ac3");
// else
// ffArgs.Add($"-map 0:{bestAudio.Index} -c:a copy");
if (Language != string.Empty)
ffArgs.Add($"-map 0:s:m:language:{Language}? -c:s copy");
else
ffArgs.Add($"-map 0:s? -c:s copy");
string ffArgsLine = string.Join(" ", ffArgs);
if (Encode(args, ffmpegExe, ffArgsLine) == false)
return -1;
return 1;
}
catch (Exception ex)
{
args.Logger.ELog("Failed processing VideoFile: " + ex.Message);
return -1;
}
}
}
// if (Language != string.Empty)
// ffArgs.Add($"-map 0:s:m:language:{Language}? -c:s copy");
// else
// ffArgs.Add($"-map 0:s? -c:s copy");
}
// if (Encode(args, ffmpegExe, ffArgs) == false)
// return -1;
// return 1;
// }
// catch (Exception ex)
// {
// args.Logger.ELog("Failed processing VideoFile: " + ex.Message);
// return -1;
// }
// }
// }
//}