diff --git a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs index 1fcedb94..2fa621ea 100644 --- a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs +++ b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs @@ -95,6 +95,8 @@ Title = item.stream.Title, Language = item.stream.Language, Stream = item.stream, + IsDefault = item.stream.Default, + IsForced = item.stream.Forced }); } diff --git a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegSubtitleStream.cs b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegSubtitleStream.cs index 76cecd2b..cdcb76a3 100644 --- a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegSubtitleStream.cs +++ b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegSubtitleStream.cs @@ -8,6 +8,11 @@ public class FfmpegSubtitleStream : FfmpegStream /// Gets or sets the source subtitle stream /// public SubtitleStream Stream { get; set; } + + /// + /// Gets or sets if this is a forced subtitle + /// + public bool IsForced { get; set; } /// /// Gets or sets if this stream has changed @@ -59,8 +64,15 @@ public class FfmpegSubtitleStream : FfmpegStream if (Metadata.Any()) results.AddRange(Metadata.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString()))); - if (args.UpdateDefaultFlag) - results.AddRange(new[] { "-disposition:a:" + args.OutputTypeIndex, this.IsDefault ? "default" : "0" }); + //if (args.UpdateDefaultFlag) // we always update the default flags for subtitles FF-381 + if(this.IsDefault && this.IsForced) + results.AddRange(new[] { "-disposition:s:" + args.OutputTypeIndex, "+default+forced" }); + else if(this.IsDefault) + results.AddRange(new[] { "-disposition:s:" + args.OutputTypeIndex, "default" }); + else if(this.IsForced) + results.AddRange(new[] { "-disposition:s:" + args.OutputTypeIndex, "forced" }); + else + results.AddRange(new[] { "-disposition:s:" + args.OutputTypeIndex, "0" }); return results.ToArray(); } diff --git a/VideoNodes/FfmpegBuilderNodes/Subtitle/FfmpegBuilderSubtitleClearDefault.cs b/VideoNodes/FfmpegBuilderNodes/Subtitle/FfmpegBuilderSubtitleClearDefault.cs new file mode 100644 index 00000000..ebc29d32 --- /dev/null +++ b/VideoNodes/FfmpegBuilderNodes/Subtitle/FfmpegBuilderSubtitleClearDefault.cs @@ -0,0 +1,73 @@ +namespace FileFlows.VideoNodes.FfmpegBuilderNodes; + +/// +/// A node that will clear the default tag from subtitles +/// +public class FfmpegBuilderSubtitleClearDefault : FfmpegBuilderNode +{ + /// + /// Gets the help URL + /// + public override string HelpUrl => "https://docs.fileflows.com/plugins/video-nodes/ffmpeg-builder/subtitle-clear-default"; + /// + /// Gets the icon + /// + public override string Icon => "fas fa-comment-slash"; + /// + /// Gets the number of outputs + /// + public override int Outputs => 2; + + /// + /// Gets or sets if forced should be left alone + /// + [Boolean(1)] + public bool LeaveForced { get; set; } + + /// + /// Gets or sets if forced should be changed to be the default + /// + [Boolean(2)] + public bool SetForcedDefault { get; set; } + + /// + /// Executes the node + /// + /// the node arguments + /// the output to call next + public override int Execute(NodeParameters args) + { + + if (Model.SubtitleStreams.Any() == false) + return 2; + bool changed = false; + bool defaultSet = false; + foreach (var stream in Model.SubtitleStreams) + { + if (SetForcedDefault && stream.IsDefault == false && stream.IsForced && defaultSet == false) + { + // check this first since this is a forced subtitle that is not set to default and we want it to be + args.Logger?.ILog($"Setting forced subtitle[{stream.Index}] as default: {(stream.Title?.EmptyAsNull() ?? stream.Language?.EmptyAsNull() ?? stream.Stream.Codec)}"); + stream.IsDefault = true; + defaultSet = true; + stream.ForcedChange = true; + continue; + } + + if (stream.IsDefault == false) + continue; // not set to default, no change needed + + if (LeaveForced && stream.Stream.Forced) + { + defaultSet = true; // this stream is set to default, therefor one track is set to default + continue; + } + args.Logger?.ILog($"Clearing default flag from subtitle[{stream.Index}]: {(stream.Title?.EmptyAsNull() ?? stream.Language?.EmptyAsNull() ?? stream.Stream.Codec)}"); + stream.IsDefault = false; + stream.ForcedChange = true; + changed = true; + } + + return changed ? 1 : 2; + } +} diff --git a/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs b/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs index 69ebcb32..46d75489 100644 --- a/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs +++ b/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs @@ -1531,6 +1531,39 @@ public class FfmpegBuilder_BasicTests : TestBase Assert.AreEqual(2, result1); Assert.AreEqual(2, result); } + + + [TestMethod] + public void FfmpegBuilder_SubtitleClearDefault() + { + var logger = new TestLogger(); + var vi = new VideoInfoHelper(FfmpegPath, logger); + var vii = vi.Read(TestFile_DefaultIsForcedSub); + var args = new NodeParameters(TestFile_DefaultIsForcedSub, logger, false, string.Empty); + args.GetToolPathActual = (string tool) => FfmpegPath; + args.TempPath = TempPath; + args.Parameters.Add("VideoInfo", vii); + + FfmpegBuilderStart ffStart = new(); + ffStart.PreExecute(args); + Assert.AreEqual(1, ffStart.Execute(args)); + + + FfmpegBuilderSubtitleClearDefault ffClearDefault = new(); + ffClearDefault.LeaveForced = true; + ffClearDefault.PreExecute(args); + int result1 = ffClearDefault.Execute(args); + Assert.AreEqual(1, result1); + + FfmpegBuilderExecutor ffExecutor = new(); + ffExecutor.PreExecute(args); + int result = ffExecutor.Execute(args); + + string log = logger.ToString(); + Assert.AreEqual(1, result1); + Assert.AreEqual(1, result); + } + } #endif \ No newline at end of file diff --git a/VideoNodes/Tests/_TestBase.cs b/VideoNodes/Tests/_TestBase.cs index 54cb4f2a..4dc961a2 100644 --- a/VideoNodes/Tests/_TestBase.cs +++ b/VideoNodes/Tests/_TestBase.cs @@ -66,6 +66,10 @@ public abstract class TestBase protected string TestFile_BasicMkv => Path.Combine(TestPath, "basic.mkv"); protected string TestFile_Tag => Path.Combine(TestPath, "tag.mp4"); protected string TestFile_Pgs => Path.Combine(TestPath, "pgs.mkv"); + protected string TestFile_Font => Path.Combine(TestPath, "font.mkv"); + protected string TestFile_DefaultSub => Path.Combine(TestPath, "default-sub.mkv"); + protected string TestFile_ForcedDefaultSub => Path.Combine(TestPath, "sub-forced-default.mkv"); + protected string TestFile_DefaultIsForcedSub => Path.Combine(TestPath, "sub-default-is-forced.mkv"); protected string TestFile_TwoPassNegInifinity => Path.Combine(TestPath, "audio_normal_neg_infinity.mkv"); protected string TestFile_4k_h264mov => Path.Combine(TestPath, "4k_h264.mov"); diff --git a/VideoNodes/VideoInfo.cs b/VideoNodes/VideoInfo.cs index caad7ed5..2d5a98fa 100644 --- a/VideoNodes/VideoInfo.cs +++ b/VideoNodes/VideoInfo.cs @@ -163,6 +163,11 @@ public class SubtitleStream : VideoFileStream /// If this is a forced subtitle /// public bool Forced { get; set; } + + /// + /// If this is a the default subtitle track + /// + public bool Default { get; set; } } /// diff --git a/VideoNodes/VideoInfoHelper.cs b/VideoNodes/VideoInfoHelper.cs index 86c20945..788da199 100644 --- a/VideoNodes/VideoInfoHelper.cs +++ b/VideoNodes/VideoInfoHelper.cs @@ -365,6 +365,7 @@ public class VideoInfoHelper if (sub.Codec.EndsWith(",")) sub.Codec = sub.Codec[..^1].Trim(); sub.Language = GetLanguage(line); + sub.Default = info.Contains("(default)"); if (rgxTitle.IsMatch(info)) sub.Title = rgxTitle.Match(info).Value.Trim(); diff --git a/VideoNodes/VideoNodes.en.json b/VideoNodes/VideoNodes.en.json index 63bdb04d..b3f96761 100644 --- a/VideoNodes/VideoNodes.en.json +++ b/VideoNodes/VideoNodes.en.json @@ -287,6 +287,20 @@ "RemoveAdditionalMetadata-Help": "If additional metadata should be removed. Additional metadata is non-standard metadata that may have been added to a video file, eg by iTunes." } }, + "FfmpegBuilderSubtitleClearDefault": { + "Label": "FFMPEG Builder: Subtitle Clear Default", + "Description": "This node will clear the default flag from subtitles.", + "Fields": { + "LeaveForced": "Leave Forced", + "LeaveForced-Help": "When checked all forced subtitles will not be touched, they will maintain their original setting. This is executed prior to 'Set Forced Default' so takes precedent.", + "SetForcedDefault": "Set Forced Default", + "SetForcedDefault-Help": "When checked the first subtitle that is found with the Forced field set, will be set as default, all others will have their default flag cleared." + }, + "Outputs": { + "1": "Subtitles default flags have been changed", + "2": "Subtitles had no changes made" + } + }, "FfmpegBuilderSubtitleFormatRemover": { "Label": "FFMPEG Builder: Subtitle Format Remover", "Description": "Removes subtitles from a video file if found.",