コード例 #1
0
    def run_ffmpeg_command(self):
        # wrapper for 'ffmpeg-progress-yield'
        ff = FfmpegProgress(self.cmd, dry_run=self.dry)
        for progress in ff.run_command_with_progress():
            yield progress

        self.output = ff.stderr
コード例 #2
0
ファイル: test.py プロジェクト: slhck/ffmpeg-progress-yield
 def test_library(self):
     cmd = [
         "ffmpeg",
         "-i",
         "test/test.mp4",
         "-c:v",
         "libx264",
         "-vf",
         "scale=1920x1080",
         "-preset",
         "fast",
         "-f",
         "null",
         "/dev/null",
     ]
     ff = FfmpegProgress(cmd)
     for progress in ff.run_command_with_progress():
         print(f"{progress}/100")
コード例 #3
0
    def _run_ffmpeg_command(self, filter_chains=[], desc=""):
        """
        Run the ffmpeg command to get the quality metrics.
        The filter chains must be specified manually.
        'desc' can be a human readable description for the progress bar.
        """
        if not self.framerate:
            ref_framerate, dist_framerate = self._get_framerates()
        else:
            ref_framerate = self.framerate
            dist_framerate = self.framerate

        cmd = [
            "ffmpeg",
            "-nostdin",
            "-nostats",
            "-y",
            "-threads",
            str(self.threads),
            "-r",
            str(ref_framerate),
            "-i",
            self.ref,
            "-r",
            str(dist_framerate),
            "-i",
            self.dist,
            "-filter_complex",
            ";".join(filter_chains),
            "-an",
            "-f",
            "null",
            NUL,
        ]

        if self.progress:
            ff = FfmpegProgress(cmd, self.dry_run)
            with tqdm(total=100, position=1, desc=desc) as pbar:
                for progress in ff.run_command_with_progress():
                    pbar.update(progress - pbar.n)
            return ff.stderr
        else:
            _, stderr = run_command(cmd, self.dry_run, self.verbose)
            return stderr
コード例 #4
0
    def getVmaf(self,
                log_path=None,
                model='HD',
                subsample=1,
                output_fmt='json',
                threads=0,
                print_progress=False,
                end_sync=False,
                features=None,
                cambi_heatmap=False):
        main = self.main.lastOutputID
        ref = self.ref.lastOutputID
        if output_fmt == 'xml':
            log_fmt = "xml"
            if log_path == None:
                log_path = os.path.splitext(
                    self.main.videoSrc)[0] + '_vmaf.xml'
        else:
            log_fmt = "json"
            if log_path == None:
                log_path = os.path.splitext(
                    self.main.videoSrc)[0] + '_vmaf.json'
        self.vmafpath = log_path

        self.vmaf_cambi_heatmap_path = os.path.splitext(
            self.main.videoSrc)[0] + '_cambi_heatmap'

        if model == 'HD':
            model_hd = f'version={HD_MODEL_VERSION}\\\\:name={HD_MODEL_NAME}|version={HD_NEG_MODEL_VERSION}\\\\:name={HD_NEG_MODEL_NAME}|version={HD_PHONE_MODEL_VERSION}\\\\:name={HD_PHONE_MODEL_NAME}\\\\:enable_transform=true'
            model = model_hd
        elif model == '4K':
            model_4k = f'version={_4K_MODEL_VERSION}\\\\:name={_4K_MODEL_NAME}'
            model = model_4k
        if threads == 0:
            threads = os.cpu_count()
        if end_sync:
            shortest = 1
        else:
            shortest = 0

        if not features:
            self.vmafFilter = [
                f'[{main}][{ref}]libvmaf=log_fmt={log_fmt}:model={model}:n_subsample={subsample}:log_path={log_path}:n_threads={threads}:shortest={shortest}'
            ]

        elif features and not cambi_heatmap:
            self.vmafFilter = [
                f'[{main}][{ref}]libvmaf=log_fmt={log_fmt}:model={model}:n_subsample={subsample}:log_path={log_path}:n_threads={threads}:shortest={shortest}:feature={features}'
            ]

        elif features and cambi_heatmap:
            self.vmafFilter = [
                f'[{main}][{ref}]libvmaf=log_fmt={log_fmt}:model={model}:n_subsample={subsample}:log_path={log_path}:n_threads={threads}:shortest={shortest}:feature={features}\\\\:heatmaps_path={self.vmaf_cambi_heatmap_path}'
            ]

        self._commit()
        if self.loglevel == "verbose":
            print(self.cmd, flush=True)

        if print_progress:
            cmd_progress = shlex.split(self.cmd)
            process = FfmpegProgress(cmd_progress)
            for progress in process.run_command_with_progress():
                print(f"progress = {progress}% - ",
                      "\n".join(str(process.stderr).splitlines()[-9:-8]),
                      flush=True)

        else:
            process = subprocess.Popen(self.cmd,
                                       stdout=subprocess.PIPE,
                                       shell=True)
            process.communicate()

        return process
コード例 #5
0
def get_scenecuts(in_f, threshold=0.3, progress=False, verbose=False):
    """
    Calculate scene cuts with ffmpeg.
    """
    if not (0 <= threshold <= 1):
        raise RuntimeError("Threshold must be between 0 and 1")

    temp_dir = tempfile.gettempdir()
    temp_file_name = os.path.join(
        temp_dir,
        next(tempfile._get_candidate_names()) + ".txt")

    try:

        cmd = [
            "ffmpeg",
            "-loglevel",
            "error",
            "-y",
            "-i",
            in_f,
            "-vf",
            "select=gte(scene\,0),metadata=print:file=" + temp_file_name,
            "-an",
            "-f",
            "null",
            "-",
        ]

        if verbose:
            cmd_q = " ".join([shlex.quote(c) for c in cmd])
            print("Running ffmpeg command: {}".format(cmd_q), file=sys.stderr)

        ff = FfmpegProgress(cmd)
        if progress:
            with tqdm(total=100, position=1) as pbar:
                for progress in ff.run_command_with_progress():
                    pbar.update(progress - pbar.n)
        else:
            for _ in ff.run_command_with_progress():
                pass

        lines = []
        if os.path.isfile(temp_file_name):
            with open(temp_file_name, "r") as out_f:
                lines = out_f.readlines()

        frames = []
        last_frame_info = {}
        for line in lines:
            line = line.strip()
            if line.startswith("frame"):
                rex = r"frame:(?P<frame>\d+)\s+pts:(?P<pts>[\d\.]+)\s+pts_time:(?P<pts_time>[\d\.]+)"
                ret = re.match(rex, line)
                if ret:
                    ret_matches = ret.groupdict()
                    last_frame_info["frame"] = int(ret_matches["frame"])
                    last_frame_info["pts"] = float(ret_matches["pts"])
                    last_frame_info["pts_time"] = float(
                        ret_matches["pts_time"])
                else:
                    raise RuntimeError("Wrongly formatted line: " + line)
                continue
            if line.startswith("lavfi.scene_score"):
                splits = line.split("=")
                if len(splits):
                    last_frame_info["score"] = float(splits[1])
                else:
                    raise RuntimeError("Wrongly formatted line: " + line)
                frames.append(last_frame_info)
                last_frame_info = {}

        scenecuts = [f for f in frames if f["score"] >= threshold]

    except Exception as e:
        raise e
    finally:
        if os.path.isfile(temp_file_name):
            os.remove(temp_file_name)

    return scenecuts