システム全体をPHPで記述し、サーバーでbashを実行して、VPSでHTML5のビデオを変換およびストリーミングします。変換はバックグラウンドでffmpegによって行われ、コンテンツはblock.txt。
次の投稿を見て:
そして
とりわけ、私は実用的な例を見つけることができません。
現在エンコードされている進行状況をパーセンテージで取得する必要があります。
上記でリンクした最初の投稿は次のようになります:
$log = @file_get_contents('block.txt');
preg_match("/Duration:([^,]+)/", $log, $matches);
list($hours,$minutes,$seconds,$mili) = split(":",$matches[1]);
$seconds = (($hours * 3600) + ($minutes * 60) + $seconds);
$seconds = round($seconds);
$page = join("",file("$txt"));
$kw = explode("time=", $page);
$last = array_pop($kw);
$values = explode(' ', $last);
$curTime = round($values[0]);
$percent_extracted = round((($curTime * 100)/($seconds)));
echo $percent_extracted;
$ percent_extracted変数はゼロをエコーします。そして、数学は私の得意ではないので、ここでどのように進めるかは本当にわかりません。
これは、block.txtからのffmpeg出力の1行です(役立つ場合)
time = 00:19:25.16 bitrate = 823.0kbits/s frame = 27963 fps = 7 q = 0.0 size = 117085kB time = 00:19:25.33 bitrate = 823.1kbits/s frame = 27967 fps = 7 q = 0.0 size = 117085kB time = 00:19:25.49 bitrate = 823.0kbits/s frame = 27971 fps = 7 q = 0.0 size = 117126kB
このパーセンテージを出力できるようにしてください。完了したら、独自の進行状況バーを作成できます。ありがとう。
さて、私は私が必要なものを見つけました-そしてうまくいけば、これは他の誰かにも役立つでしょう!
何よりもまず、ffmpegデータをサーバー上のテキストファイルに出力します。
ffmpeg -i path/to/input.mov -vcodec videocodec -acodec audiocodec path/to/output.flv 1> block.txt 2>&1
つまり、ffmpegの出力はblock.txtです。PHPでこれを実行しましょう!
$content = @file_get_contents('../block.txt');
if($content){
//get duration of source
preg_match("/Duration: (.*?), start:/", $content, $matches);
$rawDuration = $matches[1];
//rawDuration is in 00:00:00.00 format. This converts it to seconds.
$ar = array_reverse(explode(":", $rawDuration));
$duration = floatval($ar[0]);
if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;
//get the time in the file that is already encoded
preg_match_all("/time=(.*?) bitrate/", $content, $matches);
$rawTime = array_pop($matches);
//this is needed if there is more than one match
if (is_array($rawTime)){$rawTime = array_pop($rawTime);}
//rawTime is in 00:00:00.00 format. This converts it to seconds.
$ar = array_reverse(explode(":", $rawTime));
$time = floatval($ar[0]);
if (!empty($ar[1])) $time += intval($ar[1]) * 60;
if (!empty($ar[2])) $time += intval($ar[2]) * 60 * 60;
//calculate the progress
$progress = round(($time/$duration) * 100);
echo "Duration: " . $duration . "<br>";
echo "Current Time: " . $time . "<br>";
echo "Progress: " . $progress . "%";
}
残り時間のパーセンテージを出力します。
これをページにエコー出力する唯一のテキストとして使用できます。別のページから、jQueryを使用してAJAXリクエストを実行し、このテキストを取得してdivに出力します。たとえば、ページを10秒ごとに更新するには:)
ffmpegに、出力をより簡単に解析できる進行オプションが追加されました。
ffmpeg -progress block.txt -i path/to/input.mov -vcodec videocodec -acodec audiocodec path/to/output.flv 2>&1
エンコードを開始する前に、フレームの合計、およびその他の多くの情報を取得できます(これはbashで行われることです。私はPerlプログラマーなので、どのように情報を取得するのかわかりません) PHPスクリプト)。
eval $(ffprobe -of flat = s = _ -show_entries stream = height、width、nb_frames、duration、codec_name path/to/input.mov);
幅= $ {streams_stream_0_width};
height = $ {streams_stream_0_height};
frames = $ {streams_stream_0_nb_frames};
videoduration = $ {streams_stream_0_duration};
audioduration = $ {streams_stream_1_duration};
codec = $ {streams_stream_0_codec_name};
echo $ width、$ height、$ frames、$ videoduration、$ audioduration、$ codec;
-of flate = s = _は、各name = valueを別々の行に置くことを示します。 -show_entriesは、後続のエントリを表示するように指示します(-show_streamsのストリーム、-show_formatのフォーマットなど)。以下を試して、何が利用可能かを確認してください。
ffprobe -show_streams path/to/input.mov
進行状況ファイルへの出力は、約1秒に1回追加されます。コンテンツは、エンコードが完了すると次のようになります。スクリプトでは、1秒に1回、ファイルを配列に入れ、配列を逆順でトラバースします。最初の[反転前の最後の] 2つの「進行」行の間にあるものだけを使用して、ファイルの最後からの最新情報。もっと良い方法があるかもしれません。これはオーディオのないmp4からのものなので、ストリームは1つしかありません。
フレーム= 86
fps = 0.0
stream_0_0_q = 23.0
合計サイズ= 103173
out_time_ms = 1120000
out_time = 00:00:01.120000
dup_frames = 0
drop_frames = 0
進行状況=続行
フレーム= 142
fps = 140.9
stream_0_0_q = 23.0
total_size = 415861
out_time_ms = 3360000
out_time = 00:00:03.360000
dup_frames = 0
drop_frames = 0
進行状況=続行
フレーム= 185
fps = 121.1
stream_0_0_q = 23.0
total_size = 1268982
out_time_ms = 5080000
out_time = 00:00:05.080000
dup_frames = 0
drop_frames = 0
進行状況=続行
フレーム= 225
fps = 110.9
stream_0_0_q = 23.0
合計サイズ= 2366000
out_time_ms = 6680000
out_time = 00:00:06.680000
dup_frames = 0
drop_frames = 0
進行状況=続行
フレーム= 262
fps = 103.4
stream_0_0_q = 23.0
total_size = 3810570
out_time_ms = 8160000
out_time = 00:00:08.160000
dup_frames = 0
drop_frames = 0
進行状況=続行
フレーム= 299
fps = 84.9
stream_0_0_q = -1.0
合計サイズ= 6710373
out_time_ms = 11880000
out_time = 00:00:11.880000
dup_frames = 0
drop_frames = 0
progress = end
javascriptがプログレスバーを更新する場合、javascriptはステップ2を「直接」実行できます。
[この例では dojo が必要です]
1php:変換を開始し、ステータスをテキストファイルに書き込む-例構文:
exec("ffmpeg -i path/to/input.mov path/to/output.flv 1>path/to/output.txt 2>&1");
2番目の部分では、ファイルを読み取るためにjavascriptが必要です。次の例では、AJAXにdojo.requestを使用していますが、jQueryやVanillaなども使用できます。
[2]js:ファイルから進行状況を取得します。
var _progress = function(i){
i++;
// THIS MUST BE THE PATH OF THE .txt FILE SPECIFIED IN [1] :
var logfile = 'path/to/output.txt';
/* (example requires dojo) */
request.post(logfile).then( function(content){
// AJAX success
var duration = 0, time = 0, progress = 0;
var result = {};
// get duration of source
var matches = (content) ? content.match(/Duration: (.*?), start:/) : [];
if( matches.length>0 ){
var rawDuration = matches[1];
// convert rawDuration from 00:00:00.00 to seconds.
var ar = rawDuration.split(":").reverse();
duration = parseFloat(ar[0]);
if (ar[1]) duration += parseInt(ar[1]) * 60;
if (ar[2]) duration += parseInt(ar[2]) * 60 * 60;
// get the time
matches = content.match(/time=(.*?) bitrate/g);
console.log( matches );
if( matches.length>0 ){
var rawTime = matches.pop();
// needed if there is more than one match
if (lang.isArray(rawTime)){
rawTime = rawTime.pop().replace('time=','').replace(' bitrate','');
} else {
rawTime = rawTime.replace('time=','').replace(' bitrate','');
}
// convert rawTime from 00:00:00.00 to seconds.
ar = rawTime.split(":").reverse();
time = parseFloat(ar[0]);
if (ar[1]) time += parseInt(ar[1]) * 60;
if (ar[2]) time += parseInt(ar[2]) * 60 * 60;
//calculate the progress
progress = Math.round((time/duration) * 100);
}
result.status = 200;
result.duration = duration;
result.current = time;
result.progress = progress;
console.log(result);
/* UPDATE YOUR PROGRESSBAR HERE with above values ... */
if(progress==0 && i>20){
// TODO err - giving up after 8 sec. no progress - handle progress errors here
console.log('{"status":-400, "error":"there is no progress while we tried to encode the video" }');
return;
} else if(progress<100){
setTimeout(function(){ _progress(i); }, 400);
}
} else if( content.indexOf('Permission denied') > -1) {
// TODO - err - ffmpeg is not executable ...
console.log('{"status":-400, "error":"ffmpeg : Permission denied, either for ffmpeg or upload location ..." }');
}
},
function(err){
// AJAX error
if(i<20){
// retry
setTimeout(function(){ _progress(0); }, 400);
} else {
console.log('{"status":-400, "error":"there is no progress while we tried to encode the video" }');
console.log( err );
}
return;
});
}
setTimeout(function(){ _progress(0); }, 800);