From e2f1651053f20c4703342993a13d3b3bf86b1029 Mon Sep 17 00:00:00 2001 From: John Andrews Date: Thu, 16 Jun 2022 13:49:19 +1200 Subject: [PATCH] added metadata remover node --- Apprise/Apprise.csproj | Bin 2760 -> 2760 bytes Apprise/Plugin.cs | Bin 592 -> 592 bytes BasicNodes/BasicNodes.csproj | Bin 3566 -> 3566 bytes BasicNodes/Plugin.cs | Bin 740 -> 740 bytes ChecksumNodes/ChecksumNodes.csproj | Bin 2872 -> 2872 bytes ChecksumNodes/Plugin.cs | Bin 552 -> 552 bytes CollectionNodes/CollectionNodes.csproj | Bin 3256 -> 3256 bytes CollectionNodes/Plugin.cs | Bin 892 -> 892 bytes DiscordNodes/DiscordNodes.csproj | Bin 2870 -> 2870 bytes DiscordNodes/Plugin.cs | Bin 590 -> 590 bytes EmailNodes/EmailNodes.csproj | Bin 3386 -> 3386 bytes EmailNodes/Plugin.cs | Bin 548 -> 548 bytes Emby/Emby.csproj | Bin 2844 -> 2844 bytes Emby/Plugin.cs | Bin 568 -> 568 bytes Gotify/Gotify.csproj | Bin 2752 -> 2752 bytes Gotify/Plugin.cs | Bin 588 -> 588 bytes ImageNodes/ImageNodes.csproj | Bin 3232 -> 3232 bytes ImageNodes/Plugin.cs | Bin 594 -> 594 bytes MetaNodes/MetaNodes.csproj | Bin 4504 -> 4504 bytes MetaNodes/Plugin.cs | Bin 646 -> 646 bytes MusicNodes/MusicNodes.csproj | Bin 4228 -> 4228 bytes MusicNodes/Plugin.cs | Bin 762 -> 762 bytes Plex/Plex.csproj | Bin 2844 -> 2844 bytes Plex/Plugin.cs | Bin 568 -> 568 bytes VideoLegacyNodes/Plugin.cs | Bin 762 -> 762 bytes VideoLegacyNodes/VideoLegacyNodes.csproj | Bin 2994 -> 2994 bytes .../Audio/FfmpegBuilderAudioAddTrack.cs | 5 + .../FfmpegBuilderMetadataRemover.cs | 128 ++++++++++++++++++ VideoNodes/Plugin.cs | Bin 762 -> 762 bytes .../FfmpegBuilder_MetadataTests.cs | 114 +++++++++++----- VideoNodes/VideoInfo.cs | 8 ++ VideoNodes/VideoInfoHelper.cs | 2 + VideoNodes/VideoNodes.csproj | Bin 4098 -> 4098 bytes VideoNodes/VideoNodes.en.json | 23 ++++ 34 files changed, 245 insertions(+), 35 deletions(-) create mode 100644 VideoNodes/FfmpegBuilderNodes/FfmpegBuilderMetadataRemover.cs diff --git a/Apprise/Apprise.csproj b/Apprise/Apprise.csproj index 18948d0e5a64f1ee81481d4b55e5246a7201d624..b14608f39fe49bfbdfe6b6510c6a703a56bb5e16 100644 GIT binary patch delta 20 bcmX>hdO~!A4HKi`WLu_SM#Ie$nanu=M0y3c delta 20 bcmX>hdO~!A4HKimWLu_SMuW{0nanu=L}&%I diff --git a/Apprise/Plugin.cs b/Apprise/Plugin.cs index ef22b601dd2350e74c4f8472cdbc29a0971af569..435080c98f89d7015b52ba6d47abc749c35b39af 100644 GIT binary patch delta 23 ecmcb>a)D*TGe&Mh20aEt1``GY29wDj8RG#{bOu)d delta 23 ecmcb>a)D*TGe&L$20aEt24eO-2K@j4 delta 35 qcmaFD`h;~u1(UD=gC2t+gE50Sg9U>UgEa#$1J`6lM&-%tn9KlgAtqi!20aEN26F}r1{((b$qShzC*R}ZnykjcH;Gw-(QvaQvpfd?^9%|7 delta 43 zcmdlXwnJ>gAtqh}20aEN26F}r1{((b$qShzC*R}ZnykjcH;Gw-(O|PAvpfd?^5Y5n diff --git a/ChecksumNodes/Plugin.cs b/ChecksumNodes/Plugin.cs index 570092ae27e10a2ea7b57f34ae458d86164f588f..83720ac3d9838689b92a5bd08b110179903840aa 100644 GIT binary patch delta 23 ecmZ3%vVvv9K1Oas20aEt1``GY29wDr8RG#-Oa-?9 delta 23 ecmZ3%vVvv9K1OZ>20aEt24e}bCT2zeS9b-I diff --git a/DiscordNodes/DiscordNodes.csproj b/DiscordNodes/DiscordNodes.csproj index 4e496ed4ff28e8b203079b82ad908aa0b259cf81..90015ef331891d8b74d18a206bdd51583103d004 100644 GIT binary patch delta 20 bcmdlcwoPn97Zao58RG#{9|l+e diff --git a/EmailNodes/EmailNodes.csproj b/EmailNodes/EmailNodes.csproj index 8edbaa34a7d3eab0e048f52e7ba9880a5df88684..728f883b0b996a371d65cdf2eaf2b3e2d232e5b5 100644 GIT binary patch delta 20 ccmdlbwM%M)4GW{;WLuVCM#Ie$SyplY07Nnd9RL6T delta 20 ccmdlbwM%M)4GW{eWLuVCMuW{0SyplY07M`L8vp*BE=F!c20aEt1``GY29wE08RG#+NCl?= delta 23 ecmZ3&vV>*BE=Fzx20aEt24eTm|<4 delta 23 ecmdnNvV&#AIYw>+20aEt24ei3R`w diff --git a/Gotify/Gotify.csproj b/Gotify/Gotify.csproj index 2b86cbe88f68f6ce5557cb37f7f0ad270842a89e..876986f3d6a5af2fe469460b1e430dbe6f69c59c 100644 GIT binary patch delta 20 bcmX>gdO&o84HKi`WLu_SM#Ie$ne;gTLplYY delta 20 bcmX>gdO&o84HKimWLu_SMuW{0ne;gTLnsBE diff --git a/Gotify/Plugin.cs b/Gotify/Plugin.cs index 6e547a5ff4b1f5a66dc9b99dd674411ba7a0ce22..8a7a6b9a00aad78be4822446d03954aeb888df58 100644 GIT binary patch delta 23 ecmX@Za)xEYBSvmR20aEt1``GY29wEe8RG#`a0W*J delta 23 ecmX@Za)xEYBSvlm20aEt24eHp_5c6? delta 20 ccmZ1=xj=Hm1SUp<$rG6(84WhSX4=XL07=mX^Z)<= diff --git a/ImageNodes/Plugin.cs b/ImageNodes/Plugin.cs index f0dc2da3c5e06f390c01d271246f839df4ff4b0b..23a746f84de398035b0d3341cfce1a62ccf86412 100644 GIT binary patch delta 35 pcmcb_a*1Wb3r1l>20aEt1``GYAXZ|qX5eMunmmzFda@Xk4FHzR2OIzZ delta 35 rcmcb_a*1Wb3r1lB20aEt24eo84Wko84Wh;GiUMv08K3hegFUf diff --git a/MetaNodes/Plugin.cs b/MetaNodes/Plugin.cs index 855b8c842a92abe764b68514353d068e37681358..a44203156d64e2cf38e307285b48e64b1c0cdb03 100644 GIT binary patch delta 23 ecmZo;ZDZYFz{G9HpvPdyV8UR)U^3a7$r}JS_XI}( delta 23 ecmZo;ZDZYFz{G99pvPdyV9a37U@_U6$r}JTBm__Z diff --git a/MusicNodes/MusicNodes.csproj b/MusicNodes/MusicNodes.csproj index 7207905d18a10346601b6cd3ccfd340f9027eda1..5759a2975c36573fc8be7ef42bff90ff07a9df39 100644 GIT binary patch delta 20 bcmZosY*E~Bi;2;2@@=L_M#Igf%>KLpN_YlK delta 20 bcmZosY*E~Bi;2--@@=L_MuW|!%>KLpN@fO0 diff --git a/MusicNodes/Plugin.cs b/MusicNodes/Plugin.cs index 9b52da9b257b5d7f3562e1d8eab4b8266fe86bd7..fc99141cf59cb4b66f3285c9cd0dba26a04e0652 100644 GIT binary patch delta 23 ecmeyx`iphL1SW1n20aEt1``GY29wFNnc@Lc+Xe#w delta 23 ecmeyx`iphL1SW0+20aEt24eTm|<4 delta 23 ecmdnNvV&#AIYw>+20aEt24ei3R`w diff --git a/VideoLegacyNodes/Plugin.cs b/VideoLegacyNodes/Plugin.cs index 12e08d36ff2b976c10cd02009eb9aa7bada24c39..bbd5dc0799f9ba3fa97241d23a146af50c0e5ef1 100644 GIT binary patch delta 23 ecmeyx`iphL1SW1n20aEt1``GY29wFNnc@Lc+Xe#w delta 23 ecmeyx`iphL1SW0+20aEt24e x.Stream)); diff --git a/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderMetadataRemover.cs b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderMetadataRemover.cs new file mode 100644 index 00000000..df9b69ba --- /dev/null +++ b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderMetadataRemover.cs @@ -0,0 +1,128 @@ +using FileFlows.VideoNodes.FfmpegBuilderNodes.Models; + +namespace FileFlows.VideoNodes.FfmpegBuilderNodes; + +/// +/// Node that removes metadata from a file +/// +public class FfmpegBuilderMetadataRemover : FfmpegBuilderNode +{ + /// + /// Gets the Help URL for this node + /// + public override string HelpUrl => "https://docs.fileflows.com/plugins/video-nodes/ffmpeg-builder/metadata-remover"; + + /// + /// Gets the icon for this node + /// + public override string Icon => "fas fa-remove-format"; + + /// + /// Gets the number of outputs for this node + /// + public override int Outputs => 1; + + /// + /// Gets or sets if should run against video tracks + /// + [Boolean(1)] + public bool Video { get; set; } + + /// + /// Gets or sets if should run against audio tracks + /// + [Boolean(2)] + public bool Audio { get; set; } + + /// + /// Gets or sets if should run against subtitle tracks + /// + [Boolean(3)] + public bool Subtitle { get; set; } + + /// + /// Gets or sets if images should be removed + /// + [Boolean(4)] + public bool RemoveImages { get; set; } + + /// + /// Gets or sets if title should be removed + /// + [Boolean(5)] + public bool RemoveTitle { get; set; } + + /// + /// Gets or sets if language should be removed + /// + [Boolean(6)] + public bool RemoveLanguage { get; set; } + + /// + /// Gets or sets if additional metadata should be removed + /// + [Boolean(6)] + public bool RemoveAdditionalMetadata { get; set; } + + /// + /// Executes the node + /// + /// the node parameters + /// the output number to execute next + public override int Execute(NodeParameters args) + { + if (Video) + Process(Model.VideoStreams); + + if (Audio) + Process(Model.AudioStreams); + + if (Subtitle) + Process(Model.SubtitleStreams); + + if (RemoveAdditionalMetadata) + { + Model.CustomParameters.AddRange(new[] { "-map_metadata", "-1" }); + Model.ForceEncode = true; + } + + + if (RemoveImages) + { + foreach (var video in Model.VideoStreams) + { + if (video.Stream.IsImage) + video.Deleted = true; + } + } + + return 1; + } + + private void Process(List streams) where T : FfmpegStream + { + if (streams == null) + return; + foreach (var stream in streams) + Process(stream); + } + + private void Process(FfmpegStream stream) + { + if (RemoveTitle) + { + stream.Title = string.Empty; + } + + if (stream is FfmpegAudioStream audio) + { + if (RemoveLanguage) + audio.Language = string.Empty; + } + else if (stream is FfmpegSubtitleStream sub) + { + if (RemoveLanguage) + sub.Language = string.Empty; + } + } +} diff --git a/VideoNodes/Plugin.cs b/VideoNodes/Plugin.cs index 82aa1b3bf9d71b623624a1d174f129ad49c95a55..6fdf1078f973c3b2d1e7fa32d07c26e611f5f0c1 100644 GIT binary patch delta 23 ecmeyx`iphL1SW1n20aEt1``GY29wFNnc@Lc+Xe#w delta 23 ecmeyx`iphL1SW0+20aEt24e(File.ReadAllText(@"D:\videos\metadata.json")); -// args.Variables.Add("VideoMetadata", md); -// args.GetToolPathActual = (string tool) => ffmpeg; -// args.TempPath = @"D:\videos\temp"; -// args.Parameters.Add("VideoInfo", vii); +namespace FileFlows.VideoNodes.Tests.FfmpegBuilderTests; + +[TestClass] +public class FfmpegBuilder_MetadataTests: TestBase +{ + //[TestMethod] + //public void FfmpegBuilder_MetadataJson() + //{ + // const string file = @"D:\videos\unprocessed\basic.mkv"; + // 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); + // VideoMetadata md = System.Text.Json.JsonSerializer.Deserialize(File.ReadAllText(@"D:\videos\metadata.json")); + // args.Variables.Add("VideoMetadata", md); + // args.GetToolPathActual = (string tool) => ffmpeg; + // args.TempPath = @"D:\videos\temp"; + // args.Parameters.Add("VideoInfo", vii); -// FfmpegBuilderStart ffStart = new (); -// Assert.AreEqual(1, ffStart.Execute(args)); + // FfmpegBuilderStart ffStart = new (); + // Assert.AreEqual(1, ffStart.Execute(args)); -// FfmpegBuilderVideoMetadata ffMetadata = new(); -// Assert.AreEqual(1, ffMetadata.Execute(args)); + // FfmpegBuilderVideoMetadata ffMetadata = new(); + // Assert.AreEqual(1, ffMetadata.Execute(args)); -// FfmpegBuilderExecutor ffExecutor = new(); -// int result = ffExecutor.Execute(args); + // FfmpegBuilderExecutor ffExecutor = new(); + // int result = ffExecutor.Execute(args); -// string log = logger.ToString(); -// Assert.AreEqual(1, result); -// } -// } -//} + // string log = logger.ToString(); + // Assert.AreEqual(1, result); + //} -//#endif \ No newline at end of file + + [TestMethod] + public void FfmpegBuilder_Metadata_Remover() + { + string file = TestFile_MovText_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)); + + FfmpegBuilderAudioTrackRemover ffRemover = new(); + ffRemover.StreamType = "subtitle"; + ffRemover.RemoveAll = true; + ffRemover.PreExecute(args); + Assert.AreEqual(1, ffRemover.Execute(args)); + + + FfmpegBuilderMetadataRemover ffMetadata = new(); + ffMetadata.RemoveImages = true; + ffMetadata.RemoveTitle = true; + ffMetadata.RemoveLanguage = true; + ffMetadata.Video = true; + ffMetadata.Audio= true; + ffMetadata.Subtitle = true; + ffMetadata.RemoveAdditionalMetadata = true; + ffMetadata.PreExecute(args); + Assert.AreEqual(1, ffMetadata.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/VideoInfo.cs b/VideoNodes/VideoInfo.cs index e1927f29..d3672946 100644 --- a/VideoNodes/VideoInfo.cs +++ b/VideoNodes/VideoInfo.cs @@ -39,6 +39,14 @@ namespace FileFlows.VideoNodes /// public string Codec { get; set; } = ""; + /// + /// If this stream is an image + /// + public bool IsImage { get; set; } + + /// + /// Gets or sets the index string of this track + /// public string IndexString { get; set; } /// diff --git a/VideoNodes/VideoInfoHelper.cs b/VideoNodes/VideoInfoHelper.cs index 3a186b3e..976d20d6 100644 --- a/VideoNodes/VideoInfoHelper.cs +++ b/VideoNodes/VideoInfoHelper.cs @@ -220,6 +220,8 @@ namespace FileFlows.VideoNodes // Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709/unknown/unknown, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn (default) string line = info.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).First(); VideoStream vs = new VideoStream(); + vs.IsImage = info.Contains("(attached pic)"); + vs.Codec = line.Substring(line.IndexOf("Video: ") + "Video: ".Length).Replace(",", "").Trim().Split(' ').First().ToLower(); var dimensions = Regex.Match(line, @"([\d]{3,})x([\d]{3,})"); if (int.TryParse(dimensions.Groups[1].Value, out int width)) diff --git a/VideoNodes/VideoNodes.csproj b/VideoNodes/VideoNodes.csproj index 5e9ae8a8b74962b5ae5fe4830d85433b165b197c..e55f6953061bf8a4a1d9942292950a4fda1eaf51 100644 GIT binary patch delta 20 bcmZotXj0g4i;2;2@@=L_M#Igf%x8H3O9KYN delta 20 bcmZotXj0g4i;2--@@=L_MuW|!%x8H3O7RB3 diff --git a/VideoNodes/VideoNodes.en.json b/VideoNodes/VideoNodes.en.json index 2c75af04..9c86257c 100644 --- a/VideoNodes/VideoNodes.en.json +++ b/VideoNodes/VideoNodes.en.json @@ -222,6 +222,29 @@ "2": "No HDR stream found" } }, + "FfmpegBuilderMetadataRemover": { + "Label": "FFMPEG Builder: Metadata Remover", + "Description": "Removes metadata from the FFMPEG Builder so when the file is processed the selected metadata will be removed.\n\nNote: Only the metadata when this node is effected, if metadata is added after this node runs, that will not be effected.", + "Outputs": { + "1": "Metadata removed from FFMPEG Builder" + }, + "Fields": { + "Video": "Video", + "Video-Help": "If video tracks should have this metadata removed", + "Audio": "Audio", + "Audio-Help": "If audio tracks should have this metadata removed", + "Subtitle": "Subtitle", + "Subtitle-Help": "If subtitle tracks should have this metadata removed", + "RemoveImages": "Remove Images", + "RemoveImages-Help": "If any images found in the metadata should be removed", + "RemoveTitle": "Remove Title", + "RemoveTitle-Help": "If the title should be removed from the tracks", + "RemoveLanguage": "Remove Language", + "RemoveLanguage-Help": "If the language should be removed from the tracks", + "RemoveAdditionalMetadata": "Remove Additional Metadata", + "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." + } + }, "FfmpegBuilderSubtitleFormatRemover": { "Label": "FFMPEG Builder: Subtitle Format Remover", "Description": "Removes subtitles from a video file if found.",