diff --git a/Apprise/Apprise.csproj b/Apprise/Apprise.csproj index 5abb4ad4..4596b27b 100644 Binary files a/Apprise/Apprise.csproj and b/Apprise/Apprise.csproj differ diff --git a/BasicNodes/BasicNodes.csproj b/BasicNodes/BasicNodes.csproj index b94382d4..541afdb9 100644 Binary files a/BasicNodes/BasicNodes.csproj and b/BasicNodes/BasicNodes.csproj differ diff --git a/ChecksumNodes/ChecksumNodes.csproj b/ChecksumNodes/ChecksumNodes.csproj index 87c6a07a..ddd2c5ad 100644 Binary files a/ChecksumNodes/ChecksumNodes.csproj and b/ChecksumNodes/ChecksumNodes.csproj differ diff --git a/CollectionNodes/CollectionNodes.csproj b/CollectionNodes/CollectionNodes.csproj index 71dc3d42..9db42547 100644 Binary files a/CollectionNodes/CollectionNodes.csproj and b/CollectionNodes/CollectionNodes.csproj differ diff --git a/DiscordNodes/DiscordNodes.csproj b/DiscordNodes/DiscordNodes.csproj index cb20b378..729f591c 100644 Binary files a/DiscordNodes/DiscordNodes.csproj and b/DiscordNodes/DiscordNodes.csproj differ diff --git a/EmailNodes/EmailNodes.csproj b/EmailNodes/EmailNodes.csproj index 918cbb79..46dab284 100644 Binary files a/EmailNodes/EmailNodes.csproj and b/EmailNodes/EmailNodes.csproj differ diff --git a/Emby/Emby.csproj b/Emby/Emby.csproj index ee308ac7..4969388d 100644 Binary files a/Emby/Emby.csproj and b/Emby/Emby.csproj differ diff --git a/Gotify/Gotify.csproj b/Gotify/Gotify.csproj index 25c2ef22..3bca8b26 100644 Binary files a/Gotify/Gotify.csproj and b/Gotify/Gotify.csproj differ diff --git a/ImageNodes/ImageNodes.csproj b/ImageNodes/ImageNodes.csproj index 786a21cf..d789e8af 100644 Binary files a/ImageNodes/ImageNodes.csproj and b/ImageNodes/ImageNodes.csproj differ diff --git a/MetaNodes/MetaNodes.csproj b/MetaNodes/MetaNodes.csproj index 41ab370e..deabd4bd 100644 Binary files a/MetaNodes/MetaNodes.csproj and b/MetaNodes/MetaNodes.csproj differ diff --git a/MusicNodes/MusicNodes.csproj b/MusicNodes/MusicNodes.csproj index 02f22f3f..392fc0fc 100644 Binary files a/MusicNodes/MusicNodes.csproj and b/MusicNodes/MusicNodes.csproj differ diff --git a/Plex/Plex.csproj b/Plex/Plex.csproj index 0f0e5548..f78449dd 100644 Binary files a/Plex/Plex.csproj and b/Plex/Plex.csproj differ diff --git a/VideoNodes/FfmpegBuilderNodes/Audio/FfmpegBuilderAudioTrackRemover.cs b/VideoNodes/FfmpegBuilderNodes/Audio/FfmpegBuilderAudioTrackRemover.cs index 7e3ceae4..3dd12a94 100644 --- a/VideoNodes/FfmpegBuilderNodes/Audio/FfmpegBuilderAudioTrackRemover.cs +++ b/VideoNodes/FfmpegBuilderNodes/Audio/FfmpegBuilderAudioTrackRemover.cs @@ -1,39 +1,76 @@ -namespace FileFlows.VideoNodes.FfmpegBuilderNodes; +using FileFlows.VideoNodes.FfmpegBuilderNodes.Models; + +namespace FileFlows.VideoNodes.FfmpegBuilderNodes; public class FfmpegBuilderAudioTrackRemover: FfmpegBuilderNode { - public override string HelpUrl => "https://docs.fileflows.com/plugins/video-nodes/ffmpeg-builder/audio-track-remover"; + public override string HelpUrl => "https://docs.fileflows.com/plugins/video-nodes/ffmpeg-builder/track-remover"; - public override string Icon => "fas fa-volume-off"; + public override string Icon => "fas fa-eraser"; - public override int Outputs => 2; + public override int Outputs => 2; - [Boolean(1)] + + [Select(nameof(StreamTypeOptions), 1)] + public string StreamType { get; set; } + + [Boolean(2)] + [ConditionEquals(nameof(StreamType), "Video", inverse: true)] public bool RemoveAll { get; set; } - [NumberInt(2)] + + [NumberInt(3)] public int RemoveIndex { get; set; } - [TextVariable(3)] + [TextVariable(4)] [ConditionEquals(nameof(RemoveAll), false)] public string Pattern { get; set; } - [Boolean(4)] + [Boolean(5)] [ConditionEquals(nameof(RemoveAll), false)] public bool NotMatching { get; set; } - [Boolean(5)] + [Boolean(6)] [ConditionEquals(nameof(RemoveAll), false)] public bool UseLanguageCode { get; set; } + private static List _StreamTypeOptions; + public static List StreamTypeOptions + { + get + { + if (_StreamTypeOptions == null) + { + _StreamTypeOptions = new List + { + new ListOption { Label = "Audio", Value = "Audio" }, + new ListOption { Label = "Video", Value = "Video" }, + new ListOption { Label = "Subtitle", Value = "Subtitle" } + }; + } + return _StreamTypeOptions; + } + } public override int Execute(NodeParameters args) + { + if(string.IsNullOrEmpty(StreamType) || StreamType.ToLower() == "audio") + return RemoveTracks(Model.AudioStreams) ? 1 : 2; + if (StreamType.ToLower() == "subtitle") + return RemoveTracks(Model.SubtitleStreams) ? 1 : 2; + if (StreamType.ToLower() == "video") + return RemoveTracks(Model.VideoStreams) ? 1 : 2; + + return 2; + } + + private bool RemoveTracks(List tracks) where T: FfmpegStream { bool removing = false; Regex? regex = null; int index = -1; - foreach(var audio in Model.AudioStreams) + foreach (var track in tracks) { - if (audio.Deleted == false) + if (track.Deleted == false) { // only record indexes of tracks that have not been deleted ++index; @@ -41,15 +78,22 @@ public class FfmpegBuilderAudioTrackRemover: FfmpegBuilderNode continue; } - if (RemoveAll) + if (RemoveAll || string.IsNullOrEmpty(this.Pattern)) { - audio.Deleted = true; + track.Deleted = true; removing = true; continue; } - if(regex == null) + + if (regex == null) regex = new Regex(this.Pattern, RegexOptions.IgnoreCase); - string str = UseLanguageCode ? audio.Stream.Language : audio.Stream.Title; + string str = ""; + if(track is FfmpegAudioStream audio) + str = UseLanguageCode ? audio.Stream.Language : audio.Stream.Title; + else if (track is FfmpegSubtitleStream subtitle) + str = UseLanguageCode ? subtitle.Stream.Language : subtitle.Stream.Title; + else if (track is FfmpegVideoStream video) + str = video.Stream.Title; if (string.IsNullOrEmpty(str) == false) // if empty we always use this since we have no info to go on { bool matches = regex.IsMatch(str); @@ -57,11 +101,11 @@ public class FfmpegBuilderAudioTrackRemover: FfmpegBuilderNode matches = !matches; if (matches) { - audio.Deleted = true; + track.Deleted = true; removing = true; } } } - return removing ? 1 : 2; + return removing; } } diff --git a/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs b/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs index 87197c8d..5db551db 100644 --- a/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs +++ b/VideoNodes/Tests/FfmpegBuilderTests/FfmpegBuilder_BasicTests.cs @@ -1089,6 +1089,49 @@ public class FfmpegBuilder_BasicTests string log = logger.ToString(); Assert.IsTrue(log.Contains("this is a \"testing bobby drake\" blah")); } + + + [TestMethod] + public void FfmpegBuilder_ImageStream() + { + const string file = @"D:\videos\testfiles\img_stream.mp4"; + var logger = new TestLogger(); + const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe"; + var vi = new VideoInfoHelper(ffmpeg, logger); + var vii = vi.Read(file); + var args = new NodeParameters(file, logger, false, string.Empty); + args.GetToolPathActual = (string tool) => ffmpeg; + args.TempPath = @"D:\videos\temp"; + args.Parameters.Add("VideoInfo", vii); + + FfmpegBuilderStart ffStart = new(); + ffStart.PreExecute(args); + Assert.AreEqual(1, ffStart.Execute(args)); + + FfmpegBuilderRemuxToMkv ffMkv = new(); + ffMkv.PreExecute(args); + Assert.AreEqual(1, ffMkv.Execute(args)); + + FfmpegBuilderAudioTrackRemover ffRemover = new(); + ffRemover.StreamType = "Video"; + ffRemover.RemoveIndex = 1; + ffRemover.PreExecute(args); + Assert.AreEqual(1, ffRemover.Execute(args)); + + + FfmpegBuilderAudioTrackRemover ffRemoverSubtitles = new(); + ffRemoverSubtitles.StreamType = "Subtitle"; + ffRemoverSubtitles.RemoveAll = true; + ffRemoverSubtitles.PreExecute(args); + Assert.AreEqual(1, ffRemoverSubtitles.Execute(args)); + + FfmpegBuilderExecutor ffExecutor = new(); + ffExecutor.PreExecute(args); + int result = ffExecutor.Execute(args); + + string log = logger.ToString(); + Assert.AreEqual(1, result); + } } #endif \ No newline at end of file diff --git a/VideoNodes/VideoNodes.csproj b/VideoNodes/VideoNodes.csproj index 94d1ee31..1a3a3657 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 da936194..47663435 100644 --- a/VideoNodes/VideoNodes.en.json +++ b/VideoNodes/VideoNodes.en.json @@ -254,23 +254,25 @@ } }, "FfmpegBuilderAudioTrackRemover": { - "Label": "FFMPEG Builder: Audio Track Remover", + "Label": "FFMPEG Builder: Track Remover", "Outputs": { - "1": "Audio tracks set to remove", - "2": "Audio tracks NOT set to removed" + "1": "Tracks set to remove", + "2": "Tracks NOT set to removed" }, - "Description": "Allows you to remove audio tracks based on either their title or their language codes.\n\nAny title (or language code if set to \"Use Language Code\") that is blank will NOT be removed regardless of the pattern.", + "Description": "Allows you to remove tracks based on either their title or their language codes.\n\nAny title (or language code if set to \"Use Language Code\") that is blank will NOT be removed regardless of the pattern.", "Fields": { + "StreamType": "Type", + "StreamType-Help": "The type of tracks to reorder in the FFMPEG Builder", "RemoveAll": "Remove All", - "RemoveAll-Help": "Remove all current tracks from the output file. You can use Add Audio Track afterwards to add tracks of specific codecs", + "RemoveAll-Help": "Remove all current tracks from the output file. You can use Add Track afterwards to add tracks of specific codecs", "Pattern": "Pattern", "Pattern-Help": "A regular expression to match against, eg \"commentary\" to remove commentary tracks", "NotMatching": "Not Matching", "NotMatching-Help": "If audio tracks NOT matching the pattern should be removed", "UseLanguageCode": "Use Language Code", - "UseLanguageCode-Help": "If the language code of the audio track should be used instead of the title", + "UseLanguageCode-Help": "If the language code of the track should be used instead of the title", "RemoveIndex": "Remove Index", - "RemoveIndex-Help": "The start index where to remove the audio tracks from. This allows you to remove all, or all matching, audio streams after the starting index.\nSet to zero to remove all matching the parameters.\nSet to 1 to keep the first audio track and remove any after the first matching the parameters" + "RemoveIndex-Help": "The start index where to remove the tracks from. This allows you to remove all, or all matching, tracks after the starting index.\nSet to zero to remove all matching the parameters.\nSet to 1 to keep the first track and remove any after the first matching the parameters" } }, "FfmpegBuilderAudioTrackReorder": {