He estado jugando con esto durante unos días. Esa cosa "ffmpegprogress" ayudó, pero fue muy difícil llegar a trabajar con mi configuración, y es difícil leer el código.
Con el fin de mostrar el progreso de FFmpeg que tiene que hacer lo siguiente:
- ejecutar el comando ffmpeg desde PHP sin ella esperando una respuesta (para mí, esta fue la parte más difícil)
- dile a ffmpeg que envíe su salida a un archivo
- desde el extremo frontal (AJAX, Flash, lo que sea), golpea ese archivo directamente o un archivo php que puede extraer el progreso de la salida de ffmpeg.
Así es como he resuelto cada parte:
1. me dio la siguiente idea de "ffmpegprogress". Esto es lo que hizo: un archivo PHP llama a otro a través de un socket http. El segundo en realidad ejecuta el "ejecutivo" y el primer archivo simplemente cuelga en él. Para mí, su implementación fue demasiado compleja. Él estaba usando "fsockopen". Me gusta CURL.Así que aquí está lo que hice:
$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);
// # this is the key!
curl_setopt($curlH, CURLOPT_TIMEOUT, 1);
$result = curl_exec($curlH);
Configuración CURLOPT_TIMEOUT a 1 significa que se va a esperar 1 segundo para una respuesta. Preferiblemente eso sería más bajo. También está el CURLOPT_TIMEOUT_MS que demora milisegundos, pero no funcionó para mí.
Después de 1 segundo, CURL cuelga, pero el comando exec aún se ejecuta. Parte 1 resuelta.
BTW - Algunas personas sugirieron usar el comando "nohup" para esto. Pero eso no pareció funcionar para mí.
* TAMBIÉN! Tener un archivo php en su servidor que pueda ejecutar código directamente en la línea de comandos es un riesgo obvio de seguridad. Debe tener una contraseña o codificar los datos de la publicación de alguna manera.
2. El script "exec.php" de arriba también debe decirle a ffmpeg que muestre un archivo. Aquí está el código para eso:
exec("ffmpeg -i path/to/input.mov path/to/output.flv 1> path/to/output.txt 2>&1");
Nota del "1> ruta/a/2 salida.txt> & 1". No soy un experto en línea de comandos, pero por lo que puedo decir, esta línea dice "envíe salida normal a este archivo Y envíe errores al mismo lugar". Echa un vistazo a la siguiente dirección URL para obtener más información: http://tldp.org/LDP/abs/html/io-redirection.html
3. desde el extremo frontal llamar a un script php que le da la ubicación del archivo salida.txt. Ese archivo php luego sacará el progreso del archivo de texto. He aquí cómo lo hice:
// # 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;
Espero que esto ayude a alguien.
Pero ¿por qué utilizar un archivo de texto? Tiene que haber una mejor manera. ¿No tendrías que hacer un nuevo archivo de texto por cada carga? – Scarface