Configuracion del servidor (en mi caso: ubuntu):
Antes que nada, ya debe estar instalado en el servidor ffmpeg con sus respectivos codecs, FlvTool2 para insertar metaData en el video (FLV injection) y la libreria ffmpeg_movie para obtener algunos datos necesarios y/o generar imagen de vista previa.
Uno de los problemas que tuve es que al ejecutar el script desde el navegador se realizaba la conversion sin problemas, pero, al ejecutarlo en segundo plano (background) fallaba.
La causa de esto es por la configuracion de PHP que no tenia acceso a ffmpeg_movie y no lo notaba porque en /etc/php5/apache2/php.ini aparece extension=ffmpeg.so, entonces busque todos los php.ini (find / -name php.ini) y encontre /etc/php/cli/php.ini, donde no estaba la linea, simplemente la agregue y funciono correctamente.
Subir archivo y ejecutar script de conversion:
Despues de subir el archivo y validar la extension (Las que yo permito: mov, wmv, avi, mpg, mpeg y flv) iniciamos la conversion en segundo plano:
Nota: No coloco todas las validaciones necesarias, porque es demasiado codigo y vamos al grano con la conversion.
Código php:
Ver original
<?php // Subimos el archivo como lo hacemos con cualquier otro: // Para mas informacion de como subir archivos, en la seccion de aportes hay varios ejemplos // En este punto, guardamos el registro del video en base de datos // Algunos de los campos que uso: // -- id = varchar(10) // -- archivo = Nombre de archivo, primero solo almaceno la extension del archivo original // -- estado: // 0 = No se ha subido archivo // 1 = Video subido, convertido y listo para verse en la web // 2 = Se subio archivo y esta listo para convertir a FLV // 3 = Esta en proceso de conversion // Notificamos al usuario que el archivo subio y va a iniciar la conversion ?> <html> <body> <p>El archivo fue subido correctamente, ahora lo vamos a convertir a FLV, mientras puedes ver otras paginas en nuestro sitio.</p> </body> </html> <?php // >/dev/null & ---- Esto es lo que hace que se ejecute en segundo plano
convertir.php -> Configuracion general
Necesitaremos algunas variables:
- Ruta de videos pendientes de convertir: $ruta_convertir = '/ruta/convertir';
- Ruta final de videos: $ruta_video = '/ruta/videos';
- Ruta de imagen de marca de agua (opcional): $marca_agua = '/ruta/marca_agua.gif';
- Dimensiones del video convertido ANCHOxALTO: $medidas = '640x480';
- Frecuencia de audio (sample rate), especificamente, las 3 unicas permitidas en videos flv $frecuencia = array(44100, 22050, 11025);
convertir.php -> Obtener info general del video
Código php:
Ver original
// Tomamos la id del video desde GET (es necesario validar) $video = $_GET['id']; // Leemos info de la base de datos // En el campo archivo solo tengo almacenada la extension $original = "$ruta_convertir/$id$archivo"; $final = "$ruta_video/$id" . '.flv'; $vista_previa = "$ruta_video/$id" . '.jpg'; // Creamos un objeto ffmpeg_movie para obtener datos necesarios para convertir $movie = new ffmpeg_movie($original, false); $duracion = $movie->getDuration(); // Duracion en segundos $audioRate = $movie->getAudioSampleRate(); $audioBitr = $movie->getAudioBitRate(); $audioRate = 22050; $audioBitr = $audioRate; // Creamos el comando ffmpeg $ffmpeg_cmd = "ffmpeg -i $original -ar $audioRate -ab $audioBitr -f flv -s $medidas $final"; // La siguiente linea es necesaria solo si vas a agregar marca de agua $ffmpeg_cmd .= " -vhook '/usr/local/lib/vhook/watermark.so -f $marca_agua'"; // Ejecutamos el comando y guardamos la salida en una matriz (util para depurar) // Si necesitas depurar, despues de cada exec() incluye: // file_put_contents('depurar.txt', implode("\n", $salida)); // Injectamos metaData: $ffmpeg_cmd = "flvtool2 -U $final"; // Generamos la vista previa (120 x 90 pixeles, puedes modificarlo a tu gusto) // Seleccionamos una posicion en medio del video $ffmpeg_cmd2 = "ffmpeg -i $final -ss $posicion -t 00:00:01 -s 120x90 -r 1 -f image2 $vista_previa"; // Si algo fallo, intentamos otro metodo $ffmpeg_cmd2 = "ffmpeg -itsoffset -4 -i $final -vcodec mjpeg -vframes 1 -an -f rawvideo -s 120x90 $vista_previa"; } // Si volvio a fallar, intentamos con ffmpeg_movie // Nota: la libreria GD tambien debe estar habilitada en /etc/php5/cli/php.ini // extension=gd.so // Creamos el objeto, obtenemos total de cuadros y calculamos la mitad $movie = new ffmpeg_movie($final, false); $total = $movie->getFrameCount(); // Leemos el cuadro elegido y redimensionamos $frame = $movie->getFrame($medio); $frame->resize(120, 90); // Convertimos a imagen de GD, guardamos como jpg y destruimos el recurso GD $gd_image = $frame->toGDImage(); } // Actualizamos la base de datos con la informacion necesaria // Como depende de los campos que se tengan solo pongo un ejemplo: // archivo = '$final', vista_previa = '$vista_previa', duracion = $duracion, estado = 1 // Eliminamos archivo original // Listo, eso es todo... yeah!!!! // Funcion basada en http://snipplr.com/view/1459/sec2hms/ function sec2hms($sec, $useColon = false) { $hms = ''; if ($hours > 0) { } elseif ($useColon) { $hms .= '00:'; } if ($minutes > 0 || $hours > 0) return $hms; }
Es posible realizar la conversion del video e insertar metaData en un mismo comando exec('comando1 | comando2'); pero no lo recomiendo, en ocasiones no funciono y no hay diferencia en los recursos que consume el script al ejecutarse, estuve monitoreando con TOP desde SSH.
Enlaces de interes:
- API (clase?) de ffmpeg-php
- Convertir segundos (entero) en cadena (hh:mm:ss)