miércoles, 20 de febrero de 2008

ffencoderd el demonio de YouTube

Bueno esta vez solo quería comentaros sobre el nuevo proyecto en el que me he embarcado. Despues de decidirse que en el nuevo portal que estoy desarrollando debía incluirse una sección de videos estilo YouTube, empecé ha indagar por la red para ver si encontraba la manera de facilitar a los usuarios la codificación de videos a formato flv sin penalizar nuestro pobre servidor demasiado.
Mi idea era encontrar algún tipo de programa que permitiese programar las conversiones de formatos, idealmente este sería un servidor independiente que permitiese codificar, y servir los videos una vez codificados.
Pues despues de unos días (no intensivos) de búsqueda solo encontré la solución de On2, los mismos que desarrollaron uno de los codecs que pueden utilizarse nativamente en flash video. Su solución, de pago obviamente, incluia un pequeño servidor con un servicio rpc permitiendo la interactuación para enviar videos a ser codificados, realizar un seguimiento de la conversión y obtenerlos codificados.
On2 lo llama flixd o la solucion completa (cliente/servidor) Flix Engine/SDK. Proporciona implementaciones para C/Java/Perl y Python, también parace que hay disponible una par a ruby (no lo sé, eh! no conozco ruby)
ffencoderd intenta realizar unas funciones similares a las de flixd, aunque por el momento solo realiza las funciones básicas espero que pronto pueda tener tiempo para desarrollarlo e implementar funcionalidades como servicio soap y servicio http para servir los videos.
Por ahora este pequeño demonio (daemon ;) permite programar diferentes conversiones utilizando ficheros xml para definir un proceso de conversion y obtener los datos de los ficheros convertidos. Junto con el programa se ha adjuntado un ejemplo de implementacion en php. Vamos a ver como utilizariamos ffencoderd en un entorno PHP.
Lo primero sería descargar ffencoderd de http://ffencoderd.sourceforge.net , disponer de ffmpeg,PHP y Perl instalados en nuestro sistema (opcionalmente perl y ffmpeg en el servidor donde se ejecutará el proceso de ffencoderd y PHP en el servidor desde donde se servirán los videos).
Una vez tengamos descargado ffencoderd descomprimimos los contenidos en cualquier carpeta de nuestro sistema, lo primero será crear un fichero de configuración para ello encontraremos una versión inicial en la carpeta 'ffencoderd/doc' editamos el fichero para que coincida con nuestro sistema, cada opcion esta comentada en el fichero original. En principio los cambios necesarios serán los parametros referentes a los directorios y ficheros utilizados/creados por ffencoderd.
A revisar :
  • output.file : ruta y nombre del fichero de salida (ej: /home/iago/ffencoderd.xml)
  • process.dir : ruta hacia el directorio albergando los ficheros de procesos
  • video.output.dir : ruta hacia el directorio albergando los videos codificados
  • video.input.dir : ruta hacia el directorio albergando los videos sin codificar
  • pid.dir : ruta hacia una carpeta cualquiera, normalmente /var/run
  • log.dir : ruta hacia una carpeta cualquiera, este directorio albergara los archivos de registro
  • data.dir : ruta hacia un directorio cualquiera, este directorio albergara los ficheros que crea ffencoderd durante la ejecución
Una vez revisado el fichero de configuracion, solo debemos ejecutar en la linea de comandos el archivo principal "ffencoderd.pl" , este acepta varios parametros, puede utilizarse el parametro '-h' para ver todos los parametros aceptados. Nosotros por el momento solo utilizaremos el parametro '-c' que nos permite indicar el fichero de configuracion que deseamos utilizar.
En una consola ejecutamos ffencoderd:
'./ffencoderd.pl -c fichero_configuracion'
Esto iniciará el programa, lo pasará al background y nos devolverá a la consola. Podemos verificar si el se ha puesto en marcha utilizando 'ps -HA|grep ffencoderd', debería devolver una linea como '/usr/bin/perl -X ./ffencoderd.pl ...'
Esto significa que el proceso esta funcionando correctamente, si hemos habilitado el registro (definiendo true en el parametro del fichero de configuración 'log') también podemos verificar el funcionamiento en la carpeta que se ha definido en 'log.dir'.
Bien ahora ya podemos enviar video para ser codificados, los videos deben copiarse a la carpeta definida en 'video.input.dir', esto lo podemos hacer utilizando cualquier método en el servidor, con PHP, via FTP, SSH...
En la carpeta 'doc/php' hay un ejemplo de interfaz en PHP, los archivos Ffencoderd.php, Process.php y IProcess.php.
En la misma carpeta encontramos un ejemplo de utilización en Example.php, a continuación se detalla un poco este archivo.

