inc ffx single descriptor 1/
This commit is contained in:
@@ -40,8 +40,8 @@ class FfxController():
|
||||
|
||||
def __init__(self,
|
||||
context : dict,
|
||||
sourceMediaDescriptor : MediaDescriptor,
|
||||
targetMediaDescriptor : MediaDescriptor):
|
||||
targetMediaDescriptor : MediaDescriptor,
|
||||
sourceMediaDescriptor : MediaDescriptor = None):
|
||||
|
||||
self.__context = context
|
||||
self.__sourceMediaDescriptor = sourceMediaDescriptor
|
||||
@@ -90,7 +90,12 @@ class FfxController():
|
||||
'-lag-in-frames', '25']
|
||||
|
||||
|
||||
def generateCropTokens(self, start, length):
|
||||
|
||||
@staticmethod
|
||||
def generateCropTokens(cropStart : int = -1, cropLength : int = -1):
|
||||
|
||||
start = int(cropStart if cropStart > -1 else FfxController.DEFAULT_CROP_START)
|
||||
length = int(cropLength if cropLength > -1 else FfxController.DEFAULT_CROP_LENGTH)
|
||||
|
||||
return ['-ss', str(start), '-t', str(length)]
|
||||
|
||||
@@ -171,27 +176,29 @@ class FfxController():
|
||||
def generateDispositionTokens(self):
|
||||
"""-disposition:s:X default+forced"""
|
||||
|
||||
sourceTrackDescriptors = self.__sourceMediaDescriptor.getAllTrackDescriptors()
|
||||
sourceTrackDescriptors = [] if self.__sourceMediaDescriptor is None else self.__sourceMediaDescriptor.getAllTrackDescriptors()
|
||||
targetTrackDescriptors = self.__targetMediaDescriptor.getReorderedTrackDescriptors()
|
||||
|
||||
|
||||
dispositionTokens = []
|
||||
|
||||
# for subStreamIndex in range(len(subDescriptor)):
|
||||
for trackDescriptor in targetTrackDescriptors:
|
||||
|
||||
# Calculate source sub index
|
||||
changedTargetTrackDescriptor : TrackDescriptor = targetTrackDescriptors[trackDescriptor.getIndex()]
|
||||
changedTargetTrackSourceIndex = changedTargetTrackDescriptor.getSourceIndex()
|
||||
sourceSubIndex = sourceTrackDescriptors[changedTargetTrackSourceIndex].getSubIndex()
|
||||
# Calculate source sub index. This applies only if a source media descriptor is defined.
|
||||
if sourceTrackDescriptors:
|
||||
changedTargetTrackDescriptor : TrackDescriptor = targetTrackDescriptors[trackDescriptor.getIndex()]
|
||||
changedTargetTrackSourceIndex = changedTargetTrackDescriptor.getSourceIndex()
|
||||
subIndex = sourceTrackDescriptors[changedTargetTrackSourceIndex].getSubIndex()
|
||||
else:
|
||||
subIndex = trackDescriptor.getSubIndex()
|
||||
|
||||
streamIndicator = trackDescriptor.getType().indicator()
|
||||
dispositionSet = trackDescriptor.getDispositionSet()
|
||||
|
||||
if dispositionSet:
|
||||
dispositionTokens += [f"-disposition:{streamIndicator}:{sourceSubIndex}", '+'.join([d.label() for d in dispositionSet])]
|
||||
dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '+'.join([d.label() for d in dispositionSet])]
|
||||
else:
|
||||
dispositionTokens += [f"-disposition:{streamIndicator}:{sourceSubIndex}", '0']
|
||||
dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '0']
|
||||
|
||||
return dispositionTokens
|
||||
|
||||
|
||||
@@ -67,24 +67,25 @@ class FileProperties():
|
||||
#
|
||||
# print(f"season={season} episode={episode} file={file_index}")
|
||||
#
|
||||
#
|
||||
# # Assemble target filename tokens
|
||||
# targetFilenameTokens = []
|
||||
|
||||
def assembleTargetFilename(self):
|
||||
|
||||
targetFilenameTokens = []
|
||||
# targetFilenameExtension = DEFAULT_FILE_EXTENSION
|
||||
#
|
||||
# if label:
|
||||
# targetFilenameTokens = [label]
|
||||
#
|
||||
# if season > -1 and episode > -1:
|
||||
# targetFilenameTokens += [f"S{season:0{season_digits}d}E{episode:0{episode_digits}d}"]
|
||||
# elif episode > -1:
|
||||
# targetFilenameTokens += [f"E{episode:0{episode_digits}d}"]
|
||||
# if self.__season > -1 and self.__episode > -1:
|
||||
# targetFilenameTokens += [f"S{self.__season:0{season_digits}d}E{self.__episode:0{episode_digits}d}"]
|
||||
# elif self.__episode > -1:
|
||||
# targetFilenameTokens += [f"E{self.__episode:0{episode_digits}d}"]
|
||||
# else:
|
||||
# targetFilenameTokens += [f"{file_index:0{index_digits}d}"]
|
||||
#
|
||||
# else:
|
||||
# targetFilenameTokens = [sourceFileBasename]
|
||||
#
|
||||
# targetFilenameTokens = [self.__sourceFileBasename]
|
||||
|
||||
|
||||
|
||||
def searchSubtitleFiles(dir, prefix):
|
||||
|
||||
@@ -65,39 +65,74 @@ class MediaDescriptor():
|
||||
self.__jellyfinOrder = False
|
||||
|
||||
|
||||
def getDefaultVideoTrack(self):
|
||||
videoDefaultTracks = [v for v in self.getVideoTracks() if TrackDisposition.DEFAULT in v.getDispositionSet()]
|
||||
if len(videoDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getDefaultVideoTrack(): More than one default video track is not supported')
|
||||
return videoDefaultTracks[0] if videoDefaultTracks else None
|
||||
|
||||
def getForcedVideoTrack(self):
|
||||
videoForcedTracks = [v for v in self.getVideoTracks() if TrackDisposition.FORCED in v.getDispositionSet()]
|
||||
if len(videoForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getForcedVideoTrack(): More than one forced video track is not supported')
|
||||
return videoForcedTracks[0] if videoForcedTracks else None
|
||||
|
||||
def getDefaultAudioTrack(self):
|
||||
audioDefaultTracks = [a for a in self.getAudioTracks() if TrackDisposition.DEFAULT in a.getDispositionSet()]
|
||||
if len(audioDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getDefaultAudioTrack(): More than one default audio track is not supported')
|
||||
return audioDefaultTracks[0] if audioDefaultTracks else None
|
||||
|
||||
def getForcedAudioTrack(self):
|
||||
audioForcedTracks = [a for a in self.getAudioTracks() if TrackDisposition.FORCED in a.getDispositionSet()]
|
||||
if len(audioForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getForcedAudioTrack(): More than one forced audio track is not supported')
|
||||
return audioForcedTracks[0] if audioForcedTracks else None
|
||||
|
||||
def getDefaultSubtitleTrack(self):
|
||||
subtitleDefaultTracks = [s for s in self.getSubtitleTracks() if TrackDisposition.DEFAULT in s.getDispositionSet()]
|
||||
if len(subtitleDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getDefaultSubtitleTrack(): More than one default subtitle track is not supported')
|
||||
return subtitleDefaultTracks[0] if subtitleDefaultTracks else None
|
||||
|
||||
def getForcedSubtitleTrack(self):
|
||||
subtitleForcedTracks = [s for s in self.getSubtitleTracks() if TrackDisposition.FORCED in s.getDispositionSet()]
|
||||
if len(subtitleForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.getForcedSubtitleTrack(): More than one forced subtitle track is not supported')
|
||||
return subtitleForcedTracks[0] if subtitleForcedTracks else None
|
||||
|
||||
|
||||
def setDefaultSubTrack(self, trackType : TrackType, subIndex : int):
|
||||
for t in self.getAllTrackDescriptors():
|
||||
if t.getType() == trackType:
|
||||
t.setDispositionFlag(TrackDisposition.DEFAULT, t.getSubIndex() == int(subIndex))
|
||||
|
||||
def setForcedSubTrack(self, trackType : TrackType, subIndex : int):
|
||||
for t in self.getAllTrackDescriptors():
|
||||
if t.getType() == trackType:
|
||||
t.setDispositionFlag(TrackDisposition.FORCED, t.getSubIndex() == int(subIndex))
|
||||
|
||||
|
||||
def getReorderedTrackDescriptors(self):
|
||||
|
||||
videoTracks = self.getVideoTracks()
|
||||
audioTracks = self.getAudioTracks()
|
||||
subtitleTracks = self.getSubtitleTracks()
|
||||
videoTracks = self.sortSubIndices(self.getVideoTracks())
|
||||
audioTracks = self.sortSubIndices(self.getAudioTracks())
|
||||
subtitleTracks = self.sortSubIndices(self.getSubtitleTracks())
|
||||
|
||||
videoDefaultTracks = [v for v in videoTracks if TrackDisposition.DEFAULT in v.getDispositionSet()]
|
||||
videoForcedTracks = [v for v in videoTracks if TrackDisposition.FORCED in v.getDispositionSet()]
|
||||
audioDefaultTracks = [a for a in audioTracks if TrackDisposition.DEFAULT in a.getDispositionSet()]
|
||||
audioForcedTracks = [a for a in audioTracks if TrackDisposition.FORCED in a.getDispositionSet()]
|
||||
subtitleDefaultTracks = [s for s in subtitleTracks if TrackDisposition.DEFAULT in s.getDispositionSet()]
|
||||
subtitleForcedTracks = [s for s in subtitleTracks if TrackDisposition.FORCED in s.getDispositionSet()]
|
||||
videoDefaultTrack = self.getDefaultVideoTrack()
|
||||
self.getForcedVideoTrack()
|
||||
audioDefaultTrack = self.getDefaultAudioTrack()
|
||||
self.getForcedAudioTrack()
|
||||
subtitleDefaultTrack = self.getDefaultSubtitleTrack()
|
||||
self.getForcedSubtitleTrack()
|
||||
|
||||
if len(videoDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default video track is not supported')
|
||||
if len(videoForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced video track is not supported')
|
||||
if len(audioDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default audio track is not supported')
|
||||
if len(audioForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced audio track is not supported')
|
||||
if len(subtitleDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default subtitle track is not supported')
|
||||
if len(subtitleForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced subtitle track is not supported')
|
||||
|
||||
if self.__jellyfinOrder:
|
||||
if videoDefaultTracks:
|
||||
videoTracks.append(videoTracks.pop(videoTracks.index(videoDefaultTracks[0])))
|
||||
if audioDefaultTracks:
|
||||
audioTracks.append(audioTracks.pop(audioTracks.index(audioDefaultTracks[0])))
|
||||
if subtitleDefaultTracks:
|
||||
subtitleTracks.append(subtitleTracks.pop(subtitleTracks.index(subtitleDefaultTracks[0])))
|
||||
if not videoDefaultTrack is None:
|
||||
videoTracks.append(videoTracks.pop(videoTracks.index(videoDefaultTrack)))
|
||||
if not audioDefaultTrack is None:
|
||||
audioTracks.append(audioTracks.pop(audioTracks.index(audioDefaultTrack)))
|
||||
if not subtitleDefaultTrack is None:
|
||||
subtitleTracks.append(subtitleTracks.pop(subtitleTracks.index(subtitleDefaultTrack)))
|
||||
|
||||
reorderedTrackDescriptors = videoTracks + audioTracks + subtitleTracks
|
||||
orderedSourceTrackSequence = [t.getSourceIndex() for t in reorderedTrackDescriptors]
|
||||
@@ -143,32 +178,26 @@ class MediaDescriptor():
|
||||
return self.__mediaTags
|
||||
|
||||
|
||||
def sortSubIndices(self, descriptors : List[TrackDescriptor]) -> List[TrackDescriptor]:
|
||||
subIndex = 0
|
||||
for t in descriptors:
|
||||
t.setSubIndex(subIndex)
|
||||
subIndex += 1
|
||||
return descriptors
|
||||
|
||||
|
||||
def getAllTrackDescriptors(self) -> List[TrackDescriptor]:
|
||||
return self.getVideoTracks() + self.getAudioTracks() + self.getSubtitleTracks()
|
||||
|
||||
def getVideoTracks(self) -> List[TrackDescriptor]:
|
||||
videoTracks = [v for v in self.__trackDescriptors.copy() if v.getType() == TrackType.VIDEO]
|
||||
subIndex = 0
|
||||
for v in videoTracks:
|
||||
v.setSubIndex(subIndex)
|
||||
subIndex += 1
|
||||
return videoTracks
|
||||
return [v for v in self.__trackDescriptors.copy() if v.getType() == TrackType.VIDEO]
|
||||
|
||||
|
||||
def getAudioTracks(self) -> List[TrackDescriptor]:
|
||||
audioTracks = [a for a in self.__trackDescriptors.copy() if a.getType() == TrackType.AUDIO]
|
||||
subIndex = 0
|
||||
for a in audioTracks:
|
||||
a.setSubIndex(subIndex)
|
||||
subIndex += 1
|
||||
return audioTracks
|
||||
return [a for a in self.__trackDescriptors.copy() if a.getType() == TrackType.AUDIO]
|
||||
|
||||
def getSubtitleTracks(self) -> List[TrackDescriptor]:
|
||||
subtitleTracks = [s for s in self.__trackDescriptors.copy() if s.getType() == TrackType.SUBTITLE]
|
||||
subIndex = 0
|
||||
for s in subtitleTracks:
|
||||
s.setSubIndex(subIndex)
|
||||
subIndex += 1
|
||||
return subtitleTracks
|
||||
return [s for s in self.__trackDescriptors.copy() if s.getType() == TrackType.SUBTITLE]
|
||||
|
||||
def getJellyfin(self):
|
||||
return self.__jellyfinOrder
|
||||
|
||||
@@ -229,3 +229,10 @@ class TrackController():
|
||||
raise click.ClickException(f"TrackController.deleteTrack(): {repr(ex)}")
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def setDefaultSubTrack(self, trackType, subIndex):
|
||||
pass
|
||||
|
||||
def setForcedSubTrack(self, trackType, subIndex):
|
||||
pass
|
||||
|
||||
@@ -204,6 +204,16 @@ class TrackDescriptor():
|
||||
return self.__dispositionSet
|
||||
|
||||
|
||||
def getDispositionFlag(self, disposition : TrackDisposition) -> bool:
|
||||
return bool(disposition in self.__dispositionSet)
|
||||
|
||||
def setDispositionFlag(self, disposition : TrackDisposition, state : bool):
|
||||
if state:
|
||||
self.__dispositionSet.add(disposition)
|
||||
else:
|
||||
self.__dispositionSet.discard(disposition)
|
||||
|
||||
|
||||
def compare(self, vsTrackDescriptor):
|
||||
|
||||
compareResult = {}
|
||||
|
||||
Reference in New Issue
Block a user