From fe1ed5775858003eca647b96fb02440ad8b13087 Mon Sep 17 00:00:00 2001 From: Javanaut Date: Thu, 17 Oct 2024 00:20:22 +0200 Subject: [PATCH] nightl --- bin/ffx.py | 2 +- bin/ffx/audio_layout.py | 8 ++- bin/ffx/ffx_controller.py | 89 ++++++++++++++++--------------- bin/ffx/media_descriptor.py | 18 ++++--- bin/ffx/media_details_screen.py | 2 + bin/ffx/model/track.py | 19 +++++-- bin/ffx/pattern_details_screen.py | 2 +- bin/ffx/show_details_screen.py | 12 +++-- bin/ffx/track_descriptor.py | 1 + bin/ffx/track_details_screen.py | 2 + 10 files changed, 93 insertions(+), 62 deletions(-) diff --git a/bin/ffx.py b/bin/ffx.py index 27aaf64..6ed92b6 100755 --- a/bin/ffx.py +++ b/bin/ffx.py @@ -339,7 +339,7 @@ def convert(ctx, click.echo(f"Input mapping tokens: {targetMediaDescriptor.getInputMappingTokens()}") - fc = FfxController(currentMediaDescriptor, targetMediaDescriptor) + fc = FfxController(context, currentMediaDescriptor, targetMediaDescriptor) mappingTokens = fc.generateMetadataTokens() click.echo(f"Metadata Tokens: {mappingTokens}") diff --git a/bin/ffx/audio_layout.py b/bin/ffx/audio_layout.py index 30f9865..1552365 100644 --- a/bin/ffx/audio_layout.py +++ b/bin/ffx/audio_layout.py @@ -13,7 +13,7 @@ class AudioLayout(Enum): LAYOUT_UNDEFINED = {"layout": "undefined", "index": 0} - def layout(self): + def label(self): """Returns the layout as string""" return self.value['layout'] @@ -21,6 +21,12 @@ class AudioLayout(Enum): """Returns the layout as string""" return self.value['layout'] + @staticmethod + def fromIndex(index : int): + try: + return [a for a in AudioLayout if a.index() == int(index)][0] + except: + return AudioLayout.LAYOUT_UNDEFINED def identify(self, streamObj): diff --git a/bin/ffx/ffx_controller.py b/bin/ffx/ffx_controller.py index ca7d7ef..362c3c3 100644 --- a/bin/ffx/ffx_controller.py +++ b/bin/ffx/ffx_controller.py @@ -4,6 +4,7 @@ from ffx.media_descriptor import MediaDescriptor from ffx.helper import DIFF_ADDED_KEY, DIFF_REMOVED_KEY, DIFF_CHANGED_KEY from ffx.track_descriptor import TrackDescriptor from ffx.model.track import Track +from ffx.audio_layout import AudioLayout class FfxController(): @@ -37,8 +38,12 @@ class FfxController(): INPUT_FILE_EXTENSIONS = ['mkv', 'mp4', 'avi', 'flv', 'webm'] - def __init__(self, sourceMediaDescriptor : MediaDescriptor, targetMediaDescriptor : MediaDescriptor): + def __init__(self, + context : dict, + sourceMediaDescriptor : MediaDescriptor, + targetMediaDescriptor : MediaDescriptor): + self.__context = context self.__sourceMediaDescriptor = sourceMediaDescriptor self.__targetMediaDescriptor = targetMediaDescriptor @@ -99,49 +104,49 @@ class FfxController(): return ['-f', format, f"{filepath}.{ext}"] - def generateAudioEncodingTokens(self, context, index, layout): + def generateAudioEncodingTokens(self, subIndex : int, layout : AudioLayout): """Generates ffmpeg options for one output audio stream including channel remapping, codec and bitrate""" pass - # - # if layout == STREAM_LAYOUT_6_1: - # return [f"-c:a:{index}", - # 'libopus', - # f"-filter:a:{index}", - # 'channelmap=channel_layout=6.1', - # f"-b:a:{index}", - # context['bitrates']['dts']] - # - # elif layout == STREAM_LAYOUT_5_1: - # return [f"-c:a:{index}", - # 'libopus', - # f"-filter:a:{index}", - # "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1", - # f"-b:a:{index}", - # context['bitrates']['ac3']] - # - # elif layout == STREAM_LAYOUT_STEREO: - # return [f"-c:a:{index}", - # 'libopus', - # f"-b:a:{index}", - # context['bitrates']['stereo']] - # - # elif layout == STREAM_LAYOUT_6CH: - # return [f"-c:a:{index}", - # 'libopus', - # f"-filter:a:{index}", - # "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1", - # f"-b:a:{index}", - # context['bitrates']['ac3']] - # else: - # return [] - - - def generateClearTokens(self, streams): - clearTokens = [] - for s in streams: - for k in FfxController.MKVMERGE_METADATA_KEYS: - clearTokens += [f"-metadata:s:{s['type'][0]}:{s['sub_index']}", f"{k}="] - return clearTokens + + if layout == AudioLayout.LAYOUT_6_1: + return [f"-c:a:{subIndex}", + 'libopus', + f"-filter:a:{subIndex}", + 'channelmap=channel_layout=6.1', + f"-b:a:{subIndex}", + self.__context['bitrates']['dts']] + + elif layout == AudioLayout.LAYOUT_5_1: + return [f"-c:a:{subIndex}", + 'libopus', + f"-filter:a:{subIndex}", + "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1", + f"-b:a:{subIndex}", + self.__context['bitrates']['ac3']] + + elif layout == AudioLayout.LAYOUT_STEREO: + return [f"-c:a:{subIndex}", + 'libopus', + f"-b:a:{subIndex}", + self.__context['bitrates']['stereo']] + + elif layout == AudioLayout.LAYOUT_6CH: + return [f"-c:a:{subIndex}", + 'libopus', + f"-filter:a:{subIndex}", + "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1", + f"-b:a:{subIndex}", + self.__context['bitrates']['ac3']] + else: + return [] + + + # def generateClearTokens(self, streams): + # clearTokens = [] + # for s in streams: + # for k in FfxController.MKVMERGE_METADATA_KEYS: + # clearTokens += [f"-metadata:s:{s['type'][0]}:{s['sub_index']}", f"{k}="] + # return clearTokens diff --git a/bin/ffx/media_descriptor.py b/bin/ffx/media_descriptor.py index d6638fe..36d2806 100644 --- a/bin/ffx/media_descriptor.py +++ b/bin/ffx/media_descriptor.py @@ -191,8 +191,10 @@ class MediaDescriptor(): #HINT: Some tags differ per file, for example creation_time, so these are removed before diff for emt in MediaDescriptor.EXCLUDED_MEDIA_TAGS: - del tags[emt] - del vsTags[emt] + if emt in tags.keys(): + del tags[emt] + if emt in vsTags.keys(): + del vsTags[emt] tagsDiff = dictDiff(vsTags, tags) @@ -218,12 +220,12 @@ class MediaDescriptor(): for tp in range(maxNumOfTracks): - # if self.__jellyfinOrder: - # vsTrackIndex = tracks[tp].getSourceIndex() - # else: - # vsTrackIndex = tp - - vsTrackIndex = tracks[tp].getSourceIndex() + # inspect/update funktionier nur so + if self.__jellyfinOrder: + vsTrackIndex = tracks[tp].getSourceIndex() + else: + vsTrackIndex = tp + # vsTrackIndex = tracks[tp].getSourceIndex() # Will trigger if tracks are missing in file if tp > (numVsTracks - 1): diff --git a/bin/ffx/media_details_screen.py b/bin/ffx/media_details_screen.py index 20a6ca9..81e7e1f 100644 --- a/bin/ffx/media_details_screen.py +++ b/bin/ffx/media_details_screen.py @@ -507,6 +507,8 @@ class MediaDetailsScreen(Screen): if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): for removedTrackIndex, removedTrack in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY].items(): + + # Track per inspect/update hinzufügen self.__tc.addTrack(removedTrack, patternId = self.__currentPattern.getId()) if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): diff --git a/bin/ffx/model/track.py b/bin/ffx/model/track.py index 6e70176..5872fff 100644 --- a/bin/ffx/model/track.py +++ b/bin/ffx/model/track.py @@ -11,6 +11,8 @@ from ffx.iso_language import IsoLanguage from ffx.track_disposition import TrackDisposition from ffx.track_descriptor import TrackDescriptor +from ffx.audio_layout import AudioLayout + import click class Track(Base): @@ -40,8 +42,9 @@ class Track(Base): track_tags = relationship('TrackTag', back_populates='track', cascade="all, delete", lazy="joined") - disposition_flags = Column(Integer) + + audio_layout = Column(Integer) def __init__(self, **kwargs): @@ -57,7 +60,7 @@ class Track(Base): @classmethod - def fromStreamObj(cls, streamObj, patternId): + def fromFfprobeStreamObj(cls, streamObj, patternId): """{ 'index': 4, 'codec_name': 'hdmv_pgs_subtitle', @@ -124,14 +127,15 @@ class Track(Base): """ - trackType = streamObj['codec_type'] + trackType = streamObj[TrackDescriptor.FFPROBE_CODEC_TYPE_KEY] if trackType in [t.label() for t in TrackType]: - # sub_index = int(subIndex), return cls(pattern_id = patternId, track_type = trackType, - disposition_flags = sum([2**t.index() for (k,v) in streamObj['disposition'].items() if v and (t := TrackDisposition.find(k)) is not None])) + disposition_flags = sum([2**t.index() for (k,v) in streamObj[TrackDescriptor.FFPROBE_DISPOSITION_KEY].items() + if v and (t := TrackDisposition.find(k)) is not None]), + audio_layout = AudioLayout.identify(streamObj)) else: return None @@ -163,6 +167,9 @@ class Track(Base): def getDispositionSet(self): return TrackDisposition.toSet(self.disposition_flags) + def getAudioLayout(self): + return AudioLayout.fromIndex(self.audio_layout) + def getTags(self): return {str(t.key):str(t.value) for t in self.track_tags} @@ -193,5 +200,7 @@ class Track(Base): kwargs[TrackDescriptor.TRACK_TYPE_KEY] = self.getType() kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet() kwargs[TrackDescriptor.TAGS_KEY] = self.getTags() + + kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = self.getAudioLayout() return TrackDescriptor(**kwargs) diff --git a/bin/ffx/pattern_details_screen.py b/bin/ffx/pattern_details_screen.py index 8928c62..8e143ec 100644 --- a/bin/ffx/pattern_details_screen.py +++ b/bin/ffx/pattern_details_screen.py @@ -138,7 +138,7 @@ class PatternDetailsScreen(Screen): row = (td.getIndex(), trackType.label(), typeCounter[trackType], - " ", + td.getAudioLayout().label(), td.getLanguage().label(), td.getTitle(), 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No', diff --git a/bin/ffx/show_details_screen.py b/bin/ffx/show_details_screen.py index 2cfc574..9510f62 100644 --- a/bin/ffx/show_details_screen.py +++ b/bin/ffx/show_details_screen.py @@ -82,16 +82,16 @@ class ShowDetailsScreen(Screen): self.show_obj = self.__sc.getShowDesciptor(showId) if showId is not None else {} - def loadPatterns(self, show_id): + def loadPatterns(self, show_id : int): try: s = self.Session() q = s.query(Pattern).filter(Pattern.show_id == int(show_id)) - return [{'id': int(p.id), 'pattern': p.pattern} for p in q.all()] + return [{'id': int(p.id), 'pattern': str(p.pattern)} for p in q.all()] except Exception as ex: - click.ClickException(f"loadPatterns(): {repr(ex)}") + raise click.ClickException(f"ShowDetailsScreen.loadPatterns(): {repr(ex)}") finally: s.close() @@ -109,7 +109,11 @@ class ShowDetailsScreen(Screen): self.query_one("#indicator_season_digits_input", Input).value = str(self.show_obj['indicator_season_digits']) self.query_one("#indicator_episode_digits_input", Input).value = str(self.show_obj['indicator_episode_digits']) - for pattern in self.loadPatterns(int(self.show_obj['id'])): + showId = int(self.show_obj['id']) + #raise click.ClickException(f"show_id {showId}") + patternList = self.loadPatterns(showId) + # raise click.ClickException(f"patternList {patternList}") + for pattern in patternList: row = (pattern['pattern'],) self.patternTable.add_row(*map(str, row)) diff --git a/bin/ffx/track_descriptor.py b/bin/ffx/track_descriptor.py index b77d82c..fe54878 100644 --- a/bin/ffx/track_descriptor.py +++ b/bin/ffx/track_descriptor.py @@ -23,6 +23,7 @@ class TrackDescriptor(): FFPROBE_INDEX_KEY = 'index' FFPROBE_DISPOSITION_KEY = 'disposition' FFPROBE_TAGS_KEY = 'tags' + FFPROBE_CODEC_TYPE_KEY = 'codec_type' def __init__(self, **kwargs): diff --git a/bin/ffx/track_details_screen.py b/bin/ffx/track_details_screen.py index 533123e..7c4c99d 100644 --- a/bin/ffx/track_details_screen.py +++ b/bin/ffx/track_details_screen.py @@ -348,6 +348,7 @@ class TrackDetailsScreen(Screen): if self.__isNew: + # Track per Screen hinzufügen self.__tc.addTrack(trackDescriptor) self.dismiss(trackDescriptor) @@ -355,6 +356,7 @@ class TrackDetailsScreen(Screen): track = self.__tc.getTrack(self.__pattern.getId(), self.__index) + # Track per details screen updaten if self.__tc.updateTrack(track.getId(), trackDescriptor): self.dismiss(trackDescriptor)