def startup(args: Args, chunk_queue: List[Chunk]): """ If resuming, open done file and get file properties from there else get file properties and """ # TODO: move this out and pass in total frames and initial frames done_path = args.temp / 'done.json' if args.resume and done_path.exists(): log('Resuming...\n') with open(done_path) as done_file: data = json.load(done_file) total = data['total'] done = len(data['done']) initial = sum(data['done'].values()) log(f'Resumed with {done} encoded clips done\n\n') else: initial = 0 total = frame_probe_cv2(args.input) if total < 1: total = frame_probe(args.input) d = {'total': total, 'done': {}} with open(done_path, 'w') as done_file: json.dump(d, done_file) clips = len(chunk_queue) args.workers = min(args.workers, clips) print(f'\rQueue: {clips} Workers: {args.workers} Passes: {args.passes}\n' f'Params: {" ".join(args.video_params)}') counter = Manager().Counter(total, initial) args.counter = counter
def outputs_filenames(args: Args): """ Set output filename :param args: the Args """ suffix = '.mkv' args.output_file = Path(f'{args.output_file}{suffix}') if args.output_file \ else Path(f'{args.input.stem}_av1{suffix}')
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}')
def setup_encoder(args: Args): """ 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 args.video_params = encoder.default_args if args.video_params is None \ else shlex.split(args.video_params)
def encode_file(args: Args): """ Encodes a single video file on the local machine. :param args: The args for this encode :return: None """ outputs_filenames(args) done_path = args.temp / 'done.json' resuming = args.resume and done_path.exists() # set up temp dir and logging setup(args.temp, args.resume) set_log(args.logging, args.temp) # find split locations split_locations = split_routine(args, resuming) # Applying extra splits if args.extra_split: split_locations = extra_splits(args, split_locations) # create a chunk queue chunk_queue = load_or_gen_chunk_queue(args, resuming, split_locations) # things that need to be done only the first time if not resuming: extract_audio(args.input, args.temp, args.audio_params) if args.reuse_first_pass: segment_first_pass(args.temp, split_locations) # do encoding loop args.workers = determine_resources(args.encoder, args.workers) startup(args, chunk_queue) encoding_loop(args, chunk_queue) # concat concat_routine(args) if args.vmaf or args.vmaf_plots: plot_vmaf(args.input, args.output_file, args, args.vmaf_path, args.vmaf_res) # Delete temp folders if not args.keep: shutil.rmtree(args.temp)
def startup_check(args: Args): """ 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") atexit.register(restore_term) check_exes(args) set_vmaf(args) if args.reuse_first_pass and args.encoder != 'aom' and args.split_method != 'aom_keyframes': print('Reusing the first pass is only supported with \ the aom encoder and aom_keyframes split method.') terminate() setup_encoder(args) # No check because vvc if args.encoder == 'vvc': args.no_check = True 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) args.pix_format = ['-strict', '-1', '-pix_fmt', args.pix_format] args.ffmpeg_pipe = [ *args.ffmpeg, *args.pix_format, '-bufsize', '50000K', '-f', 'yuv4mpegpipe', '-' ]
def __init__(self): parser = Args() self.args = parser.get_project()