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);
}
}
});