LoginSignup
5
8

More than 5 years have passed since last update.

jQueryを使ったffmpeg変換処理の進行状況チェック

Last updated at Posted at 2017-06-17

ffmpegを利用して動画エンコードするときに進捗チェックしたい

以前作ったWebUIの操作で動画を作成するスクリプトが出て来たので役に立つか不明だがメモ代わりに。ちなみに2014年頃に作ったものらしいのでffmpegの最新ビルドで動くかどうか未確認。

ffmpeg変換用スクリプト

指定された静止画像をmp4に変換。変なパラメータがいくつか残っているが重要では無いので説明省略。
肝はwhile()内で標準出力から処理済みのフレーム数を取得して進捗率を計算しているところ?

encode.php
<?php

if (ob_get_level() == 0) ob_start();

// なんかいろいろ省略

$progress = new stdClass;
$progress->hash = $param->hash;
$progress->status = "encode";
$progress->percentage = 0;
$progress->file = 0;
$progress->totalfile = 0;

// export initial value
echo json_encode($progress,  JSON_NUMERIC_CHECK) . "\n";
@ob_flush();
@flush();

$command = "/usr/local/bin/ffmpeg -y -r {$param->real_frame_rate} -i {$tempdir}/%08d.jpg " .
           "  -f mp4 -movflags +faststart ".
           "  -c:v libx264 -r {$CFG->logicalframerate} -pix_fmt yuv420p -s 640x480 -b:v 800k -minrate 800k -maxrate 800k " .
           "  -an " .
           "  -coder ac -refs 8 -threads 0 {$tempdir}/movie.mp4";
$handle = popen($command . " 2>&1",'r');

while (!feof($handle)) {
    $line = stream_get_line($handle, 1024, "¥r");
    if (preg_match('/frame=\s*([0-9]+)/', $line, $match)) $progress->frame = $match[1];
    $progress->percentage = floor(($progress->frame/$progress->totalframe) * 100);
    if ((preg_match('/overhead/', $line)) == 1) $progress->percentage = 100;

    echo json_encode($progress,  JSON_NUMERIC_CHECK) . "\n";
    @ob_flush();
    @flush();
}
pclose($handle);

unset($progress->percentage);
unset($progress->frame);
unset($progress->totalframe);

$progress->status = "finish";
echo json_encode($progress) . "\n";
array_map('unlink', glob($tempdir . "/*.jpg"));
rename($tempdir . "/movie.mp4", $CFG->dataroot . "/movies/" . $param->hash . ".mp4");

die();

WebUI側

$.ajax({
    type: 'POST',
    url: '/encode.php',
    data: param,
    dataType: 'json',
    timeout: 0,
    xhrFields: {
        onloadstart: function() {
            var xhr = this;
            $.xhrtimer = setInterval(function() {
                var lastlogs = xhr.responseText.replace(/(^\n+)|(\n+$)/g, "").split('\n');
                var lastlog = lastlogs.pop();
                if (lastlog !== null) {
                    lastlog = eval("(" + lastlog + ")");
                        switch (lastlog.status) {
                            case false :
                           alert(lastlog.result);
                           clearInterval($.xhrtimer);
                           break;

                           // 進捗管理用の表示処理
                }
            }, 2000);
        }
    }
});
5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8