Av1an/Startup/setup.py

167 lines
4.1 KiB
Python
Raw Normal View History

2020-06-27 19:21:00 +00:00
#!/bin/env python
2020-06-22 16:32:40 +00:00
2020-07-20 20:15:52 +00:00
import atexit
2020-08-19 07:06:42 +00:00
import os
import shlex
2020-08-19 07:06:42 +00:00
import shutil
import sys
2020-07-06 15:53:25 +00:00
from distutils.spawn import find_executable
2020-06-22 16:32:40 +00:00
from pathlib import Path
2020-07-06 15:53:25 +00:00
2020-06-27 19:21:00 +00:00
from psutil import virtual_memory
2020-09-15 17:36:23 +00:00
from Startup.validate_commands import validate_inputs
2020-09-14 17:45:21 +00:00
from Encoders import ENCODERS
2020-08-29 09:56:48 +00:00
from Av1an.arg_parse import Args
from Av1an.utils import terminate
2020-06-22 16:32:40 +00:00
def set_vmaf(args):
2020-08-29 09:56:48 +00:00
"""
Av1an setup for VMAF
:param args: the Args
"""
if args.vmaf_path:
if not Path(args.vmaf_path).exists():
print(f'No such model: {Path(args.vmaf_path).as_posix()}')
terminate()
2020-06-22 16:32:40 +00:00
if args.vmaf_steps < 4:
print('Target vmaf require more than 3 probes/steps')
terminate()
encoder = ENCODERS[args.encoder]
2020-07-20 20:15:52 +00:00
if args.min_q is None:
args.min_q, _ = encoder.default_q_range
if args.max_q is None:
_, args.max_q = encoder.default_q_range
2020-07-20 20:15:52 +00:00
def check_exes(args: Args):
2020-08-29 09:56:48 +00:00
"""
Checking required executables
:param args: the Args
"""
2020-06-22 16:32:40 +00:00
if not find_executable('ffmpeg'):
print('No ffmpeg')
terminate()
if args.chunk_method in ['vs_ffms2', 'vs_lsmash'] and (not find_executable('vspipe')):
print('vspipe executable not found')
terminate()
def setup_encoder(args: Args):
2020-08-29 09:56:48 +00:00
"""
Settup encoder params and passes
:param args: the Args
"""
encoder = ENCODERS[args.encoder]
# validate encoder settings
settings_valid, error_msg = encoder.is_valid(args)
if not settings_valid:
print(error_msg)
terminate()
if args.passes is None:
args.passes = encoder.default_passes
2020-08-29 09:56:48 +00:00
args.video_params = encoder.default_args if args.video_params is None \
else shlex.split(args.video_params)
validate_inputs(args)
def startup_check(args: Args):
2020-08-29 09:56:48 +00:00
"""
Performing essential checks at startup_check
Set constant values
"""
if sys.version_info < (3, 6):
print('Python 3.6+ required')
sys.exit()
if sys.platform == 'linux':
def restore_term():
os.system("stty sane")
2020-08-19 07:06:42 +00:00
atexit.register(restore_term)
check_exes(args)
set_vmaf(args)
2020-07-20 18:07:01 +00:00
if args.reuse_first_pass and args.encoder != 'aom' and args.split_method != 'aom_keyframes':
2020-08-29 09:56:48 +00:00
print('Reusing the first pass is only supported with \
the aom encoder and aom_keyframes split method.')
2020-07-20 18:07:01 +00:00
terminate()
setup_encoder(args)
2020-07-23 20:57:03 +00:00
# No check because vvc
if args.encoder == 'vvc':
args.no_check = True
2020-08-16 04:20:58 +00:00
if args.encoder == 'svt_vp9' and args.passes == 2:
print("Implicitly changing 2 pass svt-vp9 to 1 pass\n2 pass svt-vp9 isn't supported")
args.passes = 1
args.audio_params = shlex.split(args.audio_params)
args.ffmpeg = shlex.split(args.ffmpeg)
2020-07-23 20:57:03 +00:00
args.pix_format = ['-strict', '-1', '-pix_fmt', args.pix_format]
2020-08-29 09:56:48 +00:00
args.ffmpeg_pipe = [*args.ffmpeg, *args.pix_format,
'-bufsize', '50000K', '-f', 'yuv4mpegpipe', '-']
2020-07-21 19:46:45 +00:00
2020-06-22 16:32:40 +00:00
def determine_resources(encoder, workers):
"""Returns number of workers that machine can handle with selected encoder."""
# If set by user, skip
if workers != 0:
return workers
cpu = os.cpu_count()
ram = round(virtual_memory().total / 2 ** 30)
if encoder in ('aom', 'rav1e', 'vpx'):
2020-08-19 06:41:58 +00:00
workers = round(min(cpu / 2, ram / 1.5))
2020-08-16 04:20:58 +00:00
elif encoder in ('svt_av1', 'svt_vp9', 'x265', 'x264'):
2020-08-19 06:41:58 +00:00
workers = round(min(cpu, ram)) // 8
2020-08-29 09:56:48 +00:00
elif encoder in 'vvc':
2020-07-23 21:59:09 +00:00
workers = round(min(cpu, ram))
# fix if workers round up to 0
if workers == 0:
workers = 1
return workers
2020-06-22 16:32:40 +00:00
def setup(temp: Path, resume):
"""Creating temporally folders when needed."""
# Make temporal directories, and remove them if already presented
if not resume:
if temp.is_dir():
shutil.rmtree(temp)
(temp / 'split').mkdir(parents=True, exist_ok=True)
(temp / 'encode').mkdir(exist_ok=True)
2020-06-22 20:11:07 +00:00
2020-08-29 09:56:48 +00:00
def outputs_filenames(args: Args):
"""
Set output filename
:param args: the Args
"""
suffix = '.mkv'
args.output_file = Path(args.output_file).with_suffix(suffix) if args.output_file \
else Path(f'{args.input.stem}_{args.encoder}{suffix}')