diff --git a/bin/ffx.py b/bin/ffx.py index 0f93873..ba0bcc4 100755 --- a/bin/ffx.py +++ b/bin/ffx.py @@ -618,16 +618,6 @@ 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: ### @@ -638,28 +628,6 @@ def convert(ctx, 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'] = {} - ### targetStreamDescriptor = sourceStreamDescriptor.copy() ### @@ -705,27 +673,6 @@ def convert(ctx, targetStreamDescriptor[STREAM_TYPE_SUBTITLE][substreamIndex]['disposition']['forded'] = 1 if substreamIndex == forcedSubtitle else 0 - - ## 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: @@ -740,6 +687,7 @@ def convert(ctx, 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['sub_index']} lang={aStream['tags']['language']} title={aStream['tags']['title']} default={aStream['disposition']['default']} forced={aStream['disposition']['forced']}") @@ -747,6 +695,7 @@ def convert(ctx, click.echo(f"subtitle stream {sStream['sub_index']} lang={sStream['tags']['language']} title={sStream['tags']['title']} default={sStream['disposition']['default']} forced={sStream['disposition']['forced']}") + # Find source stream order audioStreamSourceOrder = list(range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO]))) subtitleStreamSourceOrder = list(range(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE]))) @@ -761,130 +710,139 @@ def convert(ctx, subtitleStreamSourceOrder = getModifiedStreamOrder(len(sourceStreamDescriptor[STREAM_TYPE_SUBTITLE]), defaultTargetSubtitleStreams[0]['sub_index']) - click.echo(f"Audio stream source order {audioStreamSourceOrder}") - click.echo(f"Subtitle stream source order {subtitleStreamSourceOrder}") - continue + mappingVideoTokens = ['-map', '0:v:0'] + mappingTokens = mappingVideoTokens.copy() + dispositionTokens = [] - commandTokens = COMMAND_TOKENS + ['-i', sourcePath] + audioTokens = [] - subtitleFileTokens = [] - matchingSubtitles = [] - if context['import_subtitles']: - - subtitles = [a for a in availableFileSubtitleDescriptors if a['season'] == season and a['episode'] == episode] - mSubtitles = sorted(subtitles, key=lambda d: d['stream']) - for sfd in mSubtitles: - subtitleFileTokens += ['-i', sfd['path']] + audioMetadataTokens = [] + for audioStreamIndex in range(len(sourceStreamDescriptor[STREAM_TYPE_AUDIO])): - for streamIndex in range(len(mSubtitles)): - mSubtitles[streamIndex]['forced'] = 1 if forcedSubtitle != -1 and streamIndex == forcedSubtitle else 0 - mSubtitles[streamIndex]['default'] = 1 if defaultSubtitle != -1 and streamIndex == defaultSubtitle else 0 + sourceAudioStreamIndex = audioStreamSourceOrder[audioStreamIndex] + sourceAudioStream = sourceStreamDescriptor[STREAM_TYPE_AUDIO][sourceAudioStreamIndex] - if streamIndex <= len(subtitleTitles) -1: - mSubtitles[streamIndex]['title'] = subtitleTitles[streamIndex] + # Create mapping and ffmpeg options for audio streams + # mappingTokens += ['-map', f"0:a:{sourceAudioStreamIndex['src_sub_index']}"] + mappingTokens += ['-map', f"0:a:{sourceAudioStreamIndex}"] - if defaultSubtitle != -1 and jellyfin: - matchingSubtitles = getReorderedSubstreams(mSubtitles, defaultSubtitle) - else: - matchingSubtitles = mSubtitles + # audioTokens += generateAudioTokens(context, sourceAudioStream['src_sub_index'], sourceAudioStream['layout']) + audioTokens += generateAudioTokens(context, sourceAudioStreamIndex, sourceAudioStream['audio_layout']) + if sourceStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['language'] != targetStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['language']: + audioMetadataTokens += [f"-metadata:s:a:{audioStreamIndex}", f"language={targetStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['language']}"] + if sourceStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['title'] != targetStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['title']: + audioMetadataTokens += [f"-metadata:s:a:{audioStreamIndex}", f"title={targetStreamDescriptor[STREAM_TYPE_AUDIO][audioStreamIndex]['tags']['title']}"] - for q in q_list: - - click.echo(f"\nRunning job {job_index} file={sourcePath} q={q}") - job_index += 1 - - mappingVideoTokens = ['-map', '0:v:0'] - - mappingTokens = mappingVideoTokens.copy() - dispositionTokens = [] - - audioTokens = [] - - - # Reorder audio stream descriptors and create disposition options if default is given per command line option - if defaultAudio == -1: - sourceAudioStreams = audioStreams - else: - for streamIndex in range(len(audioStreams)): - audioStreams[streamIndex]['disposition']['default'] = 1 if streamIndex == defaultAudio else 0 - - sourceAudioStreams = getReorderedSubstreams(audioStreams, defaultAudio) if jellyfin else audioStreams - - dispositionTokens += generateDispositionTokens(sourceAudioStreams) - - # Set forced tag in subtitle descriptor if given per command line option - if forcedSubtitle != -1: - for streamIndex in range(len(subtitleStreams)): - subtitleStreams[streamIndex]['disposition']['forced'] = 1 if streamIndex == forcedSubtitle else 0 - - # Reorder subtitle stream descriptors and create disposition options if default is given per command line option - if defaultSubtitle == -1: - sourceSubtitleStreams = subtitleStreams - else: - for streamIndex in range(len(subtitleStreams)): - subtitleStreams[streamIndex]['disposition']['default'] = 1 if streamIndex == defaultSubtitle else 0 - sourceSubtitleStreams = getReorderedSubstreams(subtitleStreams, defaultSubtitle) if jellyfin else subtitleStreams - dispositionTokens += generateDispositionTokens(sourceSubtitleStreams) + click.echo(f"Audio stream source order {audioStreamSourceOrder}") + click.echo(f"Subtitle stream source order {subtitleStreamSourceOrder}") - audioMetadataTokens = [] - for audioStreamIndex in range(len(sourceAudioStreams)): - - audioStream = sourceAudioStreams[audioStreamIndex] - - # Create mapping and ffmpeg options for audio streams - mappingTokens += ['-map', f"0:a:{audioStream['src_sub_index']}"] - audioTokens += generateAudioTokens(context, audioStream['src_sub_index'], audioStream['layout']) - - if 'tags' in audioStream.keys(): - if 'language' in audioStream['tags'].keys(): - audioMetadataTokens += [f"-metadata:s:a:{audioStreamIndex}", f"language={audioStream['tags']['language']}"] - if 'title' in audioStream['tags'].keys(): - audioMetadataTokens += [f"-metadata:s:a:{audioStreamIndex}", f"title={audioStream['tags']['title']}"] + commandTokens = COMMAND_TOKENS + ['-i', sourcePath] - # Create mapping and ffmpeg options for subtitle streams - subtitleMetadataTokens = [] - if context['import_subtitles']: - - numMatchingSubtitles = len(matchingSubtitles) - - if jellyfin and defaultSubtitle != -1: - subtitleSequence = getModifiedStreamOrder(numMatchingSubtitles, default_subtitle) #! - else: - subtitleSequence = range(numMatchingSubtitles) + subtitleFileTokens = [] + subtitleMetadataTokens = [] - for fileIndex in range(numMatchingSubtitles): +# matchingSubtitles = [] +# if context['import_subtitles']: +# +# subtitles = [a for a in availableFileSubtitleDescriptors if a['season'] == season and a['episode'] == episode] +# mSubtitles = sorted(subtitles, key=lambda d: d['stream']) +# +# for sfd in mSubtitles: +# subtitleFileTokens += ['-i', sfd['path']] +# +# for streamIndex in range(len(mSubtitles)): +# mSubtitles[streamIndex]['forced'] = 1 if forcedSubtitle != -1 and streamIndex == forcedSubtitle else 0 +# mSubtitles[streamIndex]['default'] = 1 if defaultSubtitle != -1 and streamIndex == defaultSubtitle else 0 +# +# if streamIndex <= len(subtitleTitles) -1: +# mSubtitles[streamIndex]['title'] = subtitleTitles[streamIndex] +# +# if defaultSubtitle != -1 and jellyfin: +# matchingSubtitles = getReorderedSubstreams(mSubtitles, defaultSubtitle) +# else: +# matchingSubtitles = mSubtitles - # Create mapping for subtitle streams when imported from files - mappingTokens += ['-map', f"{subtitleSequence[fileIndex]+1}:s:0"] - msg = matchingSubtitles[fileIndex] - subtitleMetadataTokens += [f"-metadata:s:s:{fileIndex}", f"language={msg['language']}"] - if 'title' in matchingSubtitles[fileIndex].keys(): - subtitleMetadataTokens += [f"-metadata:s:s:{fileIndex}", f"title={matchingSubtitles[fileIndex]['title']}"] - else: + for q in q_list: - for subtitleStreamIndex in range(len(sourceSubtitleStreams)): + click.echo(f"\nRunning job {job_index} file={sourcePath} q={q}") + job_index += 1 - subtitleStream = sourceSubtitleStreams[subtitleStreamIndex] - # Create mapping for subtitle streams - mappingTokens += ['-map', f"s:{subtitleStream['src_sub_index']}"] +# # Reorder audio stream descriptors and create disposition options if default is given per command line option +# if defaultAudio == -1: +# sourceAudioStreams = audioStreams +# else: +# for streamIndex in range(len(audioStreams)): +# audioStreams[streamIndex]['disposition']['default'] = 1 if streamIndex == defaultAudio else 0 +# +# sourceAudioStreams = getReorderedSubstreams(audioStreams, defaultAudio) if jellyfin else audioStreams +# +# dispositionTokens += generateDispositionTokens(sourceAudioStreams) +# +# # Set forced tag in subtitle descriptor if given per command line option +# if forcedSubtitle != -1: +# for streamIndex in range(len(subtitleStreams)): +# subtitleStreams[streamIndex]['disposition']['forced'] = 1 if streamIndex == forcedSubtitle else 0 +# +# # Reorder subtitle stream descriptors and create disposition options if default is given per command line option +# if defaultSubtitle == -1: +# sourceSubtitleStreams = subtitleStreams +# else: +# for streamIndex in range(len(subtitleStreams)): +# subtitleStreams[streamIndex]['disposition']['default'] = 1 if streamIndex == defaultSubtitle else 0 +# +# sourceSubtitleStreams = getReorderedSubstreams(subtitleStreams, defaultSubtitle) if jellyfin else subtitleStreams +# +# dispositionTokens += generateDispositionTokens(sourceSubtitleStreams) +# - if 'tags' in subtitleStream.keys(): - if 'language' in subtitleStream['tags'].keys(): - subtitleMetadataTokens += [f"-metadata:s:s:{subtitleStreamIndex}", f"language={subtitleStream['tags']['language']}"] - if 'title' in subtitleStream['tags'].keys(): - subtitleMetadataTokens += [f"-metadata:s:s:{subtitleStreamIndex}", f"title={subtitleStream['tags']['title']}"] + +# # Create mapping and ffmpeg options for subtitle streams + +# if context['import_subtitles']: +# +# numMatchingSubtitles = len(matchingSubtitles) +# +# if jellyfin and defaultSubtitle != -1: +# subtitleSequence = getModifiedStreamOrder(numMatchingSubtitles, default_subtitle) #! +# else: +# subtitleSequence = range(numMatchingSubtitles) +# +# for fileIndex in range(numMatchingSubtitles): +# +# # Create mapping for subtitle streams when imported from files +# mappingTokens += ['-map', f"{subtitleSequence[fileIndex]+1}:s:0"] +# +# msg = matchingSubtitles[fileIndex] +# subtitleMetadataTokens += [f"-metadata:s:s:{fileIndex}", f"language={msg['language']}"] +# if 'title' in matchingSubtitles[fileIndex].keys(): +# subtitleMetadataTokens += [f"-metadata:s:s:{fileIndex}", f"title={matchingSubtitles[fileIndex]['title']}"] +# +# else: +# +# for subtitleStreamIndex in range(len(sourceSubtitleStreams)): +# +# subtitleStream = sourceSubtitleStreams[subtitleStreamIndex] +# +# # Create mapping for subtitle streams +# mappingTokens += ['-map', f"s:{subtitleStream['src_sub_index']}"] +# +# if 'tags' in subtitleStream.keys(): +# if 'language' in subtitleStream['tags'].keys(): +# subtitleMetadataTokens += [f"-metadata:s:s:{subtitleStreamIndex}", f"language={subtitleStream['tags']['language']}"] +# if 'title' in subtitleStream['tags'].keys(): +# subtitleMetadataTokens += [f"-metadata:s:s:{subtitleStreamIndex}", f"title={subtitleStream['tags']['title']}"] # Job specific tokens