1. Para poder probar tanto en local como en produccion, guardo en variables las rutas de los programas y archivos necesarios.
Código PHP:
Ver originalif($_SERVER['SERVER_NAME'] == 'localhost') {
$ffmpeg = 'c:/wamp/bin/mplayer/ffmpeg.exe';
$flvtool = 'c:/wamp/bin/mplayer/flvtool2.exe';
$srcdir = '/servidor/pruebas/tests/original';
$cnvdir = '/servidor/pruebas/tests/converted';
// Tratando de mostrar info conforme avanza el proceso
// Esto generalmente me causa errores en Ubuntu
// Por eso lo tengo solo para el servidor local
@ini_set('zlib.output_compression', 0); } else {
// En ubuntu no necesito la ruta absoluta para los programas
$ffmpeg = 'ffmpeg';
$flvtool = 'flvtool2';
$srcdir = '/ruta_del_sitio/htdocs/tests/original';
$cnvdir = '/ruta_del_sitio/htdocs/tests/converted';
}
// Por si vamos a agregar marca de agua (probado solo en Windows)
$watermark = "$srcdir/watermark2.png";
// Directorio para generar imagenes de vista previa
$preview_dir = "$cnvdir/preview";
// Sample rates soportados por FLV
$samples = array(44100, 22050, 11025);
Bien, ya teniendo lista la configuracion, leemos los archivos, ya sea de base de datos o, en este caso, del directorio de pruebas:
Código PHP:
Ver original// Leer archivos en directorio original
// No use glob porque esto ya lo tenia
if($file != '.' && $file != '..' && end(explode('.', $file)) != 'png') { $files[] = $file;
}
}
echo 'Preparando para convertir: ' . count($files) . " videos\n------------\n";
Ok, iniciamos con lo bueno, solo pido de favor no criticar el enredo de codigo, porque iba parchando un script muy viejo sobre la marcha y... siendo solo pruebas... pues hay que hacerlo rapido.
Nota, para poder ver los avances, despues de cada echo hay que agregar
flush();
Código PHP:
Ver originalforeach($files as $file) {
$newext = '.flv';
$preext = '.jpg';
$curext = '.' . end($parts);
// Las dos lineas siguientes son solo por "compatibilidad" con el codigo de produccion
$file_orig = "$srcdir/$curvid$curext";
$file_final = "$cnvdir/$curvid$newext";
$file_pre = "$preview_dir/$curvid$preext"; // Vista previa
$file_th = "$preview_dir/{$curvid}.th$preext"; // Agregue esto para crear miniaturas
echo "Preparando para convertir $file_orig to $file_final\n";
// Obtener información del video... recordando que php_ffmpeg me dio problemas
// Simplemente hacemos que ffmpeg nos de algunos datos
// para pasarlos por preg_match
exec("$ffmpeg -i $file_orig 2>&1", $output); $duration = $frameRate = $audioRate = $audioBitr = 0;
if(preg_match('/Duration: (.*?),/', $output, $matches)) { $duration = $matches[1];
$duration_array = explode(':', $duration); $duration = ($duration_array[0] * 3600) + ($duration_array[1] * 60) + $duration_array[2];
}
if (preg_match('/([0-9\.]+)\stbr/', $output, $matches)) { $frameRate = $matches[1];
}
if(preg_match('/bitrate: ([0-9]+) kb\/s/', $output, $matches)) { $audioBitr = $matches[1];
}
if(preg_match('/Audio:.+?([0-9]+) Hz/', $output, $matches)) { $audioRate = $matches[1];
}
if($duration == 0) {
// No obtuvimos duracion, el resto de datos podemos "calcularlos", pero este no
echo "----------------\nFormato de video no reconocido: $file_orig\nDuracion: $duration\nFrame Rate: $frameRate\nAudio Sample: $audioRate\nAudio Bit: $audioBitr\n\n";
continue;
}
// Verificamos que todo sea soportado en FLV
$oldrate = '';
$oldrate = "/$audioRate";
$audioRate = 22050;
}
if(!isset($audioBitr) || !$audioBitr || $audioBitr < 1) { $audioBitr = $audioRate;
}
echo "---- Duración: $duration segundos\n---- Frame Rate: $frameRate fps";
echo "---- Audio Bit Rate: $audioBitr\n---- Audio Sample Rate: $audioRate$oldrate";
// Ojo, esto tuve que hacerlo para probar, solo me funciono en Windows
// Hace mas complicado el codigo, pero necesitaba poder omitirlo para Linux
$newWater = "-vf \"movie=$watermark [img]; [in] [img] overlay=0:0:1 [movie]; [movie] setdar=3:2\"";
// Los WMV son mas latosos, asi que por separado y conservando la misma calidad (?) ( -sameq )
$ffmpeg_cmd = "$ffmpeg -i $file_orig -sameq -acodec libmp3lame -ar 22050 -ab 96000 -deinterlace -nr 500 -s 450x300 -aspect 4:3 -r 20 -g 500 -me_range 20 -b 270k -f flv -y $newWater $file_final";
} else {
// El resto de formatos con una calidad entre 65 y 70% ( -qscale 10 )
$ffmpeg_cmd = "$ffmpeg -i $file_orig -qscale 10 -acodec libmp3lame -ar $audioRate -ab $audioBitr -f flv -s 450x300 $newWater $file_final";
}
echo "-- Comando para convertir: $ffmpeg_cmd\n";
exec("$ffmpeg_cmd 2>&1", $output);
// Verificamos que se haya generado el video
echo "\n\n------ $fecha CONVERSION FALLO, archivo no creado\nOriginal: [$file_orig]\nDestino: [$file_final]\n" . implode("\n", $output) . "\n"; continue;
}
// Se genero el archivo, pero sin informacion?
echo "\n\n------ $fecha CONVERSION FALLO, archivo creado con cero bytes\nOriginal: [$file_orig]\nDestino: [$file_final]\n" . implode("\n", $output) . "\n"; continue;
}
// Parece que todo va bien... inyectamos meta datos FLV
$ffmpeg_cmd = "$flvtool -U $file_final";
echo "-- FLVtool injection: $ffmpeg_cmd\n";
exec("$ffmpeg_cmd 2>&1", $output);
// Preparamos para crear miniatura e imagen de vista previa
// Para el primer metodo, con itoffset, se requiere la posicion en numero entero
$itoffset = ceil($duration / 2); // Para el segundo metodo, lo necesitamos en formato hh:mm:ss
$thumb_position = sec2hms
(ceil($duration / 2));
// Primero la miniatura
$ffmpeg_cmd2 = "$ffmpeg -itsoffset -$itoffset -i $file_final -vcodec mjpeg -vframes 1 -an -f rawvideo -s 100x68 $file_th";
echo "-- Crear thumbnail (1): $ffmpeg_cmd2\n";
exec("$ffmpeg_cmd2 2>&1", $output); // Si no se genero correctamente, lo eliminamos
}
// No se genero, probamos el segundo metodo
// Aclaro que esto lo tengo desde la primera version del aporte
// Y no ha llegado el caso de probarlo...
// Tal vez lo haga manualmente cuando tenga tiempo
$ffmpeg_cmd2 = "ffmpeg -i $file_final -ss $thumb_position -t 00:00:01 -s 100x68 -r 1 -f image2 $file_th";
echo "-- Crear thumbnail (2): $ffmpeg_cmd2\n";
exec("$ffmpeg_cmd2 2>&1", $output); }
// Es exactamente el mismo proceso para la imagen de vista previa
// Solo cambiamos el tamaño para que sea igual que el video: -s 450x300
// Y reemplazamos la variable $file_th por $file_pre
echo "$curvid fue convertido correctamente!!!\n\n";
}
echo "Proceso finalizado.\n";
Notas:
- La funcion
sec2hms() es la misma que aparece en el primer mensaje, asi que no tiene caso repetirla.
- En Windows todo trabaja como debe ser, probando videos 3gp, mov, m4v, mp4, wmv, avi y flv.
- Si quieren cambiar la calidad del video generado, el parametro -qscale puede tener valores entre 1 (maxima calidad) y 31 (lo mas bajo)... dejandolo en 10 creo que tiene una excelente relacion tamaño de archivo/calidad.
- Lo de la marca de agua no pude hacerlo funcionar en linux porque mi version ya no tiene soporte (Ubuntu 6.06 LTS) y el unico codec/filtro que no pude instalar es el requerido para esto (avfilter-lavf)... si alguien puede instalar todo sin problemas le agradeceria cualquier comentario sobre el tema, para irme preparando... pronto cambiaremos el servidor.
Como decia un gran amigo mio: Capri, c'est fini