diff --git a/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetOriginalLanguageAsDefault.cs b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetOriginalLanguageAsDefault.cs new file mode 100644 index 00000000..e5d1eb0d --- /dev/null +++ b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetOriginalLanguageAsDefault.cs @@ -0,0 +1,148 @@ +using FileFlows.VideoNodes.FfmpegBuilderNodes.Models; + +namespace FileFlows.VideoNodes.FfmpegBuilderNodes; + +/// +/// FFmpeg Builder flow element to set the original language as the default tracks +/// +public class FfmpegBuilderSetOriginalLanguageAsDefault: FfmpegBuilderNode +{ + /// + /// Gets the help URL for the flow element + /// + public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/set-original-language-as-default"; + + /// + /// Gets the number of outputs of the flow element + /// + public override int Outputs => 2; + + /// + /// Gets the icon of the flow element + /// + public override string Icon => "fas fa-globe"; + + /// + /// Gets or sets the stream type + /// + [Select(nameof(StreamTypeOptions), 1)] + public string StreamType { get; set; } + + private static List _StreamTypeOptions; + /// + /// Gets the stream options to show in the UI + /// + public static List StreamTypeOptions + { + get + { + if (_StreamTypeOptions == null) + { + _StreamTypeOptions = new List + { + new () { Label = "Audio", Value = "Audio" }, + new () { Label = "Subtitle", Value = "Subtitle" }, + new () { Label = "Both", Value = "Both" }, + }; + } + return _StreamTypeOptions; + } + } + + /// + /// Executes the flow element + /// + /// the flow parameters + /// the flow output to call next + public override int Execute(NodeParameters args) + { + string originalLanguage; + if (args.Variables.TryGetValue("OriginalLanguage", out object oValue) == false || + string.IsNullOrWhiteSpace(originalLanguage = oValue as string)) + { + args.Logger?.ILog("OriginalLanguage variable was not set."); + return 2; + } + args.Logger?.ILog("OriginalLanguage: " + originalLanguage); + + int changes = 0; + if(StreamType is "Audio" or "Both") + { + changes += ProcessStreams(args, Model.AudioStreams, originalLanguage); + } + if(StreamType is "Subtitle" or "Both") + { + changes += ProcessStreams(args, Model.SubtitleStreams, originalLanguage); + } + + return changes > 0 ? 1 : 2; + } + + private int ProcessStreams(NodeParameters args, List streams, string originalLanguage) where T : FfmpegStream + { + if (streams?.Any() != true) + return 0; + + int changed = 0; + foreach (var stream in streams) + { + if (stream.Deleted) + continue; + + bool isDefault = LanguageMatches(stream.Language, originalLanguage); + if(isDefault) + args.Logger?.ILog($"Stream '{stream.GetType().Name}' '{stream.Language}' set as default."); + + if (stream.IsDefault == isDefault) + continue; + + stream.IsDefault = isDefault; + ++changed; + } + + return changed; + } + + /// + /// Tests if a language matches + /// + /// the language of ths stream + /// the language to test + /// true if matches, otherwise false + private bool LanguageMatches(string streamLanguage, string testLanguage) + { + if (string.IsNullOrWhiteSpace(testLanguage)) + return false; + if (string.IsNullOrWhiteSpace(streamLanguage)) + return false; + if (testLanguage.ToLowerInvariant().Contains(streamLanguage.ToLowerInvariant())) + return true; + try + { + if (LanguageHelper.GetIso2Code(streamLanguage) == LanguageHelper.GetIso2Code(testLanguage)) + return true; + } + catch (Exception) + { + } + + try + { + if (LanguageHelper.GetIso1Code(streamLanguage) == LanguageHelper.GetIso1Code(testLanguage)) + return true; + } + catch (Exception) + { + } + + try + { + var rgx = new Regex(testLanguage, RegexOptions.IgnoreCase); + return rgx.IsMatch(streamLanguage); + } + catch (Exception) + { + return false; + } + } +}