ffmpeg的进度条 - 编码PHP百分比(ffmpeg Progress Bar - Encodi

2019-06-14 21:09发布

我已经写在服务器上PHP的整体系统和bash转换和对我的VPS流在HTML5视频。 该转换是通过FFMPEG在后台进行,将内容输出到block.txt。

说完看了下面的帖子:

ffmpeg的可以显示一个进度条?

ffmpeg的视频编码进度条

除其他外,我找不到工作的例子。

我要抓住当前编码进度的百分比。

我上面链接中的第一篇文章给:

$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变量呼应零,因为数学是不是我的强项,我真的不知道怎么这方面的进展。

下面是从FFmpeg的输出一行从block.txt(如果它是有帮助的)

时间= 00:19:25.16比特率= 823.0kbits / s的帧= 27963 FPS = 7 Q = 0.0尺寸= 117085kB时间= 00:19:25.33比特率= 823.1kbits / s的帧= 27967 FPS = 7 Q = 0.0尺寸= 117085kB时间= 00:19:25.49比特率= 823.0kbits / s的帧= 27971 FPS = 7 q = 0.0尺寸= 117126kB

请帮我输出这一比例,一旦做我可以创造我自己的进度条。 谢谢。

Answer 1:

好吧,我发现我需要的东西 - 希望这可以帮助其他人的!

首先,你要输出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这一段文字,并输出它抢进一个div执行AJAX请求,例如,你的页面的每个上更新10秒。 :)



Answer 2:

ffmpeg的现在有一个进步的选项,这使输出更容易分析。

FFMPEG -progress block.txt -i路径/到/ input.mov -vcodec VIDEOCODEC -acodec的AudioCodec路径/到/ output.flv 2>&1

你开始编码,你可以得到的总框架,以及很多其他的信息与在此之前(这是什么会使用bash来完成。我是一个Perl程序员,所以我不知道你是如何得到信息到您的PHP脚本)。

EVAL $(ffprobe -of平= S = _ -show_entries流=高度,宽度,nb_frames,持续时间,codec_name路径/到/ input.mov);
宽度= $ {streams_stream_0_width};
高度= $ {streams_stream_0_height};
帧= $ {streams_stream_0_nb_frames};
videoduration = $ {streams_stream_0_duration};
audioduration = $ {streams_stream_1_duration};
编解码器= $ {streams_stream_0_codec_name};
回声$宽度,$高度,$帧,$ videoduration,$ audioduration,$编解码器;

-of flate = S = _说把每个名称=值在单独一行。 -show_entries告知将显示从什么如下(流为-show_streams,为-show_format格式等)流条目= ......说来显示从-show_streams输出的项目。 尝试以下,看看什么是可用:

ffprobe -show_streams路径/到/ input.mov

输出到进度文件被添加到大约每秒一次。 内容,编码完成后,如下所示。 在我的剧本,一次第二,我把文件到一个数组,遍历以相反的顺序排列,只使用什么是第一[前最后的逆转]两个“进步”行,我觉得之间,所以,我现在用的从文件末尾最近的信息。 可能有更好的方法。 这是不带音频的MP4所以只有一个流。

帧= 86
FPS = 0.0
stream_0_0_q = 23.0
TOTAL_SIZE = 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
TOTAL_SIZE = 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
TOTAL_SIZE = 6710373
out_time_ms = 11880000
Out_time相当= 00:00:11.880000
dup_frames = 0
drop_frames = 0
进度=端



Answer 3:

如果JavaScript的更新您的进度条,javascript中可以执行“直接”第2步:

[本实施例中需要道场 ]


1个 PHP:启动转换和写入状态,以一个文本-示例语法:

exec("ffmpeg -i path/to/input.mov path/to/output.flv 1>path/to/output.txt 2>&1");

对于第二部分,我们需要JavaScript来读取文件。 下面的示例使用dojo.request对AJAX的,但你可以使用jQuery或香草或任何还有:

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


文章来源: ffmpeg Progress Bar - Encoding Percentage in PHP