I play with this for several days. This "ffmpegprogress" thing helped, but it was very difficult to work with my setup and reading the code was not easy.
To show the progress of ffmpeg, you need to do the following:
- run ffmpeg command with php without waiting for an answer (for me it was the hardest part)
- tell ffmpeg to send it to a file
- from the front side (AJAX, Flash, independently) it gets either to this file directly or to the php file, which can output progress from ffmpeg output.
Here is how I solved each part:
1. I got the following idea from "ffmpegprogress". This he did: one PHP file calls another via an http socket. The second one actually runs "exec", and the first file just hangs on it. For me, its implementation was too complicated. He used "fsockopen". I like curl. So here is what I did:
$url = "http://".$_SERVER["HTTP_HOST"]."/path/to/exec/exec.php"; curl_setopt($curlH, CURLOPT_URL, $url); $postData = "&cmd=".urlencode($cmd); $postData .= "&outFile=".urlencode("path/to/output.txt"); curl_setopt($curlH, CURLOPT_POST, TRUE); curl_setopt($curlH, CURLOPT_POSTFIELDS, $postData); curl_setopt($curlH, CURLOPT_RETURNTRANSFER, TRUE);
Setting CURLOPT_TIMEOUT to 1 means that 1 second will wait for a response. Preferably, this is lower. There is also CURLOPT_TIMEOUT_MS, which takes milliseconds, but for me it did not work.
After 1 second, CURL freezes, but the exec command still works. Part 1 solved.
BTW - Several people have suggested using the nohup command for this. But it didn't seem to work for me.
* ALSO! Having a php file on your server that can execute code directly on the command line is an obvious security risk. You must have a password or encode these messages in some way.
2. The above "exec.php" script should also specify ffmpeg to output to the file. Here is the code for this:
exec("ffmpeg -i path/to/input.mov path/to/output.flv 1> path/to/output.txt 2>&1");
Note the "1> path /to/output.txt 2> & 1". I am not an expert on the command line, but from what I can say, this line says "send normal output to this file and send errors to the same place." Check this url for more information: http://tldp.org/LDP/abs/html/io-redirection.html
3. From the external interface, call php script, indicating the location of the output.txt file. Then this php file will pull the progress from the text file. Here is how I did it:
// # 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 current time preg_match_all("/time=(.*?) bitrate/", $content, $matches); $last = array_pop($matches); // # this is needed if there is more than one match if (is_array($last)) { $last = array_pop($last); } $curTime = floatval($last); // # finally, progress is easy $progress = $curTime/$duration;
Hope this helps someone.