From 9a980b5766d83ceab73c83a23b37b568b78d7924 Mon Sep 17 00:00:00 2001 From: Javanaut Date: Sat, 11 Apr 2026 20:50:09 +0200 Subject: [PATCH] Fix streamtags remove list --- src/ffx/media_descriptor_change_set.py | 17 ++++++ .../subtrack_mapping/test_cli_bundle.py | 58 +++++++++++++++++++ .../unit/test_media_descriptor_change_set.py | 43 +++++++++++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/ffx/media_descriptor_change_set.py b/src/ffx/media_descriptor_change_set.py index 458259d..a5448bc 100644 --- a/src/ffx/media_descriptor_change_set.py +++ b/src/ffx/media_descriptor_change_set.py @@ -298,8 +298,25 @@ class MediaDescriptorChangeSet(): for tagKey, tagValue in self.__context.get('encoding_metadata_tags', {}).items(): metadataTokens += [f"-metadata:g", f"{tagKey}={tagValue}"] + metadataTokens += self.generateConfiguredRemovalMetadataTokens() + return metadataTokens def getChangeSetObj(self): return self.__changeSetObj + + def generateConfiguredRemovalMetadataTokens(self): + metadataTokens = [] + + for removeKey in self.__removeGlobalKeys: + metadataTokens += ["-metadata:g", f"{removeKey}="] + + for trackDescriptor in self.__targetTrackDescriptors: + for removeKey in self.__removeTrackKeys: + metadataTokens += [ + f"-metadata:s:{trackDescriptor.getType().indicator()}:{trackDescriptor.getSubIndex()}", + f"{removeKey}=", + ] + + return metadataTokens diff --git a/tests/integration/subtrack_mapping/test_cli_bundle.py b/tests/integration/subtrack_mapping/test_cli_bundle.py index 3b26eea..874062f 100644 --- a/tests/integration/subtrack_mapping/test_cli_bundle.py +++ b/tests/integration/subtrack_mapping/test_cli_bundle.py @@ -184,6 +184,64 @@ class SubtrackMappingBundleTests(unittest.TestCase): ["video-0", "audio-2", "audio-1", "subtitle-3"], ) + def test_no_pattern_stream_remove_list_clears_copied_stream_metadata(self): + source_filename = "remove_tags_s01e01.mkv" + self.write_config( + { + "metadata": { + "streams": { + "remove": ["BPS"], + } + } + } + ) + source_path = create_source_fixture( + self.workdir, + source_filename, + [ + SourceTrackSpec( + TrackType.VIDEO, + identity="video-0", + extra_tags={"BPS": "remove-me", "KEEP_ME": "video-keep"}, + ), + SourceTrackSpec( + TrackType.AUDIO, + identity="audio-1", + language="eng", + title="Main Audio", + extra_tags={"BPS": "remove-me", "KEEP_ME": "audio-keep"}, + ), + ], + ) + + completed = run_ffx_convert( + self.workdir, + self.home_dir, + self.database_path, + "--video-encoder", + "copy", + "--no-pattern", + "--no-tmdb", + "--no-prompt", + "--no-signature", + str(source_path), + ) + self.assertCompleted(completed) + + output_path = expected_output_path(self.workdir, source_filename) + streams = ffprobe_json(output_path)["streams"] + + self.assertEqual( + [stream["codec_type"] for stream in streams], + ["video", "audio"], + ) + self.assertEqual(get_tag(streams[0], "THIS_IS"), "video-0") + self.assertEqual(get_tag(streams[0], "KEEP_ME"), "video-keep") + self.assertIsNone(get_tag(streams[0], "BPS")) + self.assertEqual(get_tag(streams[1], "THIS_IS"), "audio-1") + self.assertEqual(get_tag(streams[1], "KEEP_ME"), "audio-keep") + self.assertIsNone(get_tag(streams[1], "BPS")) + def test_pattern_validation_fails_for_nonexistent_source_track_reference(self): source_filename = "invalid_s01e01.mkv" source_path = create_source_fixture( diff --git a/tests/unit/test_media_descriptor_change_set.py b/tests/unit/test_media_descriptor_change_set.py index 5bc84c2..bf9be09 100644 --- a/tests/unit/test_media_descriptor_change_set.py +++ b/tests/unit/test_media_descriptor_change_set.py @@ -77,7 +77,48 @@ class MediaDescriptorChangeSetTests(unittest.TestCase): self.assertIn("THIS_IS=embedded-subtitle", metadata_tokens) self.assertIn("EXTERNAL_KEEP=keep-me", metadata_tokens) self.assertNotIn("BPS=remove-me", metadata_tokens) - self.assertNotIn("BPS=", metadata_tokens) + self.assertIn("BPS=", metadata_tokens) + + def test_target_only_tracks_still_emit_remove_tokens_for_configured_stream_keys(self): + context = { + "logger": get_ffx_logger(), + "config": StaticConfig( + { + "metadata": { + "remove": ["creation_time"], + "streams": { + "remove": ["BPS"], + } + } + } + ), + } + + target_track = TrackDescriptor( + index=0, + source_index=0, + sub_index=0, + track_type=TrackType.AUDIO, + tags={ + "language": "eng", + "title": "Main Audio", + "BPS": "remove-me", + "KEEP_ME": "keep-me", + }, + ) + + change_set = MediaDescriptorChangeSet( + context, + MediaDescriptor(tags={"creation_time": "remove-me"}, track_descriptors=[target_track]), + ) + + metadata_tokens = change_set.generateMetadataTokens() + + self.assertIn("-metadata:g", metadata_tokens) + self.assertIn("creation_time=", metadata_tokens) + self.assertIn("-metadata:s:a:0", metadata_tokens) + self.assertIn("BPS=", metadata_tokens) + self.assertIn("KEEP_ME=keep-me", metadata_tokens) if __name__ == "__main__":