decon/inc stream parsing
This commit is contained in:
191
bin/ffx.py
191
bin/ffx.py
@@ -209,30 +209,29 @@ def getStreamDescriptor(filename):
|
||||
|
||||
for subStream in streamData:
|
||||
|
||||
s = subStream.copy()
|
||||
|
||||
#Defaulting to undefined if tag not defined for stream
|
||||
if 'tags' in subStream.keys() and 'language' in subStream['tags'].keys():
|
||||
s['language'] = subStream['tags']['language']
|
||||
else:
|
||||
s['language'] = 'undefined'
|
||||
|
||||
#Defaulting to undefined if tag not defined for stream
|
||||
if 'tags' in subStream.keys() and 'title' in subStream['tags'].keys():
|
||||
s['title'] = subStream['tags']['title']
|
||||
else:
|
||||
s['title'] = 'undefined'
|
||||
if not 'disposition' in subStream.keys():
|
||||
subStream['disposition'] = {}
|
||||
if not 'default' in subStream['disposition'].keys():
|
||||
subStream['disposition']['default'] = 0
|
||||
if not 'forced' in subStream['disposition'].keys():
|
||||
subStream['disposition']['forced'] = 0
|
||||
if not 'tags' in subStream.keys():
|
||||
subStream['tags'] = {}
|
||||
if not 'language' in subStream['tags'].keys():
|
||||
subStream['tags']['language'] = 'undefined'
|
||||
if not 'title' in subStream['tags'].keys():
|
||||
subStream['tags']['title'] = 'undefined'
|
||||
|
||||
if subStream['codec_type'] == STREAM_TYPE_AUDIO:
|
||||
if 'channel_layout' in subStream.keys():
|
||||
s['layout'] = subStream['channel_layout']
|
||||
subStream['audio_layout'] = subStream['channel_layout']
|
||||
elif subStream['channels'] == 6:
|
||||
s['layout'] = STREAM_LAYOUT_6CH
|
||||
subStream['audio_layout'] = STREAM_LAYOUT_6CH
|
||||
else:
|
||||
s['layout'] = 'undefined'
|
||||
subStream['audio_layout'] = 'undefined'
|
||||
|
||||
descriptor[s['codec_type']].append(s)
|
||||
descriptor[s['codec_type']][-1]['src_sub_index'] = len(descriptor[s['codec_type']]) - 1
|
||||
descriptor[subStream['codec_type']].append(subStream)
|
||||
descriptor[subStream['codec_type']][-1]['sub_index'] = len(descriptor[subStream['codec_type']]) - 1
|
||||
|
||||
return descriptor
|
||||
|
||||
@@ -247,13 +246,13 @@ def getModifiedStreamOrder(length, last):
|
||||
return seq
|
||||
|
||||
|
||||
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 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(q, p):
|
||||
@@ -619,46 +618,61 @@ def convert(ctx,
|
||||
targetFilenameTokens = [sourceFileBasename]
|
||||
|
||||
|
||||
# SSD -> TSD -> MSO
|
||||
#
|
||||
# src file [vtt files] -> SSD
|
||||
#
|
||||
# in opts, checks -> TSD
|
||||
#
|
||||
# jellyfin -> MSO
|
||||
#
|
||||
# TSD - SSD, MSO -> out opts
|
||||
|
||||
# Load source stream descriptor
|
||||
try:
|
||||
###
|
||||
sourceStreamDescriptor = getStreamDescriptor(sourcePath)
|
||||
|
||||
# Ensure disposition and tags keys for every stream
|
||||
for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
if not 'disposition' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'] = {}
|
||||
if not 'default' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition']['default'] = 0
|
||||
if not 'forced' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition']['forced'] = 0
|
||||
for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
if not 'tags' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['tags'] = {}
|
||||
for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE])):
|
||||
if not 'disposition' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'] = {}
|
||||
if not 'default' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['default'] = 0
|
||||
if not 'forced' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['forced'] = 0
|
||||
for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE])):
|
||||
if not 'tags' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex].keys():
|
||||
sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['tags'] = {}
|
||||
|
||||
targetStreamDescriptor = sourceStreamDescriptor.copy()
|
||||
###
|
||||
|
||||
except Exception:
|
||||
click.echo(f"File with path {sourcePath} does not contain any audiovisual data, skipping ...")
|
||||
continue
|
||||
|
||||
# # Ensure disposition and tags keys for every stream
|
||||
# for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
# if not 'disposition' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'] = {}
|
||||
# if not 'default' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition']['default'] = 0
|
||||
# if not 'forced' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition'].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['disposition']['forced'] = 0
|
||||
# for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
# if not 'tags' in sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_AUDIO][substreamIndex]['tags'] = {}
|
||||
# for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE])):
|
||||
# if not 'disposition' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'] = {}
|
||||
# if not 'default' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['default'] = 0
|
||||
# if not 'forced' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition'].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['forced'] = 0
|
||||
# for substreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE])):
|
||||
# if not 'tags' in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex].keys():
|
||||
# sourceStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['tags'] = {}
|
||||
|
||||
click.echo('Source streans:')
|
||||
###
|
||||
targetStreamDescriptor = sourceStreamDescriptor.copy()
|
||||
###
|
||||
|
||||
|
||||
click.echo('\nSource streams:')
|
||||
for aStream in sourceStreamDescriptor[STREAM_TYPE_AUDIO]:
|
||||
click.echo(f"audio stream {aStream['src_sub_index']} lang={aStream['language']} title={aStream['title']} default={aStream['disposition']['default']} forced={aStream['disposition']['forced']}")
|
||||
|
||||
click.echo(f"audio stream {aStream['sub_index']} lang={aStream['tags']['language']} title={aStream['tags']['title']} default={aStream['disposition']['default']} forced={aStream['disposition']['forced']}")
|
||||
for sStream in sourceStreamDescriptor[STREAM_TYPE_SUBTITLE]:
|
||||
click.echo(f"subtitle stream {sStream['src_sub_index']} lang={sStream['language']} title={sStream['title']} default={sStream['disposition']['default']} forced={sStream['disposition']['forced']}")
|
||||
click.echo(f"subtitle stream {sStream['sub_index']} lang={sStream['tags']['language']} title={sStream['tags']['title']} default={sStream['disposition']['default']} forced={sStream['disposition']['forced']}")
|
||||
|
||||
|
||||
# Check for multiple default or forced dispositions if not set by user input or database requirements
|
||||
#NOTE: It is currently expected that all source file have the same substream pattern, e.g. coming from the same encoder
|
||||
numDefaultAudioStreams = len([a for a in sourceStreamDescriptor[STREAM_TYPE_AUDIO] if a['disposition']['default'] == 1])
|
||||
if defaultAudio == -1 and numDefaultAudioStreams > 1:
|
||||
@@ -676,7 +690,6 @@ def convert(ctx,
|
||||
if forcedSubtitle == -1 and numForcedSubtitleStreams > 1:
|
||||
forcedSubtitle = click.prompt("More than one forced subtitle stream detected! Please select stream", type=int)
|
||||
|
||||
|
||||
#Fix multiple default/forced tags
|
||||
if defaultAudio != -1:
|
||||
for substreamIndex in range(len(targetStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
@@ -692,14 +705,50 @@ def convert(ctx,
|
||||
targetStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['forded'] = 1 if substreamIndex == forcedSubtitle else 0
|
||||
|
||||
|
||||
click.echo('Target streans:')
|
||||
|
||||
## Process input opts
|
||||
|
||||
# # Source stream descriptors
|
||||
# audioStreams = targetStreamDescriptor[STREAM_TYPE_AUDIO]
|
||||
# subtitleStreams = targetStreamDescriptor[STREAM_TYPE_SUBTITLE]
|
||||
#
|
||||
# # Set language and title in source stream descriptors if given per command line option
|
||||
# for streamIndex in range(len(audioStreams)):
|
||||
# if streamIndex <= len(audioLanguages) - 1:
|
||||
# audioStreams[streamIndex]['tags']['language'] = audioLanguages[streamIndex]
|
||||
# if streamIndex <= len(audioTitles) - 1:
|
||||
# audioStreams[streamIndex]['tags']['title'] = audioTitles[streamIndex]
|
||||
#
|
||||
# for streamIndex in range(len(subtitleStreams)):
|
||||
# if streamIndex <= len(subtitleLanguages) - 1:
|
||||
# subtitleStreams[streamIndex]['tags']['language'] = subtitleLanguages[streamIndex]
|
||||
# if streamIndex <= len(subtitleTitles) - 1:
|
||||
# subtitleStreams[streamIndex]['tags']['title'] = subtitleTitles[streamIndex]
|
||||
|
||||
|
||||
# Set language and title in source stream descriptors if given per command line option
|
||||
for streamIndex in range(len(targetStreamDescriptor[STREAM_TYPE_AUDIO])):
|
||||
if streamIndex <= len(audioLanguages) - 1:
|
||||
targetStreamDescriptor[STREAM_TYPE_AUDIO][streamIndex]['tags']['language'] = audioLanguages[streamIndex]
|
||||
if streamIndex <= len(audioTitles) - 1:
|
||||
targetStreamDescriptor[STREAM_TYPE_AUDIO][streamIndex]['tags']['title'] = audioTitles[streamIndex]
|
||||
|
||||
for streamIndex in range(len(targetStreamDescriptor[STREAM_TYPE_SUBTITLE])):
|
||||
if streamIndex <= len(subtitleLanguages) - 1:
|
||||
targetStreamDescriptor[STREAM_TYPE_SUBTITLE][streamIndex]['tags']['language'] = subtitleLanguages[streamIndex]
|
||||
if streamIndex <= len(subtitleTitles) - 1:
|
||||
targetStreamDescriptor[STREAM_TYPE_SUBTITLE][streamIndex]['tags']['title'] = subtitleTitles[streamIndex]
|
||||
|
||||
|
||||
|
||||
|
||||
click.echo('\nTarget streams:')
|
||||
for aStream in targetStreamDescriptor[STREAM_TYPE_AUDIO]:
|
||||
click.echo(f"audio stream {aStream['src_sub_index']} lang={aStream['language']} title={aStream['title']} default={aStream['disposition']['default']} forced={aStream['disposition']['forced']}")
|
||||
|
||||
click.echo(f"audio stream {aStream['sub_index']} lang={aStream['tags']['language']} title={aStream['tags']['title']} default={aStream['disposition']['default']} forced={aStream['disposition']['forced']}")
|
||||
for sStream in targetStreamDescriptor[STREAM_TYPE_SUBTITLE]:
|
||||
click.echo(f"subtitle stream {sStream['src_sub_index']} lang={sStream['language']} title={sStream['title']} default={sStream['disposition']['default']} forced={sStream['disposition']['forced']}")
|
||||
|
||||
click.echo(f"subtitle stream {sStream['sub_index']} lang={sStream['tags']['language']} title={sStream['tags']['title']} default={sStream['disposition']['default']} forced={sStream['disposition']['forced']}")
|
||||
|
||||
continue
|
||||
|
||||
commandTokens = COMMAND_TOKENS + ['-i', sourcePath]
|
||||
|
||||
@@ -739,28 +788,6 @@ def convert(ctx,
|
||||
|
||||
audioTokens = []
|
||||
|
||||
# Source stream descriptors
|
||||
audioStreams = sourceStreamDescriptor[STREAM_TYPE_AUDIO]
|
||||
subtitleStreams = sourceStreamDescriptor[STREAM_TYPE_SUBTITLE]
|
||||
|
||||
# Set language and title in source stream descriptors if given per command line option
|
||||
for streamIndex in range(len(audioStreams)):
|
||||
if 'tags' not in audioStreams[streamIndex].keys():
|
||||
audioStreams[streamIndex]['tags'] = {}
|
||||
|
||||
if streamIndex <= len(audioLanguages) - 1:
|
||||
audioStreams[streamIndex]['tags']['language'] = audioLanguages[streamIndex]
|
||||
if streamIndex <= len(audioTitles) - 1:
|
||||
audioStreams[streamIndex]['tags']['title'] = audioTitles[streamIndex]
|
||||
|
||||
for streamIndex in range(len(subtitleStreams)):
|
||||
if 'tags' not in subtitleStreams[streamIndex].keys():
|
||||
subtitleStreams[streamIndex]['tags'] = {}
|
||||
|
||||
if streamIndex <= len(subtitleLanguages) - 1:
|
||||
subtitleStreams[streamIndex]['tags']['language'] = subtitleLanguages[streamIndex]
|
||||
if streamIndex <= len(subtitleTitles) - 1:
|
||||
subtitleStreams[streamIndex]['tags']['title'] = subtitleTitles[streamIndex]
|
||||
|
||||
# Reorder audio stream descriptors and create disposition options if default is given per command line option
|
||||
if defaultAudio == -1:
|
||||
@@ -813,7 +840,7 @@ def convert(ctx,
|
||||
numMatchingSubtitles = len(matchingSubtitles)
|
||||
|
||||
if jellyfin and defaultSubtitle != -1:
|
||||
subtitleSequence = getModifiedStreamOrder(numMatchingSubtitles, default_subtitle)
|
||||
subtitleSequence = getModifiedStreamOrder(numMatchingSubtitles, default_subtitle) #!
|
||||
else:
|
||||
subtitleSequence = range(numMatchingSubtitles)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user