nightl
This commit is contained in:
@@ -339,7 +339,7 @@ def convert(ctx,
|
|||||||
|
|
||||||
click.echo(f"Input mapping tokens: {targetMediaDescriptor.getInputMappingTokens()}")
|
click.echo(f"Input mapping tokens: {targetMediaDescriptor.getInputMappingTokens()}")
|
||||||
|
|
||||||
fc = FfxController(currentMediaDescriptor, targetMediaDescriptor)
|
fc = FfxController(context, currentMediaDescriptor, targetMediaDescriptor)
|
||||||
|
|
||||||
mappingTokens = fc.generateMetadataTokens()
|
mappingTokens = fc.generateMetadataTokens()
|
||||||
click.echo(f"Metadata Tokens: {mappingTokens}")
|
click.echo(f"Metadata Tokens: {mappingTokens}")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class AudioLayout(Enum):
|
|||||||
LAYOUT_UNDEFINED = {"layout": "undefined", "index": 0}
|
LAYOUT_UNDEFINED = {"layout": "undefined", "index": 0}
|
||||||
|
|
||||||
|
|
||||||
def layout(self):
|
def label(self):
|
||||||
"""Returns the layout as string"""
|
"""Returns the layout as string"""
|
||||||
return self.value['layout']
|
return self.value['layout']
|
||||||
|
|
||||||
@@ -21,6 +21,12 @@ class AudioLayout(Enum):
|
|||||||
"""Returns the layout as string"""
|
"""Returns the layout as string"""
|
||||||
return self.value['layout']
|
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):
|
def identify(self, streamObj):
|
||||||
|
|
||||||
|
|||||||
@@ -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.helper import DIFF_ADDED_KEY, DIFF_REMOVED_KEY, DIFF_CHANGED_KEY
|
||||||
from ffx.track_descriptor import TrackDescriptor
|
from ffx.track_descriptor import TrackDescriptor
|
||||||
from ffx.model.track import Track
|
from ffx.model.track import Track
|
||||||
|
from ffx.audio_layout import AudioLayout
|
||||||
|
|
||||||
|
|
||||||
class FfxController():
|
class FfxController():
|
||||||
@@ -37,8 +38,12 @@ class FfxController():
|
|||||||
|
|
||||||
INPUT_FILE_EXTENSIONS = ['mkv', 'mp4', 'avi', 'flv', 'webm']
|
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.__sourceMediaDescriptor = sourceMediaDescriptor
|
||||||
self.__targetMediaDescriptor = targetMediaDescriptor
|
self.__targetMediaDescriptor = targetMediaDescriptor
|
||||||
|
|
||||||
@@ -99,49 +104,49 @@ class FfxController():
|
|||||||
return ['-f', format, f"{filepath}.{ext}"]
|
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"""
|
"""Generates ffmpeg options for one output audio stream including channel remapping, codec and bitrate"""
|
||||||
pass
|
pass
|
||||||
#
|
|
||||||
# if layout == STREAM_LAYOUT_6_1:
|
if layout == AudioLayout.LAYOUT_6_1:
|
||||||
# return [f"-c:a:{index}",
|
return [f"-c:a:{subIndex}",
|
||||||
# 'libopus',
|
'libopus',
|
||||||
# f"-filter:a:{index}",
|
f"-filter:a:{subIndex}",
|
||||||
# 'channelmap=channel_layout=6.1',
|
'channelmap=channel_layout=6.1',
|
||||||
# f"-b:a:{index}",
|
f"-b:a:{subIndex}",
|
||||||
# context['bitrates']['dts']]
|
self.__context['bitrates']['dts']]
|
||||||
#
|
|
||||||
# elif layout == STREAM_LAYOUT_5_1:
|
elif layout == AudioLayout.LAYOUT_5_1:
|
||||||
# return [f"-c:a:{index}",
|
return [f"-c:a:{subIndex}",
|
||||||
# 'libopus',
|
'libopus',
|
||||||
# f"-filter:a:{index}",
|
f"-filter:a:{subIndex}",
|
||||||
# "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1",
|
"channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1",
|
||||||
# f"-b:a:{index}",
|
f"-b:a:{subIndex}",
|
||||||
# context['bitrates']['ac3']]
|
self.__context['bitrates']['ac3']]
|
||||||
#
|
|
||||||
# elif layout == STREAM_LAYOUT_STEREO:
|
elif layout == AudioLayout.LAYOUT_STEREO:
|
||||||
# return [f"-c:a:{index}",
|
return [f"-c:a:{subIndex}",
|
||||||
# 'libopus',
|
'libopus',
|
||||||
# f"-b:a:{index}",
|
f"-b:a:{subIndex}",
|
||||||
# context['bitrates']['stereo']]
|
self.__context['bitrates']['stereo']]
|
||||||
#
|
|
||||||
# elif layout == STREAM_LAYOUT_6CH:
|
elif layout == AudioLayout.LAYOUT_6CH:
|
||||||
# return [f"-c:a:{index}",
|
return [f"-c:a:{subIndex}",
|
||||||
# 'libopus',
|
'libopus',
|
||||||
# f"-filter:a:{index}",
|
f"-filter:a:{subIndex}",
|
||||||
# "channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1",
|
"channelmap=FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1",
|
||||||
# f"-b:a:{index}",
|
f"-b:a:{subIndex}",
|
||||||
# context['bitrates']['ac3']]
|
self.__context['bitrates']['ac3']]
|
||||||
# else:
|
else:
|
||||||
# return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def generateClearTokens(self, streams):
|
# def generateClearTokens(self, streams):
|
||||||
clearTokens = []
|
# clearTokens = []
|
||||||
for s in streams:
|
# for s in streams:
|
||||||
for k in FfxController.MKVMERGE_METADATA_KEYS:
|
# for k in FfxController.MKVMERGE_METADATA_KEYS:
|
||||||
clearTokens += [f"-metadata:s:{s['type'][0]}:{s['sub_index']}", f"{k}="]
|
# clearTokens += [f"-metadata:s:{s['type'][0]}:{s['sub_index']}", f"{k}="]
|
||||||
return clearTokens
|
# return clearTokens
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -191,8 +191,10 @@ class MediaDescriptor():
|
|||||||
|
|
||||||
#HINT: Some tags differ per file, for example creation_time, so these are removed before diff
|
#HINT: Some tags differ per file, for example creation_time, so these are removed before diff
|
||||||
for emt in MediaDescriptor.EXCLUDED_MEDIA_TAGS:
|
for emt in MediaDescriptor.EXCLUDED_MEDIA_TAGS:
|
||||||
del tags[emt]
|
if emt in tags.keys():
|
||||||
del vsTags[emt]
|
del tags[emt]
|
||||||
|
if emt in vsTags.keys():
|
||||||
|
del vsTags[emt]
|
||||||
|
|
||||||
tagsDiff = dictDiff(vsTags, tags)
|
tagsDiff = dictDiff(vsTags, tags)
|
||||||
|
|
||||||
@@ -218,12 +220,12 @@ class MediaDescriptor():
|
|||||||
|
|
||||||
for tp in range(maxNumOfTracks):
|
for tp in range(maxNumOfTracks):
|
||||||
|
|
||||||
# if self.__jellyfinOrder:
|
# inspect/update funktionier nur so
|
||||||
# vsTrackIndex = tracks[tp].getSourceIndex()
|
if self.__jellyfinOrder:
|
||||||
# else:
|
vsTrackIndex = tracks[tp].getSourceIndex()
|
||||||
# vsTrackIndex = tp
|
else:
|
||||||
|
vsTrackIndex = tp
|
||||||
vsTrackIndex = tracks[tp].getSourceIndex()
|
# vsTrackIndex = tracks[tp].getSourceIndex()
|
||||||
|
|
||||||
# Will trigger if tracks are missing in file
|
# Will trigger if tracks are missing in file
|
||||||
if tp > (numVsTracks - 1):
|
if tp > (numVsTracks - 1):
|
||||||
|
|||||||
@@ -507,6 +507,8 @@ class MediaDetailsScreen(Screen):
|
|||||||
|
|
||||||
if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||||
for removedTrackIndex, removedTrack in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY].items():
|
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())
|
self.__tc.addTrack(removedTrack, patternId = self.__currentPattern.getId())
|
||||||
|
|
||||||
if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ from ffx.iso_language import IsoLanguage
|
|||||||
from ffx.track_disposition import TrackDisposition
|
from ffx.track_disposition import TrackDisposition
|
||||||
from ffx.track_descriptor import TrackDescriptor
|
from ffx.track_descriptor import TrackDescriptor
|
||||||
|
|
||||||
|
from ffx.audio_layout import AudioLayout
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
class Track(Base):
|
class Track(Base):
|
||||||
@@ -40,9 +42,10 @@ class Track(Base):
|
|||||||
|
|
||||||
track_tags = relationship('TrackTag', back_populates='track', cascade="all, delete", lazy="joined")
|
track_tags = relationship('TrackTag', back_populates='track', cascade="all, delete", lazy="joined")
|
||||||
|
|
||||||
|
|
||||||
disposition_flags = Column(Integer)
|
disposition_flags = Column(Integer)
|
||||||
|
|
||||||
|
audio_layout = Column(Integer)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
@@ -57,7 +60,7 @@ class Track(Base):
|
|||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromStreamObj(cls, streamObj, patternId):
|
def fromFfprobeStreamObj(cls, streamObj, patternId):
|
||||||
"""{
|
"""{
|
||||||
'index': 4,
|
'index': 4,
|
||||||
'codec_name': 'hdmv_pgs_subtitle',
|
'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]:
|
if trackType in [t.label() for t in TrackType]:
|
||||||
|
|
||||||
# sub_index = int(subIndex),
|
|
||||||
return cls(pattern_id = patternId,
|
return cls(pattern_id = patternId,
|
||||||
track_type = trackType,
|
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:
|
else:
|
||||||
return None
|
return None
|
||||||
@@ -163,6 +167,9 @@ class Track(Base):
|
|||||||
def getDispositionSet(self):
|
def getDispositionSet(self):
|
||||||
return TrackDisposition.toSet(self.disposition_flags)
|
return TrackDisposition.toSet(self.disposition_flags)
|
||||||
|
|
||||||
|
def getAudioLayout(self):
|
||||||
|
return AudioLayout.fromIndex(self.audio_layout)
|
||||||
|
|
||||||
def getTags(self):
|
def getTags(self):
|
||||||
return {str(t.key):str(t.value) for t in self.track_tags}
|
return {str(t.key):str(t.value) for t in self.track_tags}
|
||||||
|
|
||||||
@@ -194,4 +201,6 @@ class Track(Base):
|
|||||||
kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet()
|
kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet()
|
||||||
kwargs[TrackDescriptor.TAGS_KEY] = self.getTags()
|
kwargs[TrackDescriptor.TAGS_KEY] = self.getTags()
|
||||||
|
|
||||||
|
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = self.getAudioLayout()
|
||||||
|
|
||||||
return TrackDescriptor(**kwargs)
|
return TrackDescriptor(**kwargs)
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class PatternDetailsScreen(Screen):
|
|||||||
row = (td.getIndex(),
|
row = (td.getIndex(),
|
||||||
trackType.label(),
|
trackType.label(),
|
||||||
typeCounter[trackType],
|
typeCounter[trackType],
|
||||||
" ",
|
td.getAudioLayout().label(),
|
||||||
td.getLanguage().label(),
|
td.getLanguage().label(),
|
||||||
td.getTitle(),
|
td.getTitle(),
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
|
|||||||
@@ -82,16 +82,16 @@ class ShowDetailsScreen(Screen):
|
|||||||
self.show_obj = self.__sc.getShowDesciptor(showId) if showId is not None else {}
|
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:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
q = s.query(Pattern).filter(Pattern.show_id == int(show_id))
|
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:
|
except Exception as ex:
|
||||||
click.ClickException(f"loadPatterns(): {repr(ex)}")
|
raise click.ClickException(f"ShowDetailsScreen.loadPatterns(): {repr(ex)}")
|
||||||
finally:
|
finally:
|
||||||
s.close()
|
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_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'])
|
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'],)
|
row = (pattern['pattern'],)
|
||||||
self.patternTable.add_row(*map(str, row))
|
self.patternTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class TrackDescriptor():
|
|||||||
FFPROBE_INDEX_KEY = 'index'
|
FFPROBE_INDEX_KEY = 'index'
|
||||||
FFPROBE_DISPOSITION_KEY = 'disposition'
|
FFPROBE_DISPOSITION_KEY = 'disposition'
|
||||||
FFPROBE_TAGS_KEY = 'tags'
|
FFPROBE_TAGS_KEY = 'tags'
|
||||||
|
FFPROBE_CODEC_TYPE_KEY = 'codec_type'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
|
|||||||
@@ -348,6 +348,7 @@ class TrackDetailsScreen(Screen):
|
|||||||
|
|
||||||
if self.__isNew:
|
if self.__isNew:
|
||||||
|
|
||||||
|
# Track per Screen hinzufügen
|
||||||
self.__tc.addTrack(trackDescriptor)
|
self.__tc.addTrack(trackDescriptor)
|
||||||
self.dismiss(trackDescriptor)
|
self.dismiss(trackDescriptor)
|
||||||
|
|
||||||
@@ -355,6 +356,7 @@ class TrackDetailsScreen(Screen):
|
|||||||
|
|
||||||
track = self.__tc.getTrack(self.__pattern.getId(), self.__index)
|
track = self.__tc.getTrack(self.__pattern.getId(), self.__index)
|
||||||
|
|
||||||
|
# Track per details screen updaten
|
||||||
if self.__tc.updateTrack(track.getId(), trackDescriptor):
|
if self.__tc.updateTrack(track.getId(), trackDescriptor):
|
||||||
self.dismiss(trackDescriptor)
|
self.dismiss(trackDescriptor)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user