ffmpeg video encoding progress bar

12,511

Solution 1

javascript should tell php to start converting [1] and then do [2] ...


[1] php: start conversion and write status to a textfile - example syntax:

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

For the second part we need just javascript to read the file. The following example uses dojo.request for AJAX, but you could use jQuery or vanilla or whatever as well :

[2] js: grab the progress from the file:

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

Solution 2

It can be done, although it would be good idea to go for a simpler ajax indicator for smaller files, but for larger files >50-80 MBs you can do this:

You can read FFMPEG return values via PHP. ffmpeg (last few lines) returns this:

Press [q] to stop encoding
frame= 1850 fps=115 q=31.0 Lsize=    5789kB time=74.00 bitrate= 640.8kbits/s   
video:5135kB audio:580kB

The time=74.00 is the current file time (NOT execution time). You can use some regex to parse that value and with some math you can get the percentage complete bar.

If you don't know the file time length. FFMPEG first few lines returns this:

Input #0, flv, from 'cf_video_3728.flv':
  Duration: 00:01:14.13, start: 0.000000, bitrate: 864 kb/s

You can parse the Duration and get the total time.

Hope this helps.

Solution 3

If you're using PHP-FFMpeg, they've added an on function that you can listen for progress and execute a call back with. You set it up on your video format container like so:

$format = new Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
    echo "$percentage % transcoded";
});

More info found in the docs https://github.com/PHP-FFMpeg/PHP-FFMpeg

Share:
12,511

Related videos on Youtube

Rahul TS
Author by

Rahul TS

Working as Chief Technology Officer at Ergonomicscit.com Consultant of Web applications/Software Development

Updated on May 04, 2022

Comments

  • Rahul TS
    Rahul TS about 2 years

    When I run the conversion in the browser it simply shows the white blank space. Only after the conversion process page will load.

    Please suggest how to implement a progress bar which shows the progress to the user when the video conversion takes place.

    I have this in my php script

    exec("ffmpeg -i filename.flv -sameq -ab 128 -s 640x480 filename.mp4");
    

    so how should I change this script to get the progress details even to a file or directly as ouput in the page. Please can anyone give me a complete script/code to explain it in detail. Because I think I cant get the complete answers and so I am confused on what to do with this

  • Ultimate Gobblement
    Ultimate Gobblement almost 14 years
    It would be awkward and inefficient, but I imagine you should be able to redirect the ffmpeg output to a tempfile, which can then be read by php. I'd sooner go for the waiting indicator though - much simpler.
  • sebilasse
    sebilasse about 11 years
    Basically I agree, Comet D would make my answer complete and any push technique should be preferred.