def call_vmaf(chunk: Chunk, encoded: Path, n_threads, model, res, fl_path: Path = None, vmaf_filter=None, vmaf_rate=0): cmd = '' # settings model path mod = f":model_path={model}" if model else '' # limiting amount of threads for calculation n_threads = f':n_threads={n_threads}' if n_threads else '' if fl_path is None: fl_path = chunk.fake_input_path.with_name( encoded.stem).with_suffix('.json') fl = fl_path.as_posix() filter = vmaf_filter + ',' if vmaf_filter else '' # For vmaf calculation both source and encoded segment scaled to 1080 # Also it's required to use -r before both files of vmaf calculation to avoid errors cmd_in = ('ffmpeg', '-loglevel', 'info', '-y', '-thread_queue_size', '1024', '-hide_banner', '-r', '60', '-i', encoded.as_posix(), '-r', '60', '-i', '-') filter_complex = ('-filter_complex', ) # Change framerate of comparison to framerate of probe select_frames = f"select=not(mod(n\\,{vmaf_rate}))," if vmaf_rate != 0 else '' distorted = f'[0:v]{select_frames}scale={res}:flags=bicubic:\ force_original_aspect_ratio=decrease,setpts=PTS-STARTPTS[distorted];' ref = fr'[1:v]{select_frames}{filter}scale={res}:flags=bicubic:'\ 'force_original_aspect_ratio=decrease,setpts=PTS-STARTPTS[ref];' vmaf_filter = f"[distorted][ref]libvmaf=log_fmt='json':eof_action=endall:\ log_path={shlex.quote(fl)}{mod}{n_threads}" cmd_out = ('-f', 'null', '-') cmd = (*cmd_in, *filter_complex, distorted + ref + vmaf_filter, *cmd_out) ffmpeg_gen_pipe = subprocess.Popen(chunk.ffmpeg_gen_cmd, stdout=PIPE, stderr=STDOUT) pipe = subprocess.Popen(cmd, stdin=ffmpeg_gen_pipe.stdout, stdout=PIPE, stderr=STDOUT, universal_newlines=True) process_pipe(pipe) return fl_path
def per_frame_probe(q_list, q, chunk, project): qfile = chunk.make_q_file(q_list) cmd = per_frame_probe_cmd(chunk, q, project.ffmpeg_pipe, project.encoder, 1, qfile) pipe = make_pipes(chunk.ffmpeg_gen_cmd, cmd) process_pipe(pipe, chunk) fl = call_vmaf(chunk, gen_probes_names(chunk, q), project.n_threads, project.vmaf_path, project.vmaf_res, vmaf_filter=project.vmaf_filter, vmaf_rate=1) jsn = read_json(fl) vmafs = [x['metrics']['vmaf'] for x in jsn['frames']] return vmafs
def vmaf_probe(chunk: Chunk, q, args: Project, probing_rate): """ Calculates vmaf and returns path to json file :param chunk: the Chunk :param q: Value to make probe :param args: the Project :return : path to json file with vmaf scores """ cmd = probe_cmd(chunk, q, args.ffmpeg_pipe, args.encoder, probing_rate) pipe = make_pipes(chunk.ffmpeg_gen_cmd, cmd) process_pipe(pipe, chunk) file = call_vmaf(chunk, gen_probes_names(chunk, q), args.n_threads, args.vmaf_path, args.vmaf_res, vmaf_filter=args.vmaf_filter, vmaf_rate=probing_rate) return file
def vmaf_probe(chunk: Chunk, q, args: Args): """ Make encoding probe to get VMAF that Q returns :param chunk: the Chunk :param q: Value to make probe :param args: the Args :return : """ cmd = probe_cmd(chunk, q, args.ffmpeg_pipe, args.encoder, args.vmaf_rate) pipe = make_pipes(chunk.ffmpeg_gen_cmd, cmd) process_pipe(pipe) file = call_vmaf(chunk, gen_probes_names(chunk, q), args.n_threads, args.vmaf_path, args.vmaf_res, vmaf_filter=args.vmaf_filter, vmaf_rate=args.vmaf_rate) score = read_vmaf_json(file, 20) return score