From ebdc23c3ce44f6b75ee0cd08cc1630e9d109767a Mon Sep 17 00:00:00 2001 From: Javanaut Date: Sat, 11 Apr 2026 17:31:10 +0200 Subject: [PATCH] Fixes remove stream tags per list --- src/ffx/media_descriptor_change_set.py | 9 +- .../subtrack_mapping/test_cli_bundle.py | 18 ++++ .../unit/test_media_descriptor_change_set.py | 84 +++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_media_descriptor_change_set.py diff --git a/src/ffx/media_descriptor_change_set.py b/src/ffx/media_descriptor_change_set.py index cf98391..fdfaaf8 100644 --- a/src/ffx/media_descriptor_change_set.py +++ b/src/ffx/media_descriptor_change_set.py @@ -277,7 +277,14 @@ class MediaDescriptorChangeSet(): # media payload, keep metadata from the regular # source track unless the external/target side # overrides it explicitly. - preservedTrackTags = removedTrackTags | unchangedTrackTags + preservedTrackTags = ( + { + tagKey: tagValue + for tagKey, tagValue in removedTrackTags.items() + if tagKey not in self.__removeTrackKeys + } + | unchangedTrackTags + ) for tagKey, tagValue in preservedTrackTags.items(): metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" + f":{trackDescriptor.getSubIndex()}", diff --git a/tests/integration/subtrack_mapping/test_cli_bundle.py b/tests/integration/subtrack_mapping/test_cli_bundle.py index 94a171f..3b26eea 100644 --- a/tests/integration/subtrack_mapping/test_cli_bundle.py +++ b/tests/integration/subtrack_mapping/test_cli_bundle.py @@ -1,5 +1,6 @@ from __future__ import annotations +import json from pathlib import Path import tempfile import unittest @@ -39,6 +40,11 @@ class SubtrackMappingBundleTests(unittest.TestCase): def tearDown(self): self.tempdir.cleanup() + def write_config(self, data: dict) -> None: + config_dir = self.home_dir / ".local" / "etc" + config_dir.mkdir(parents=True, exist_ok=True) + (config_dir / "ffx.json").write_text(json.dumps(data), encoding="utf-8") + def assertCompleted(self, completed): if completed.returncode != 0: self.fail( @@ -218,6 +224,15 @@ class SubtrackMappingBundleTests(unittest.TestCase): def test_external_subtitle_file_replaces_payload_and_overrides_metadata(self): source_filename = "substitute_s01e01.mkv" + self.write_config( + { + "metadata": { + "streams": { + "remove": ["BPS"], + } + } + } + ) source_path = create_source_fixture( self.workdir, source_filename, @@ -229,6 +244,7 @@ class SubtrackMappingBundleTests(unittest.TestCase): identity="embedded-subtitle", language="eng", title="Embedded Title", + extra_tags={"BPS": "remove-me", "EXTERNAL_KEEP": "keep-me"}, subtitle_lines=("embedded subtitle payload",), ), ], @@ -273,6 +289,8 @@ class SubtrackMappingBundleTests(unittest.TestCase): self.assertEqual(get_tag(subtitle_stream, "language"), "deu") self.assertEqual(get_tag(subtitle_stream, "title"), "Embedded Title") self.assertEqual(get_tag(subtitle_stream, "THIS_IS"), "embedded-subtitle") + self.assertEqual(get_tag(subtitle_stream, "EXTERNAL_KEEP"), "keep-me") + self.assertIsNone(get_tag(subtitle_stream, "BPS")) extracted_subtitle = extract_first_subtitle_text(self.workdir, output_path) self.assertIn("external subtitle payload", extracted_subtitle) diff --git a/tests/unit/test_media_descriptor_change_set.py b/tests/unit/test_media_descriptor_change_set.py new file mode 100644 index 0000000..5bc84c2 --- /dev/null +++ b/tests/unit/test_media_descriptor_change_set.py @@ -0,0 +1,84 @@ +from __future__ import annotations + +from pathlib import Path +import sys +import unittest + + +SRC_ROOT = Path(__file__).resolve().parents[2] / "src" + +if str(SRC_ROOT) not in sys.path: + sys.path.insert(0, str(SRC_ROOT)) + + +from ffx.media_descriptor import MediaDescriptor # noqa: E402 +from ffx.media_descriptor_change_set import MediaDescriptorChangeSet # noqa: E402 +from ffx.track_descriptor import TrackDescriptor # noqa: E402 +from ffx.track_type import TrackType # noqa: E402 +from ffx.logging_utils import get_ffx_logger # noqa: E402 + + +class StaticConfig: + def __init__(self, data: dict): + self._data = data + + def getData(self): + return self._data + + +class MediaDescriptorChangeSetTests(unittest.TestCase): + def test_external_subtitle_preserves_source_only_tags_except_removed_keys(self): + context = { + "logger": get_ffx_logger(), + "config": StaticConfig( + { + "metadata": { + "streams": { + "remove": ["BPS"], + } + } + } + ), + } + + source_track = TrackDescriptor( + index=0, + source_index=0, + sub_index=0, + track_type=TrackType.SUBTITLE, + tags={ + "language": "eng", + "title": "Embedded Title", + "THIS_IS": "embedded-subtitle", + "EXTERNAL_KEEP": "keep-me", + "BPS": "remove-me", + }, + ) + target_track = TrackDescriptor( + index=0, + source_index=0, + sub_index=0, + track_type=TrackType.SUBTITLE, + tags={"language": "deu"}, + external_source_file="/tmp/external-subtitle.vtt", + ) + + change_set = MediaDescriptorChangeSet( + context, + MediaDescriptor(track_descriptors=[target_track]), + MediaDescriptor(track_descriptors=[source_track]), + ) + + metadata_tokens = change_set.generateMetadataTokens() + + self.assertIn("-metadata:s:s:0", metadata_tokens) + self.assertIn("language=deu", metadata_tokens) + self.assertIn("title=Embedded Title", metadata_tokens) + 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) + + +if __name__ == "__main__": + unittest.main()