nightly
parent
bcb4e4d3d6
commit
93cc8a23c9
@ -1,2 +1,255 @@
|
||||
import click
|
||||
|
||||
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
|
||||
|
||||
|
||||
class FfxController():
|
||||
pass
|
||||
|
||||
COMMAND_TOKENS = ['ffmpeg', '-y']
|
||||
NULL_TOKENS = ['-f', 'null', '/dev/null'] # -f null /dev/null
|
||||
|
||||
TEMP_FILE_NAME = "ffmpeg2pass-0.log"
|
||||
|
||||
DEFAULT_VIDEO_ENCODER = 'vp9'
|
||||
|
||||
DEFAULT_QUALITY = 23
|
||||
DEFAULT_AV1_PRESET = 5
|
||||
|
||||
DEFAULT_FILE_FORMAT = 'webm'
|
||||
DEFAULT_FILE_EXTENSION = 'webm'
|
||||
|
||||
DEFAULT_STEREO_BANDWIDTH = "128"
|
||||
DEFAULT_AC3_BANDWIDTH = "256"
|
||||
DEFAULT_DTS_BANDWIDTH = "320"
|
||||
|
||||
DEFAULT_CROP_START = 60
|
||||
DEFAULT_CROP_LENGTH = 180
|
||||
|
||||
MKVMERGE_METADATA_KEYS = ['BPS',
|
||||
'NUMBER_OF_FRAMES',
|
||||
'NUMBER_OF_BYTES',
|
||||
'_STATISTICS_WRITING_APP',
|
||||
'_STATISTICS_WRITING_DATE_UTC',
|
||||
'_STATISTICS_TAGS']
|
||||
|
||||
|
||||
|
||||
# def getReorderedSubstreams(subDescriptor, last):
|
||||
# numSubStreams = len(subDescriptor)
|
||||
# modifiedOrder = getModifiedStreamOrder(numSubStreams, last)
|
||||
# reorderedDescriptor = []
|
||||
# for streamIndex in range(numSubStreams):
|
||||
# reorderedDescriptor.append(subDescriptor[modifiedOrder[streamIndex]])
|
||||
# return reorderedDescriptor
|
||||
|
||||
|
||||
def generateAV1Tokens(self, quality, preset):
|
||||
|
||||
return ['-c:v:0', 'libsvtav1',
|
||||
'-svtav1-params', f"crf={quality}:preset={preset}:tune=0:enable-overlays=1:scd=1:scm=0",
|
||||
'-pix_fmt', 'yuv420p10le']
|
||||
|
||||
|
||||
# -c:v:0 libvpx-vp9 -row-mt 1 -crf 32 -pass 1 -speed 4 -frame-parallel 0 -g 9999 -aq-mode 0
|
||||
def generateVP9Pass1Tokens(self, quality):
|
||||
|
||||
return ['-c:v:0', 'libvpx-vp9',
|
||||
'-row-mt', '1',
|
||||
'-crf', str(quality),
|
||||
'-pass', '1',
|
||||
'-speed', '4',
|
||||
'-frame-parallel', '0',
|
||||
'-g', '9999',
|
||||
'-aq-mode', '0']
|
||||
|
||||
# -c:v:0 libvpx-vp9 -row-mt 1 -crf 32 -pass 2 -frame-parallel 0 -g 9999 -aq-mode 0 -auto-alt-ref 1 -lag-in-frames 25
|
||||
def generateVP9Pass2Tokens(self, quality):
|
||||
|
||||
return ['-c:v:0', 'libvpx-vp9',
|
||||
'-row-mt', '1',
|
||||
'-crf', str(quality),
|
||||
'-pass', '2',
|
||||
'-frame-parallel', '0',
|
||||
'-g', '9999',
|
||||
'-aq-mode', '0',
|
||||
'-auto-alt-ref', '1',
|
||||
'-lag-in-frames', '25']
|
||||
|
||||
|
||||
def generateCropTokens(self, start, length):
|
||||
|
||||
return ['-ss', str(start), '-t', str(length)]
|
||||
|
||||
|
||||
def generateDenoiseTokens(self, spatial=5, patch=7, research=7, hw=False):
|
||||
filterName = 'nlmeans_opencl' if hw else 'nlmeans'
|
||||
return ['-vf', f"{filterName}=s={spatial}:p={patch}:r={research}"]
|
||||
|
||||
|
||||
def generateOutputTokens(self, filepath, format, ext):
|
||||
return ['-f', format, f"{filepath}.{ext}"]
|
||||
|
||||
|
||||
def generateAudioEncodingTokens(self, context, index, layout):
|
||||
"""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
|
||||
|
||||
|
||||
def getDispositionFlags(self, subStreamDescriptor):
|
||||
return {k for (k,v) in subStreamDescriptor['disposition'].items() if v == 1} if 'disposition' in subStreamDescriptor.keys() else set()
|
||||
|
||||
|
||||
|
||||
# def generateDispositionTokens(subDescriptor):
|
||||
def generateDispositionTokens(self, subDescriptor, modifyOrder = []):
|
||||
"""-disposition:s:X default+forced"""
|
||||
|
||||
dispositionTokens = []
|
||||
|
||||
for subStreamIndex in range(len(subDescriptor)):
|
||||
|
||||
sourceSubStreamIndex = modifyOrder[subStreamIndex] if modifyOrder else subStreamIndex
|
||||
|
||||
subStream = subDescriptor[sourceSubStreamIndex]
|
||||
|
||||
streamType = subStream['codec_type'][0] # v|a|s
|
||||
dispositionFlags = self.getDispositionFlags(subStream)
|
||||
|
||||
if dispositionFlags:
|
||||
dispositionTokens += [f"-disposition:{streamType}:{subStreamIndex}", '+'.join(dispositionFlags)]
|
||||
else:
|
||||
dispositionTokens += [f"-disposition:{streamType}:{subStreamIndex}", '0']
|
||||
|
||||
return dispositionTokens
|
||||
|
||||
|
||||
|
||||
def generateMappingTokensFromDescriptors(self, sourceMediaDescriptor : MediaDescriptor, targetMediaDescriptor : MediaDescriptor):
|
||||
|
||||
mappingTokens = []
|
||||
|
||||
mediaDifferences = targetMediaDescriptor.compare(sourceMediaDescriptor)
|
||||
|
||||
if MediaDescriptor.TAGS_KEY in mediaDifferences.keys():
|
||||
|
||||
sourceTags = sourceMediaDescriptor.getTags()
|
||||
targetTags = targetMediaDescriptor.getTags()
|
||||
|
||||
if DIFF_ADDED_KEY in mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||
for addedTagKey in mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]:
|
||||
# row = (f"added media tag: key='{addedTagKey}' value='{targetTags[addedTagKey]}'",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if DIFF_REMOVED_KEY in mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||
for removedTagKey in mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]:
|
||||
# row = (f"removed media tag: key='{removedTagKey}' value='{sourceTags[removedTagKey]}'",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if DIFF_CHANGED_KEY in mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||
for changedTagKey in mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_CHANGED_KEY]:
|
||||
# row = (f"changed media tag: key='{changedTagKey}' value='{sourceTags[changedTagKey]}'->'{targetTags[changedTagKey]}'",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if MediaDescriptor.TRACKS_KEY in mediaDifferences.keys():
|
||||
|
||||
sourceTracks = sourceMediaDescriptor.getAllTracks() # 0,1,2,3
|
||||
targetTracks = targetMediaDescriptor.getAllTracks() # 0 <- from DB
|
||||
|
||||
if DIFF_ADDED_KEY in mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||
addedTracksIndices = mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]
|
||||
raise click.ClickException(f"FfxController.generateMappingTokensFromDescriptors(): Adding tracks is not supported. Track indices {addedTracksIndices}")
|
||||
|
||||
#raise click.ClickException(f"add track {mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]}")
|
||||
#for addedTrackIndex in mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]:
|
||||
#addedTrack : Track = targetTracks[addedTrackIndex]
|
||||
# row = (f"added {addedTrack.getType().label()} track: index={addedTrackIndex} lang={addedTrack.getLanguage().threeLetter()}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
|
||||
if DIFF_REMOVED_KEY in mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||
removedTracksIndices = mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY].keys()
|
||||
raise click.ClickException(f"FfxController.generateMappingTokensFromDescriptors(): Removing tracks is not supported. Track indices {removedTracksIndices}")
|
||||
#for removedTrackIndex in mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY]:
|
||||
# row = (f"removed track: index={removedTrackIndex}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
|
||||
if DIFF_CHANGED_KEY in mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||
for changedTrackIndex in mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY].keys():
|
||||
|
||||
changedTrack : Track = targetTracks[changedTrackIndex]
|
||||
changedTrackDiff : dict = mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY][changedTrackIndex]
|
||||
|
||||
if MediaDescriptor.TAGS_KEY in changedTrackDiff.keys():
|
||||
|
||||
if DIFF_ADDED_KEY in changedTrackDiff[MediaDescriptor.TAGS_KEY]:
|
||||
for addedTagKey in changedTrackDiff[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]:
|
||||
addedTagValue = changedTrack.getTags()[addedTagKey]
|
||||
# row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added key={addedTagKey} value={addedTagValue}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if DIFF_REMOVED_KEY in changedTrackDiff[MediaDescriptor.TAGS_KEY]:
|
||||
for removedTagKey in changedTrackDiff[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]:
|
||||
# row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed key={removedTagKey}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if TrackDescriptor.DISPOSITION_SET_KEY in changedTrackDiff.keys():
|
||||
|
||||
if DIFF_ADDED_KEY in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY]:
|
||||
for addedDisposition in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY][DIFF_ADDED_KEY]:
|
||||
# row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added disposition={addedDisposition.label()}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
if DIFF_REMOVED_KEY in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY]:
|
||||
for removedDisposition in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY][DIFF_REMOVED_KEY]:
|
||||
# row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed disposition={removedDisposition.label()}",)
|
||||
# self.differencesTable.add_row(*map(str, row))
|
||||
pass
|
||||
|
||||
|
Loading…
Reference in New Issue