feat: new prompts and ffmpeg commands (#21)

* Version 1.3

* Back changes and fixed bug

* README update
This commit is contained in:
Kyrch
2023-06-08 00:45:45 -03:00
committed by GitHub
parent 071ec5d035
commit cf4580091f
6 changed files with 53 additions and 19 deletions
+2 -4
View File
@@ -25,15 +25,13 @@ Ideally we are iterating over a combination of filters and settings, picking the
`--mode 1` generates commands from input files in the current directory.
The user will be prompted for values that are not determined programmatically, such as inclusion/exclusion of a source file candidate, start time, end time and output file name.
The user will be prompted for values that are not determined programmatically, such as inclusion/exclusion of a source file candidate, start time, end time, output file name and new audio filters.
`--mode 2` executes commands from file in the current directory line-by-line.
By default, the program looks for a file named `commands.txt` in the current directory. This file name can be specified by the `--file` argument.
`--mode 3` generates commands from input files in the current directory and executes the commands sequentially without writing to file.
The `--file` argument will be ignored in this case.
`--mode 3` generates commands from input files in the current directory and executes the commands sequentially.
**File**
+9 -10
View File
@@ -27,7 +27,7 @@ def main():
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'
'3: Unused')
'3: Name of file commands are written to (default: commands.txt)')
parser.add_argument('--configfile', nargs='?', default='batch_encoder.ini', type=configfile_arg_type,
help='Name of config file (default: batch_encoder.ini)\n'
'If the file does not exist, default configuration will be written\n'
@@ -113,13 +113,19 @@ def main():
commands = output_list
# Write commands to file
if args.mode == 1:
# Write commands to file
logging.info(f'Writing {len(commands)} commands to file \'{args.file}\'...')
with open(args.file, mode='w', encoding='utf8') as f:
for command in commands:
f.write(command + '\n')
# Execute commands in memory and write commands to file if requested
if args.mode == 3:
logging.info(f'Executing {len(commands)} commands...')
for command in commands:
subprocess.call(command, shell=True)
# Read and execute commands from file
if args.mode == 2:
if not os.path.isfile(args.file):
@@ -135,13 +141,6 @@ def main():
for command in commands:
subprocess.call(command, shell=True)
# Execute commands in memory
if args.mode == 3:
logging.info(f'Executing {len(commands)} commands...')
for command in commands:
subprocess.call(command, shell=True)
if __name__ == '__main__':
try:
main()
+9
View File
@@ -104,6 +104,12 @@ class EncodeWebM:
limit_size = max_allowed_size / 8
return str(round(limit_size))
# Command to preview a seek
def preview_seek(self, webm_filename=''):
return f'ffmpeg {self.seek.get_seek_string()} ' \
f'{self.get_audio_filters()} ' \
f'-vcodec copy -c:a aac -b:a 128k -sn -f mp4 {webm_filename}.mp4'
# First-pass encode
def get_first_pass(self, encoding_mode, crf=None, threads=4):
@@ -137,6 +143,7 @@ class EncodeWebM:
audio_filters = []
self.source_file.apply_audio_resampling(audio_filters)
audio_filters.append(self.loudnorm_filter.get_normalization_filter())
audio_filters.append(self.seek.new_audio_filter) if self.seek.new_audio_filter.strip() != '' else None
return '-af ' + ','.join(audio_filters)
# Build video filtergraph for encodes
@@ -177,6 +184,8 @@ class EncodeWebM:
f'crfs: \'{encoding_config.crfs}\', '
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()))
for encoding_mode in encoding_config.encoding_modes:
if BitrateMode.CBR.name == encoding_mode.upper():
+2 -1
View File
@@ -1,10 +1,11 @@
# The seek information for our encode
class Seek:
def __init__(self, source_file, ss, to, output_name):
def __init__(self, source_file, ss, to, output_name, new_audio_filter):
self.source_file = source_file
self.ss = ss
self.to = to
self.output_name = output_name
self.new_audio_filter = new_audio_filter
# The seek string arguments for our encode
def get_seek_string(self):
+30 -3
View File
@@ -15,11 +15,15 @@ class SeekCollector:
# Examples: Tamayura-OP1, PlanetWith-ED1v2
filename_pattern = re.compile('^[a-zA-Z0-9\-]+$')
# List for all output_files
all_output_names = []
def __init__(self, source_file):
self.source_file = source_file
self.start_positions = SeekCollector.prompt_time('Start time(s): ')
self.end_positions = SeekCollector.prompt_time('End time(s): ')
self.output_names = SeekCollector.prompt_output_name()
self.new_audio_filters = SeekCollector.prompt_new_audio_filters()
# Prompt the user for our list of starting/ending positions of our WebMs
# For starting positions, a blank input value is the 0 position of the source file
@@ -50,6 +54,12 @@ class SeekCollector:
break
if not invalid_name:
return filenames
# Prompt the user for ours list of audio filters of ours WebMs
@staticmethod
def prompt_new_audio_filters():
new_audio_filters = input('Audio Filter(s): ').split(',,')
return new_audio_filters
# Integrity Test 1: Our lists should be of equal length
def is_length_consistent(self):
@@ -99,6 +109,16 @@ class SeekCollector:
return len(set(self.output_names)) == len(self.output_names)
# Integrity Test 5: Unique output names in other source
def is_unique_output_names_other_source(self):
self.all_output_names.extend(self.output_names)
logging.debug(
f'[SeekCollector.is_unique_output_names_other_source] len(set): \'{len(set(self.all_output_names))}\', '
f'len: \'{len(self.all_output_names)}\'')
return len(set(self.all_output_names)) == len(self.all_output_names)
# Integrity Tests with feedback
def is_valid(self):
is_valid = True
@@ -119,15 +139,22 @@ class SeekCollector:
is_valid = False
logging.error('Output Names are not unique')
if not self.is_unique_output_names_other_source():
is_valid = False
logging.error('Output Name is already being used')
if not is_valid:
self.all_output_names.pop()
return is_valid
# Our list of positions, validated if called after is_valid
def get_seek_list(self):
seek_list = []
for start_position, end_position, output_name in zip(self.start_positions, self.end_positions,
self.output_names):
seek = Seek(self.source_file, start_position, end_position, output_name)
for start_position, end_position, output_name, new_audio_filter in zip(self.start_positions, self.end_positions,
self.output_names, self.new_audio_filters):
seek = Seek(self.source_file, start_position, end_position, output_name, new_audio_filter)
seek_list.append(seek)
return seek_list
+1 -1
View File
@@ -7,7 +7,7 @@ with open('README.md') as f:
setup(
name='animethemes-batch-encoder',
version='1.2',
version='1.3',
author='AnimeThemes',
author_email='admin@animethemes.moe',
url='https://github.com/AnimeThemes/animethemes-batch-encoder',