Instanciamos la interfaz de ffencoderd, el primer parametro es el archivo que ffencoderd crea con su salida, este concuerda con el parametro 'output.file' el segundo parametro es el directorio que ffencoderd lee para los procesos corresponde a 'process.dir'
$ffencoderd = new Ffencoderd('http://localhost/ffencoderd/ffencoder.xml','/opt/ffencoderd/process/');
Añadir un nuevo proceso, para ello instanciamos la clase Process, el primer parametro sera un identificador unico para el proceso, podemos utilizar cualquier tipo, en principio un entero nos servirá
$process = new Process(1,'ser5.mov','220x300');
Añadimos el proceso para ser procesado
$ffencoderd->addProcess($process);
Comunicamos a ffencoderd que ya puede codificar, se ha finalizado el envio
$ffencoderd->process();

Ahora si queremos podemos verificar si ffencoderd ha terminado de codificar el video utilizando
$ffencoderd = new Ffencoderd('http://localhost/ffencoderd/ffencoder.xml','/opt/ffencoderd/process/');
$process = new Process(1,'ser5.mov');
$status = $ffencoderd->verify($process);
switch($status){
case Ffencoderd::PROCESS_OK :
echo "
Video encoding process ended";
break;
case Ffencoderd::PROCESS_IN_WORK:
echo "
Video encoding process in work";
break;
}

lunes, 4 de febrero de 2008

La clase Locale de AS3, internacionalización en actionscript 3

Como no me fue fácil decubrir cómo funcionaba la clase Locale en AS3, quería dejarlo para la bitácora por si a alguién le puede ser útil.
Éste es un método para permitir internacionalizar una aplicación flash, ActionScript 3, este método no puede utilizarse con ActionScript 2. Además éste método es para utilizar principalmente con FlashDevelop, supongo que con Flash CS3 IDE puede también hacerse pero no lo he probado.
Primero ActionScript 3 tiene soporte para los archivos XLIFF , este es una especificación para archivos XML, lo básico es que debemos crear un archivo por cada idioma que queramos implementar con el siguiente formato. Al crear este archivo XML debemos vigilar de utilizar una codificación UTF-8, si lo creamos con notepad al guardar se puede definir el tipo de codificación en el desplegable de debajo del nombre del arhivo a guardar.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN"
"http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
<xliff version="1.0" lang="es">
<file datatype="plaintext" original="ICCS.swf" language="ES">
<header></header>
<body>
<trans-unit id="010" resname="VER_TODO">
<source>Ver todo</source>
</trans-unit>
</body>
</file>
</xliff>



Una vez creado nuestro archivo lo guardamos en cualquier carpeta dentro de nuestro proyecto (o en cualquier lugar del sistema), lo único que debermos indicarle a la clase Locale donde se halla cada archivo de localización (nuestro archivos XML). Podemos utilizar una ruta absoluta o relativa, aunque aconsejo que sea relativa y ubicar la carpeta dentro de la misma carpeta donde se encuentra nuestro SWF principal.
Para cargar los archivos de localización y poder utilizarlos dentro de la aplicación, debemos definir en nuestro método principal las siguientes lineas:
package {
...
import flash.Locale.*;
...
Locale.addXMLPath("es", "lang/es.xml");
Locale.initialize();
Locale.setDefaultLang("es");
Locale.setLoadCallback(init);
....
public function init(success:Boolean):void {

trace(Locale.loadString("ID_PRUEBA"));
}

Bien, estas lineas cargarán los archivos de localización y el método loadString nos permite llamar a nuestras traducciones en el idioma definido.
Así por encima los métodos que llamamos hacen lo siguiente:
Locale.addXMLPath(id,path) , añade al listado interno la ruta y el identificador del archivo de localización, luego Locale.initialize() inicializa la instancia con todos los idiomas, Locale.setDefaultLang define el idioma principal a utilizar y Locale.setLoadCallback(funcion) define la funcion que se llamara una vez finalizada la carga de los archivos de localización.
Una vez finalizada la carga podremos llamar al método Locale.loadString(id_traduccion) el cual nos devuelve la traduccion referenciada por el id proporcionado en el idioma definido.