From e7426398ee171327b8a6cbd1a1ca1b709d5ab6e7 Mon Sep 17 00:00:00 2001 From: Javanaut Date: Thu, 12 Sep 2024 13:52:49 +0000 Subject: [PATCH] inc --- bin/ffx.py | 95 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/bin/ffx.py b/bin/ffx.py index 52300d5..88fc807 100755 --- a/bin/ffx.py +++ b/bin/ffx.py @@ -1,6 +1,6 @@ #! /usr/bin/python3 -import os, sys, subprocess, json, click, time +import os, sys, subprocess, json, click, time, re from textual.app import App, ComposeResult from textual.screen import Screen @@ -50,6 +50,9 @@ STREAM_LAYOUT_5_1 = '5.1(side)' STREAM_LAYOUT_STEREO = 'stereo' STREAM_LAYOUT_6CH = '6ch' +SEASON_EPISODE_INDICATOR_MATCH = '([sS][0-9]+)([eE][0-9]+)' +SEASON_INDICATOR_MATCH = '([sS][0-9]+)' +EPISODE_INDICATOR_MATCH = '([eE][0-9]+)' class DashboardScreen(Screen): @@ -364,8 +367,10 @@ def streams(filename): @click.option("-c", "--clear-metadata", is_flag=True, default=False) @click.option("-d", "--denoise", is_flag=True, default=False) +@click.option("-o", "--output-directory", type=str, default='') -def convert(ctx, paths, label, video_encoder, quality, preset, stereo_bitrate, ac3_bitrate, dts_bitrate, crop, clear_metadata, default_subtitle, forced_audio, default_audio, denoise): + +def convert(ctx, paths, label, video_encoder, quality, preset, stereo_bitrate, ac3_bitrate, dts_bitrate, crop, clear_metadata, default_subtitle, forced_audio, default_audio, denoise, output_directory): """Batch conversion of audiovideo files in format suitable for web playback, e.g. jellyfin Files found under PATHS will be converted according to parameters. @@ -377,67 +382,75 @@ def convert(ctx, paths, label, video_encoder, quality, preset, stereo_bitrate, a context = ctx.obj - for sourcePath in paths: + click.echo(f"\nVideo encoder: {video_encoder}") - if not os.path.isfile(sourcePath): - click.echo(f"There is no file with path {sourcePath}, skipping ...") + qualityTokens = quality.split(',') + q_list = [q for q in qualityTokens if q.isnumeric()] - sourceDirectory = os.path.dirname(sourcePath) - sourceFilename = os.path.basename(sourcePath) - sourcePathTokens = sourceFilename.split('.') + click.echo(f"Qualities: {q_list}") - if sourcePathTokens[-1] in FILE_EXTENSIONS: - sourceFileBasename = '.'.join(sourcePathTokens[:-1]) - sourceFilenameExtension = sourcePathTokens[-1] - else: - sourceFileBasename = sourceFilename - sourceFilenameExtension = '' - - click.echo(f"dir={sourceDirectory} base={sourceFileBasename} ext={sourceFilenameExtension}") + + ctx.obj['bitrates'] = {} + ctx.obj['bitrates']['stereo'] = str(stereo_bitrate) if str(stereo_bitrate).endswith('k') else f"{stereo_bitrate}k" + ctx.obj['bitrates']['ac3'] = str(ac3_bitrate) if str(ac3_bitrate).endswith('k') else f"{ac3_bitrate}k" + ctx.obj['bitrates']['dts'] = str(dts_bitrate) if str(dts_bitrate).endswith('k') else f"{dts_bitrate}k" - #click.echo(f"src: {sourcePath} tgt: {targetFilename}") + click.echo(f"Stereo bitrate: {ctx.obj['bitrates']['stereo']}") + click.echo(f"AC3 bitrate: {ctx.obj['bitrates']['ac3']}") + click.echo(f"DTS bitrate: {ctx.obj['bitrates']['dts']}") + ctx.obj['perform_crop'] = (crop != 'none') - #click.echo(f"ve={video_encoder}") + if ctx.obj['perform_crop']: + cropTokens = crop.split(',') - #qualityTokens = quality.split(',') + if cropTokens and len(cropTokens) == 2: - #q_list = [q for q in qualityTokens if q.isnumeric()] + ctx.obj['crop_start'], ctx.obj['crop_length'] = crop.split(',') + else: + ctx.obj['crop_start'] = DEFAULT_CROP_START + ctx.obj['crop_length'] = DEFAULT_CROP_LENGTH - #click.echo(q_list) + click.echo(f"crop start={ctx.obj['crop_start']} length={ctx.obj['crop_length']}") - #ctx.obj['bitrates'] = {} - #ctx.obj['bitrates']['stereo'] = str(stereo_bitrate) if str(stereo_bitrate).endswith('k') else f"{stereo_bitrate}k" - #ctx.obj['bitrates']['ac3'] = str(ac3_bitrate) if str(ac3_bitrate).endswith('k') else f"{ac3_bitrate}k" - #ctx.obj['bitrates']['dts'] = str(dts_bitrate) if str(dts_bitrate).endswith('k') else f"{dts_bitrate}k" + click.echo(f"\nRunning {len(paths) * len(q_list)} jobs") - #click.echo(f"a={ctx.obj['bitrates']['stereo']}") - #click.echo(f"ac3={ctx.obj['bitrates']['ac3']}") - #click.echo(f"dts={ctx.obj['bitrates']['dts']}") + + se_match = re.compile(SEASON_EPISODE_INDICATOR_MATCH) + s_match = re.compile(SEASON_INDICATOR_MATCH) + e_match = re.compile(EPISODE_INDICATOR_MATCH) - #performCrop = (crop != 'none') + for sourcePath in paths: - #if performCrop: + if not os.path.isfile(sourcePath): + click.echo(f"There is no file with path {sourcePath}, skipping ...") + continue - #cropTokens = crop.split(',') + sourceDirectory = os.path.dirname(sourcePath) + sourceFilename = os.path.basename(sourcePath) + sourcePathTokens = sourceFilename.split('.') - #if cropTokens and len(cropTokens) == 2: + if sourcePathTokens[-1] in FILE_EXTENSIONS: + sourceFileBasename = '.'.join(sourcePathTokens[:-1]) + sourceFilenameExtension = sourcePathTokens[-1] + else: + sourceFileBasename = sourceFilename + sourceFilenameExtension = '' - #cropStart, cropLength = crop.split(',') - #else: - #cropStart = DEFAULT_CROP_START - #cropLength = DEFAULT_CROP_LENGTH + #click.echo(f"dir={sourceDirectory} base={sourceFileBasename} ext={sourceFilenameExtension}") - #click.echo(f"crop start={cropStart} length={cropLength}") + click.echo(f"\nProcessing file {sourcePath}") + se_result = se_match.search(sourceFilename) + s_result = s_match.search(sourceFilename) + e_result = e_match.search(sourceFilename) - #click.echo(f"\nRunning {len(q_list)} jobs") #streamDescriptor = getStreamDescriptor(sourcePath) @@ -522,9 +535,11 @@ def convert(ctx, paths, label, video_encoder, quality, preset, stereo_bitrate, a #executeProcess(commandSequence2) - app = ModesApp(ctx.obj) - app.run() + #app = ModesApp(ctx.obj) + #app.run() + #click.confirm('Warning! This file is not compliant to the defined source schema! Do you want to continue?', abort=True) + click.echo('\nDONE\n') endTime = time.perf_counter()