diff --git a/README.md b/README.md index e2472d9..22070a6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Ideally we are iterating over a combination of filters and settings, picking the ### Usage - python -m beta_batch_encoder [-h] [--generate | -g] [--execute | -e] [--file [FILE]] [--configfile [CONFIGFILE]] --loglevel [{debug,info,error}] + python -m beta_batch_encoder [-h] [--generate | -g] [--execute | -e] [--custom | -c] [--file [FILE]] [--configfile [CONFIGFILE]] --loglevel [{debug,info,error}] **Mode** @@ -35,6 +35,10 @@ By default, the program looks for a file named `commands.txt` in the current dir `None` will give modes options to run. +**Custom** + +`--custom` customizes options like Create Preview, Limit Size Enable, CRFs and Encoding Modes for each output file. Default configs are specified in the `--file` argument. + **File** The file that commands are written to or read from. @@ -77,6 +81,8 @@ Available bitrate control modes are: `AlternateSourceEnable` is a flag for alternate command lines between source files. Default is False. +`CreatePreview` is a flag for create a command line to preview seeks. Default is False. + `IncludeUnfiltered` is a flag for including or excluding an encode without video filters for each bitrate control mode and CRF pairing. Default is True. `VideoFilters` is a configuration item list used for named video filtergraphs for each bitrate control mode and CRF pairing. diff --git a/beta_batch_encoder/__main__.py b/beta_batch_encoder/__main__.py index b001c65..b7e2b78 100644 --- a/beta_batch_encoder/__main__.py +++ b/beta_batch_encoder/__main__.py @@ -9,6 +9,7 @@ from appdirs import AppDirs import argparse import configparser +import copy import logging import os import shutil @@ -21,8 +22,9 @@ def main(): parser = argparse.ArgumentParser(prog='beta_batch_encoder', description='Generate/Execute FFmpeg commands for files in acting directory', formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('--generate', '-g', action='store_true',help='Generate commands and write to file') + parser.add_argument('--generate', '-g', action='store_true', help='Generate commands and write to file') parser.add_argument('--execute', '-e', action='store_true', help='Execute commands from file') + parser.add_argument('--custom', '-c', action='store_true', help='Customize some options for each seek') parser.add_argument('--file', nargs='?', default='commands.txt', type=commandfile_arg_type, help='1: Name of file commands are written to (default: commands.txt)\n' '2: Name of file commands are executed from (default: commands.txt)\n' @@ -59,6 +61,7 @@ def main(): EncodingConfig.config_threads: EncodingConfig.default_threads, EncodingConfig.config_limit_size_enable: EncodingConfig.default_limit_size_enable, EncodingConfig.config_alternate_source_files: EncodingConfig.default_alternate_source_files, + EncodingConfig.create_preview: EncodingConfig.default_create_preview, EncodingConfig.config_include_unfiltered: EncodingConfig.default_include_unfiltered, EncodingConfig.config_default_video_stream: '', EncodingConfig.config_default_audio_stream: ''} @@ -108,10 +111,16 @@ def main(): is_collector_valid = seek_collector.is_valid() for seek in seek_collector.get_seek_list(): + new_encoding_config = copy.copy(encoding_config) + if args.custom: + print(f'\033[92mOutput Name: {seek.output_name}\033[0m') + new_encoding_config = Interface.custom_options(new_encoding_config) + logging.info(f'Generating commands with seek ss: \'{seek.ss}\', to: \'{seek.to}\'') encode_webm = EncodeWebM(file_value, seek) - load_commands = encode_webm.get_commands(encoding_config) + load_commands = encode_webm.get_commands(new_encoding_config) commands = commands + load_commands + except KeyboardInterrupt: logging.info(f'Exiting from inclusion of file \'{file}\' after keyboard interrupt') diff --git a/beta_batch_encoder/_encode_webm.py b/beta_batch_encoder/_encode_webm.py index 1a326bf..6de574b 100644 --- a/beta_batch_encoder/_encode_webm.py +++ b/beta_batch_encoder/_encode_webm.py @@ -185,7 +185,8 @@ class EncodeWebM: f'include_unfiltered: \'{encoding_config.include_unfiltered}\', ' f'video_filters: \'{encoding_config.video_filters}\'') - file_commands.append(self.preview_seek(webm_filename=self.get_webm_filename())) + if encoding_config.create_preview: + file_commands.append(self.preview_seek(webm_filename=self.get_webm_filename())) for encoding_mode in encoding_config.encoding_modes: if BitrateMode.CBR.name == encoding_mode.upper(): diff --git a/beta_batch_encoder/_encoding_config.py b/beta_batch_encoder/_encoding_config.py index e1ff099..c947c5f 100644 --- a/beta_batch_encoder/_encoding_config.py +++ b/beta_batch_encoder/_encoding_config.py @@ -9,6 +9,7 @@ class EncodingConfig: config_threads = 'Threads' config_limit_size_enable = 'LimitSizeEnable' config_alternate_source_files = 'AlternateSourceFiles' + config_create_preview = 'CreatePreview' config_include_unfiltered = 'IncludeUnfiltered' # Default Config keys @@ -22,13 +23,14 @@ class EncodingConfig: default_threads = '4' default_limit_size_enable = True default_alternate_source_files = False + default_create_preview = False default_include_unfiltered = True default_video_filters = {'filtered': 'hqdn3d=0:0:3:3,gradfun,unsharp', 'lightdenoise': 'hqdn3d=0:0:3:3', 'heavydenoise': 'hqdn3d=1.5:1.5:6:6', 'unsharp': 'unsharp'} - def __init__(self, allowed_filetypes, encoding_modes, crfs, threads, limit_size_enable, alternate_source_files, include_unfiltered, video_filters, default_video_stream, + def __init__(self, allowed_filetypes, encoding_modes, crfs, threads, limit_size_enable, alternate_source_files, create_preview, include_unfiltered, video_filters, default_video_stream, default_audio_stream): self.allowed_filetypes = allowed_filetypes self.encoding_modes = encoding_modes @@ -36,6 +38,7 @@ class EncodingConfig: self.threads = threads self.limit_size_enable = limit_size_enable self.alternate_source_files = alternate_source_files + self.create_preview = create_preview self.include_unfiltered = include_unfiltered self.video_filters = video_filters self.default_video_stream = default_video_stream @@ -52,6 +55,7 @@ class EncodingConfig: EncodingConfig.default_threads) limit_size_enable = config.getboolean('Encoding', EncodingConfig.config_limit_size_enable, fallback=EncodingConfig.default_limit_size_enable) alternate_source_files = config.getboolean('Encoding', EncodingConfig.config_alternate_source_files, fallback=EncodingConfig.default_alternate_source_files) + create_preview = config.getboolean('Encoding', EncodingConfig.config_create_preview, fallback=EncodingConfig.default_create_preview) include_unfiltered = config.getboolean('Encoding', EncodingConfig.config_include_unfiltered, fallback=EncodingConfig.default_include_unfiltered) video_filters = config.items('VideoFilters', EncodingConfig.default_video_filters) @@ -59,7 +63,7 @@ class EncodingConfig: default_video_stream = config['Encoding'].get(EncodingConfig.config_default_video_stream) default_audio_stream = config['Encoding'].get(EncodingConfig.config_default_audio_stream) - return cls(allowed_filetypes, encoding_modes, crfs, threads, limit_size_enable, alternate_source_files, include_unfiltered, video_filters, default_video_stream, + return cls(allowed_filetypes, encoding_modes, crfs, threads, limit_size_enable, alternate_source_files, create_preview, include_unfiltered, video_filters, default_video_stream, default_audio_stream) def get_default_stream(self, stream_type): diff --git a/beta_batch_encoder/_interface.py b/beta_batch_encoder/_interface.py index 8e4987c..d54a4ce 100644 --- a/beta_batch_encoder/_interface.py +++ b/beta_batch_encoder/_interface.py @@ -8,22 +8,17 @@ class Interface: # Prompt the mode options to run to the user def choose_mode(): - modes = { - 'Generate commands': 1, - 'Execute commands': 2, - 'Generate and execute commands': 3 - } - - question = [inquirer.List('mode', message='Mode (Enter)', choices=list(modes.keys()))] + modes = [('Generate commands', 1), ('Execute commands', 2), ('Generate and execute commands', 3)] + question = [inquirer.List('mode', message='Mode (Enter)', choices=modes)] answer = inquirer.prompt(question) logging.debug(f'[Interface.choose_mode] answer["mode"]: \'{answer["mode"]}\'') - return modes[answer['mode']] + return answer['mode'] # Prompt the source files to choose def choose_source_files(source_files): - question = [inquirer.Checkbox('source_files', message='Source Files (Space)', choices=source_files)] + question = [inquirer.Checkbox('source_files', message='Source Files (Space to select)', choices=source_files)] answer = inquirer.prompt(question) logging.debug(f'[Interface.choose_source_files] answer["source_files"]: \'{answer["source_files"]}\'') @@ -113,4 +108,38 @@ class Interface: f'audio_filters["Custom"]: \'{audio_filters["Custom"]}\'' ) - return ','.join(audio_filters_list) \ No newline at end of file + return ','.join(audio_filters_list) + + # Prompt custom options if requested + def custom_options(encoding_config): + create_preview = encoding_config.create_preview + limit_size_enable = encoding_config.limit_size_enable + crfs = encoding_config.crfs + encoding_modes = encoding_config.encoding_modes + + validate_crfs = lambda _, x: all(y.strip().isdigit() for y in x.split(',')) + validate_encoding_modes = lambda _, x: all(y.strip().upper() in ['VBR', 'CBR', 'CQ'] for y in x.split(',')) + + questions = [ + inquirer.Confirm('create_preview', message=f'Create Preview?', default=create_preview), + inquirer.Confirm('limit_size_enable', message=f'Limit Size Enable?', default=limit_size_enable), + inquirer.Text('crfs', message='CRFs', default=','.join(crfs), validate=validate_crfs), + inquirer.Text('encoding_modes', message='Encoding Modes', default=','.join(encoding_modes), validate=validate_encoding_modes) + ] + + answer = inquirer.prompt(questions) + + encoding_config.create_preview = answer['create_preview'] + encoding_config.limit_size_enable = answer['limit_size_enable'] + encoding_config.crfs = answer['crfs'].split(',') + encoding_config.encoding_modes = answer['encoding_modes'].split(',') + + logging.debug( + f'[Interface.custom_options] ' + f'encoding_config.create_preview: \'{encoding_config.create_preview}\', ' + f'encoding_config.limit_size_enable: \'{encoding_config.create_preview}\', ' + f'encoding_config.crfs: \'{encoding_config.crfs}\', ' + f'encoding_config.encoding_modes: \'{encoding_config.encoding_modes}\'' + ) + + return encoding_config \ No newline at end of file diff --git a/setup.py b/setup.py index 74be7a7..39e49c8 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ with open('README.md') as f: setup( name='animethemes-beta-batch-encoder', - version='1.1', + version='1.2', author='AnimeThemes', author_email='admin@animethemes.moe', url='https://github.com/AnimeThemes/animethemes-batch-encoder', @@ -31,5 +31,6 @@ setup( python_requires='>=3.6', install_requires=[ 'appdirs', + 'inquirer' ], )