This commit is contained in:
Javanaut
2026-04-12 10:06:19 +02:00
parent 20bdfc0dd7
commit 9dc08d48e9
2 changed files with 120 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
import click import click
from ffx.iso_language import IsoLanguage
from ffx.media_descriptor import MediaDescriptor from ffx.media_descriptor import MediaDescriptor
from ffx.track_descriptor import TrackDescriptor from ffx.track_descriptor import TrackDescriptor
@@ -117,7 +118,11 @@ class MediaDescriptorChangeSet():
sourceTrackDescriptor: TrackDescriptor = None): sourceTrackDescriptor: TrackDescriptor = None):
sourceTrackTags = sourceTrackDescriptor.getTags() if sourceTrackDescriptor is not None else {} sourceTrackTags = sourceTrackDescriptor.getTags() if sourceTrackDescriptor is not None else {}
targetTrackTags = targetTrackDescriptor.getTags() if targetTrackDescriptor is not None else {} targetTrackTags = (
self.normalizeTrackTags(targetTrackDescriptor.getTags())
if targetTrackDescriptor is not None
else {}
)
trackCompareResult = {} trackCompareResult = {}
@@ -142,6 +147,25 @@ class MediaDescriptorChangeSet():
return trackCompareResult return trackCompareResult
def normalizeTrackTagValue(self, tagKey, tagValue):
if tagKey != "language":
return tagValue
if isinstance(tagValue, IsoLanguage):
return tagValue.threeLetter()
trackLanguage = IsoLanguage.findThreeLetter(str(tagValue))
if trackLanguage != IsoLanguage.UNDEFINED:
return trackLanguage.threeLetter()
return tagValue
def normalizeTrackTags(self, trackTags: dict):
return {
tagKey: self.normalizeTrackTagValue(tagKey, tagValue)
for tagKey, tagValue in trackTags.items()
}
def generateDispositionTokens(self): def generateDispositionTokens(self):
""" """
@@ -243,7 +267,7 @@ class MediaDescriptorChangeSet():
addedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY] addedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY]
trackDescriptor: TrackDescriptor trackDescriptor: TrackDescriptor
for trackDescriptor in addedTracks.values(): for trackDescriptor in addedTracks.values():
for tagKey, tagValue in trackDescriptor.getTags().items(): for tagKey, tagValue in self.normalizeTrackTags(trackDescriptor.getTags()).items():
if not tagKey in self.__removeTrackKeys: if not tagKey in self.__removeTrackKeys:
metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}"
+ f":{trackDescriptor.getSubIndex()}", + f":{trackDescriptor.getSubIndex()}",
@@ -267,7 +291,7 @@ class MediaDescriptorChangeSet():
trackDescriptor = self.__targetTrackDescriptorsByIndex[trackIndex] trackDescriptor = self.__targetTrackDescriptorsByIndex[trackIndex]
for tagKey, tagValue in outputTrackTags.items(): for tagKey, tagValue in self.normalizeTrackTags(outputTrackTags).items():
metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}"
+ f":{trackDescriptor.getSubIndex()}", + f":{trackDescriptor.getSubIndex()}",
f"{tagKey}={tagValue}"] f"{tagKey}={tagValue}"]
@@ -285,7 +309,7 @@ class MediaDescriptorChangeSet():
} }
| unchangedTrackTags | unchangedTrackTags
) )
for tagKey, tagValue in preservedTrackTags.items(): for tagKey, tagValue in self.normalizeTrackTags(preservedTrackTags).items():
metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}"
+ f":{trackDescriptor.getSubIndex()}", + f":{trackDescriptor.getSubIndex()}",
f"{tagKey}={tagValue}"] f"{tagKey}={tagValue}"]

View File

@@ -27,6 +27,64 @@ class StaticConfig:
class MediaDescriptorChangeSetTests(unittest.TestCase): class MediaDescriptorChangeSetTests(unittest.TestCase):
def test_non_primary_source_language_code_is_normalized_in_changed_track_metadata(self):
context = {
"logger": get_ffx_logger(),
"config": StaticConfig({}),
}
source_track = TrackDescriptor(
index=0,
source_index=0,
sub_index=0,
track_type=TrackType.AUDIO,
tags={"language": "ger", "title": "German Main"},
)
target_track = TrackDescriptor(
index=0,
source_index=0,
sub_index=0,
track_type=TrackType.AUDIO,
tags={"language": "ger", "title": "German Main"},
)
change_set = MediaDescriptorChangeSet(
context,
MediaDescriptor(track_descriptors=[target_track]),
MediaDescriptor(track_descriptors=[source_track]),
)
metadata_tokens = change_set.generateMetadataTokens()
self.assertIn("-metadata:s:a:0", metadata_tokens)
self.assertIn("language=deu", metadata_tokens)
self.assertNotIn("language=ger", metadata_tokens)
def test_target_only_track_language_metadata_uses_primary_code(self):
context = {
"logger": get_ffx_logger(),
"config": StaticConfig({}),
}
target_track = TrackDescriptor(
index=0,
source_index=0,
sub_index=0,
track_type=TrackType.AUDIO,
tags={"language": "ger", "title": "German Main"},
)
change_set = MediaDescriptorChangeSet(
context,
MediaDescriptor(track_descriptors=[target_track]),
)
metadata_tokens = change_set.generateMetadataTokens()
self.assertIn("-metadata:s:a:0", metadata_tokens)
self.assertIn("language=deu", metadata_tokens)
self.assertNotIn("language=ger", metadata_tokens)
def test_external_subtitle_preserves_source_only_tags_except_removed_keys(self): def test_external_subtitle_preserves_source_only_tags_except_removed_keys(self):
context = { context = {
"logger": get_ffx_logger(), "logger": get_ffx_logger(),
@@ -79,6 +137,40 @@ class MediaDescriptorChangeSetTests(unittest.TestCase):
self.assertNotIn("BPS=remove-me", metadata_tokens) self.assertNotIn("BPS=remove-me", metadata_tokens)
self.assertIn("BPS=", metadata_tokens) self.assertIn("BPS=", metadata_tokens)
def test_external_subtitle_normalizes_preserved_source_language_metadata(self):
context = {
"logger": get_ffx_logger(),
"config": StaticConfig({}),
}
source_track = TrackDescriptor(
index=0,
source_index=0,
sub_index=0,
track_type=TrackType.SUBTITLE,
tags={"language": "ger", "title": "German Subtitle"},
)
target_track = TrackDescriptor(
index=0,
source_index=0,
sub_index=0,
track_type=TrackType.SUBTITLE,
tags={},
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.assertNotIn("language=ger", metadata_tokens)
def test_target_only_tracks_still_emit_remove_tokens_for_configured_stream_keys(self): def test_target_only_tracks_still_emit_remove_tokens_for_configured_stream_keys(self):
context = { context = {
"logger": get_ffx_logger(), "logger": get_ffx_logger(),