diff --git a/VideoNodes/ExtensionMethods.cs b/VideoNodes/ExtensionMethods.cs index e9c21ba7..a8fe50de 100644 --- a/VideoNodes/ExtensionMethods.cs +++ b/VideoNodes/ExtensionMethods.cs @@ -1,5 +1,6 @@ namespace FileFlows.VideoNodes { + using System.Linq; internal static class ExtensionMethods { public static void AddOrUpdate(this Dictionary dict, string key, object value) { @@ -12,5 +13,44 @@ { return str == string.Empty ? null : str; } + + public static IEnumerable 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 Split(this string str, + Func 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; + } } } diff --git a/VideoNodes/FFMpegEncoder.cs b/VideoNodes/FFMpegEncoder.cs index cbadbed0..65f8f013 100644 --- a/VideoNodes/FFMpegEncoder.cs +++ b/VideoNodes/FFMpegEncoder.cs @@ -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 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 (); - 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 ExecuteShellCommand(string command, string arguments, int timeout = 0) + public async Task ExecuteShellCommand(string command, List 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 { diff --git a/VideoNodes/Tests/AudioNormalizationTests.cs b/VideoNodes/Tests/AudioNormalizationTests.cs index 754f0beb..df22a00b 100644 --- a/VideoNodes/Tests/AudioNormalizationTests.cs +++ b/VideoNodes/Tests/AudioNormalizationTests.cs @@ -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)); } diff --git a/VideoNodes/VideoNodes/AudioAdjustVolume.cs b/VideoNodes/VideoNodes/AudioAdjustVolume.cs index d4ac4add..629a7aed 100644 --- a/VideoNodes/VideoNodes/AudioAdjustVolume.cs +++ b/VideoNodes/VideoNodes/AudioAdjustVolume.cs @@ -43,25 +43,27 @@ return 2; } - List ffArgs = new List(); - ffArgs.Add($"-map 0:v"); + List ffArgs = new List + { + "-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; diff --git a/VideoNodes/VideoNodes/AudioNormalization.cs b/VideoNodes/VideoNodes/AudioNormalization.cs index 961ea432..c6a28afb 100644 --- a/VideoNodes/VideoNodes/AudioNormalization.cs +++ b/VideoNodes/VideoNodes/AudioNormalization.cs @@ -44,10 +44,10 @@ List ffArgs = new List(); - 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(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 { "-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(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; } diff --git a/VideoNodes/VideoNodes/AudioTrackReorder.cs b/VideoNodes/VideoNodes/AudioTrackReorder.cs index d4b9675e..6d6c102e 100644 --- a/VideoNodes/VideoNodes/AudioTrackReorder.cs +++ b/VideoNodes/VideoNodes/AudioTrackReorder.cs @@ -98,8 +98,12 @@ if (string.IsNullOrEmpty(ffmpegExe)) return -1; - List ffArgs = new List(); - ffArgs.Add($"-map 0:v"); + List ffArgs = new List + { + "-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; diff --git a/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs b/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs index 9f3490c7..71f20f80 100644 --- a/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs +++ b/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs @@ -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; diff --git a/VideoNodes/VideoNodes/ComskipChapters.cs b/VideoNodes/VideoNodes/ComskipChapters.cs index d0610134..7b911fc9 100644 --- a/VideoNodes/VideoNodes/ComskipChapters.cs +++ b/VideoNodes/VideoNodes/ComskipChapters.cs @@ -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; diff --git a/VideoNodes/VideoNodes/ComskipRemoveAds.cs b/VideoNodes/VideoNodes/ComskipRemoveAds.cs index 4e9bf9cf..63f254ab 100644 --- a/VideoNodes/VideoNodes/ComskipRemoveAds.cs +++ b/VideoNodes/VideoNodes/ComskipRemoveAds.cs @@ -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 ffArgs = new List + { + "-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 ffArgs = new List + { + "-ss", start.ToString(), + "-t", duration.ToString(), + "-c", "copy" + }; + if (Encode(args, ffmpegExe, ffArgs, outputFile: segment, updateWorkingFile: false)) { segments.Add(segment); return true; diff --git a/VideoNodes/VideoNodes/EncodingNode.cs b/VideoNodes/VideoNodes/EncodingNode.cs index 23936f87..17e946f8 100644 --- a/VideoNodes/VideoNodes/EncodingNode.cs +++ b/VideoNodes/VideoNodes/EncodingNode.cs @@ -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 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 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() diff --git a/VideoNodes/VideoNodes/FFMPEG.cs b/VideoNodes/VideoNodes/FFMPEG.cs index 0e57babc..3ffdb245 100644 --- a/VideoNodes/VideoNodes/FFMPEG.cs +++ b/VideoNodes/VideoNodes/FFMPEG.cs @@ -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 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; diff --git a/VideoNodes/VideoNodes/Remux.cs b/VideoNodes/VideoNodes/Remux.cs index c49f19f5..69dfb7d9 100644 --- a/VideoNodes/VideoNodes/Remux.cs +++ b/VideoNodes/VideoNodes/Remux.cs @@ -23,7 +23,7 @@ try { - if (Encode(args, ffmpegExe, "-c copy -map 0", "mkv") == false) + if (Encode(args, ffmpegExe, new List { "-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 { "-c", "copy", "-map", "0" }, "mp4") == false) return -1; return 1; diff --git a/VideoNodes/VideoNodes/SubtitleRemover.cs b/VideoNodes/VideoNodes/SubtitleRemover.cs index aa21bd90..9865a5bb 100644 --- a/VideoNodes/VideoNodes/SubtitleRemover.cs +++ b/VideoNodes/VideoNodes/SubtitleRemover.cs @@ -55,8 +55,11 @@ if (string.IsNullOrEmpty(ffmpegExe)) return -1; - List ffArgs = new List(); - ffArgs.Add($"-map 0:v -map 0:a"); + List ffArgs = new List() + { + "-map", "0:v", + "-map", "0:a", + }; var removeCodecs = SubtitlesToRemove?.Where(x => string.IsNullOrWhiteSpace(x) == false)?.Select(x => x.ToLower())?.ToList() ?? new List(); @@ -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; diff --git a/VideoNodes/VideoNodes/VideoEncode.cs b/VideoNodes/VideoNodes/VideoEncode.cs index 21f692a1..c26ba878 100644 --- a/VideoNodes/VideoNodes/VideoEncode.cs +++ b/VideoNodes/VideoNodes/VideoEncode.cs @@ -140,8 +140,8 @@ namespace FileFlows.VideoNodes List ffArgs = new List(); - 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; diff --git a/VideoNodes/VideoNodes/VideoScaler.cs b/VideoNodes/VideoNodes/VideoScaler.cs index d4c002e1..ab2c5104 100644 --- a/VideoNodes/VideoNodes/VideoScaler.cs +++ b/VideoNodes/VideoNodes/VideoScaler.cs @@ -88,14 +88,15 @@ namespace FileFlows.VideoNodes if (string.IsNullOrEmpty(ffmpegExe)) return -1; - List ffArgs = new List(); string codec = CheckVideoCodec(ffmpegExe, VideoCodec); - ffArgs.Add($"-vf scale={Resolution}:flags=lanczos -c:v {codec}"); + List ffArgs = new List() + { + "-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; diff --git a/VideoNodes/VideoNodes/Video_H265_AC3.cs b/VideoNodes/VideoNodes/Video_H265_AC3.cs index abaa6d43..d71e3a29 100644 --- a/VideoNodes/VideoNodes/Video_H265_AC3.cs +++ b/VideoNodes/VideoNodes/Video_H265_AC3.cs @@ -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(DetectBlackBars.CROP_KEY) ?? ""; - if (crop != string.Empty) - crop = " -vf crop=" + crop; +// string crop = args.GetParameter(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 ffArgs = new List(); +// List ffArgs = new List(); - 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"); -} \ No newline at end of file +// if (Encode(args, ffmpegExe, ffArgs) == false) +// return -1; + +// return 1; +// } +// catch (Exception ex) +// { +// args.Logger.ELog("Failed processing VideoFile: " + ex.Message); +// return -1; +// } +// } +// } + + +//} \ No newline at end of file