diff --git a/BasicNodes/BasicNodes.csproj b/BasicNodes/BasicNodes.csproj index c51fe385..7c90d309 100644 Binary files a/BasicNodes/BasicNodes.csproj and b/BasicNodes/BasicNodes.csproj differ diff --git a/BasicNodes/File/CopyFile.cs b/BasicNodes/File/CopyFile.cs index d5c209a6..3f90f9fd 100644 --- a/BasicNodes/File/CopyFile.cs +++ b/BasicNodes/File/CopyFile.cs @@ -58,6 +58,13 @@ namespace FileFlows.BasicNodes.File else dest = Path.Combine(dest, new FileInfo(args.FileName).Name); + var fiDest = new FileInfo(dest); + var fiWorking = new FileInfo(args.WorkingFile); + if (string.IsNullOrEmpty(fiDest.Extension) == false && fiDest.Extension != fiWorking.Extension) + { + dest = dest.Substring(0, dest.LastIndexOf(".")) + fiWorking.Extension; + } + var destDir = new FileInfo(dest).DirectoryName; args.CreateDirectoryIfNotExists(destDir ?? String.Empty); @@ -67,6 +74,7 @@ namespace FileFlows.BasicNodes.File dest = Path.Combine(destDir!, destFile); } + args.Logger?.ILog($"Copying file '{args.WorkingFile}' to '{dest}"); // have to use file streams so we can report progress int bufferSize = 1024 * 1024; diff --git a/BasicNodes/File/MoveFile.cs b/BasicNodes/File/MoveFile.cs index f9744571..b0eecf6c 100644 --- a/BasicNodes/File/MoveFile.cs +++ b/BasicNodes/File/MoveFile.cs @@ -45,6 +45,12 @@ namespace FileFlows.BasicNodes.File else dest = Path.Combine(dest, new FileInfo(args.FileName).Name); + var fiDest = new FileInfo(dest); + var fiWorking = new FileInfo(args.WorkingFile); + if (string.IsNullOrEmpty(fiDest.Extension) == false && fiDest.Extension != fiWorking.Extension) + { + dest = dest.Substring(0, dest.LastIndexOf(".")) + fiWorking.Extension; + } if (string.IsNullOrEmpty(DestinationFile) == false) { @@ -52,7 +58,7 @@ namespace FileFlows.BasicNodes.File dest = Path.Combine(new FileInfo(dest).DirectoryName!, destFile); } - var fiDest = new FileInfo(dest); + fiDest = new FileInfo(dest); var fiWorkingFile = new FileInfo(args.WorkingFile); if (fiDest.Extension != fiWorkingFile.Extension) { diff --git a/BasicNodes/Functions/Function.cs b/BasicNodes/Functions/Function.cs index 714e1c8d..f1a24235 100644 --- a/BasicNodes/Functions/Function.cs +++ b/BasicNodes/Functions/Function.cs @@ -21,7 +21,7 @@ namespace FileFlows.BasicNodes.Functions public new int Outputs { get; set; } [Required] - [DefaultValue("// Variables contain variables available to this node from previous nodes.\n// Logger lets you log messages to the flow output.\n\n// return 0 to complete the flow.\n// return -1 to signal an error in the flow\n// return 1+ to select which output node will be processed next\n\nif(Variables.FileSize === 0)\n\treturn -1;\n\nreturn 0;")] + [DefaultValue("// Variables contain variables available to this node from previous nodes.\n// Logger lets you log messages to the flow output.\n\n// return 0 to complete the flow.\n// return -1 to signal an error in the flow\n// return 1+ to select which output node will be processed next\n\nif(Variables.file.Size === 0)\n\treturn -1;\n\nreturn 0;")] [Code(2)] public string Code { get; set; } diff --git a/VideoNodes/VideoNodes.csproj b/VideoNodes/VideoNodes.csproj index c521de88..4bd7898d 100644 Binary files a/VideoNodes/VideoNodes.csproj and b/VideoNodes/VideoNodes.csproj differ diff --git a/VideoNodes/VideoNodes.en.json b/VideoNodes/VideoNodes.en.json index 635b1948..bc3147f6 100644 --- a/VideoNodes/VideoNodes.en.json +++ b/VideoNodes/VideoNodes.en.json @@ -10,6 +10,14 @@ "Languages-Help": "The order of languages to sort the audio tracks by. This sorting is done before the codec." } }, + "AudioTrackSetLanguage": { + "Label": "Audio: Set Language", + "Description": "Allows you to set the language for any audio tracks that have no language set. If the audio track does have a language set, it will be skipped.\n\nOutput 1: Audio Tracks were updated\nOutput 2: No audio tracks were needing to be updated", + "Fields": { + "Language": "Language", + "Language-Help": "The ISO 639-2 language code to use. \nhttps://en.wikipedia.org/wiki/List_of_ISO_639-2_codes" + } + }, "VideoFile": { "Description": "An input video file that has had its VideoInformation read and can be processed" }, diff --git a/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs b/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs new file mode 100644 index 00000000..9f3490c7 --- /dev/null +++ b/VideoNodes/VideoNodes/AudioTrackSetLanguage.cs @@ -0,0 +1,68 @@ +namespace FileFlows.VideoNodes +{ + using FileFlows.Plugin; + using FileFlows.Plugin.Attributes; + using System; + using System.Collections.Generic; + using System.ComponentModel.DataAnnotations; + + public class AudioTrackSetLanguage : EncodingNode + { + public override int Outputs => 2; + + public override string Icon => "fas fa-comment-dots"; + + [Required] + [Text(1)] + public string Language { get; set; } + + public override int Execute(NodeParameters args) + { + try + { + VideoInfo videoInfo = GetVideoInfo(args); + if (videoInfo == null) + return -1; + + string ffmpegExe = GetFFMpegExe(args); + if (string.IsNullOrEmpty(ffmpegExe)) + return -1; + + List ffArgs = new List(); + + int index = 0; + foreach(var at in videoInfo.AudioStreams) + { + if (string.IsNullOrEmpty(at.Language)) + { + ffArgs.Add($"-metadata:s:a:{index} language={Language.ToLower()}"); + } + ++index; + } + if (ffArgs.Count == 0) + return 2; // nothing to do + + + ffArgs.Insert(0, $"-map 0 -c copy"); + + string ffArgsLine = string.Join(" ", ffArgs); + + string extension = new FileInfo(args.WorkingFile).Extension; + if(extension.StartsWith(".")) + extension = extension.Substring(1); + args.Logger?.DLog("Working file: " + args.WorkingFile); + args.Logger?.DLog("Extension: " + extension); + + if (Encode(args, ffmpegExe, ffArgsLine, extension) == false) + return -1; + + return 1; + } + catch (Exception ex) + { + args.Logger?.ELog("Failed processing VideoFile: " + ex.Message); + return -1; + } +} + } +}