Archivo de la categoría: Técnico

Convierte tu móvil 3G en un punto de acceso wifi con JoikuSpot

Hace unos días tuve un problema, necesitaba conectar dos portátiles a Internet simultáneamente pero sólo disponía de un teléfono 3G, así que, o conectaba uno o conectaba el otro. Buscando por Google llegué a JoikuSpot, una aplicación para Symbian que convierte tu teléfono 3G en un router inalámbrico. Sí, como lo has oído, lo mismo que hacen esos routers pero con un sencillo teléfono S60.

Además de la ventaja de compartir la red, me pareció interesante disponer de  un método de conexión portátil/teléfono alternativo y estándar al Bluetooth y al cable USB.

Obviamente este método sólamente sirve para terminales que dispongan de conexión wifi 😛 . En mi caso tengo un Nokia E51 que la tiene, así que es un dispositivo con dos interfaces de red, la wifi por un lado y la conexión dinámica 3G/HSDPA por el otro, lo mismo que un router normal y corriente.

Existen dos versiones de JoikuSpot,  Light (gratis) y Premium (en oferta por 15$). La diferencia fundamental es la cantidad de protocolos soportados. Mientras que con la primera sólamente tienes HTTP/HTTPS, con la segunda tienes prácticamente todos los necesarios para una navegación completa (smtp, pop3, vpn, messenger, skype…). Para el uso que le voy a dar yo me es suficiente con la versión Light, al menos por el momento.

Una vez descargada habrá que configurar el punto de acceso inalámbrico con los parámetros típicos de cualquier router: nombre de la red, canal, tipo de autentificación, clave…

screenshot0003.jpg

Una vez tenemos nuestro punto de acceso wifi bien configurado no tenemos más que iniciarlo, para lo cual nos pedirá qué punto de acceso de datos queremos utilizar para salir a Internet. Seleccionamos nuestra conexión 3G/HSDPA y nuestro móvil ya será un router inalámbrico.

screenshot0001.jpg

En todo momento tenemos información del tráfico y el tiempo de conexión.

screenshot0002.jpg

Ahora podemos buscar la red inalámbrica desde los portátiles. Veremos que en la lista de redes aparece una nueva con el nombre que le hemos puesto al configurar JoikuSpot. Nos conectamos indicando la clave y por arte de magia tenemos conexión a Internet en todos los equipos que se conecten a nuestro móvil.

screenshot0009.jpg

Todo muy sencillo de configurar.

Una alternativa más que útil para emergencias (Noooooo, no funciona Internet) o viajes.

Screenshot

Para los que se estén preguntando cómo hago las capturas de pantalla directamente desde el móvil, os recomiendo Screenshot, una aplicación Symbian libre para realizar capturas de pantalla y que te permite definir la combinación de teclas que dispararán la captura. Llevo utilizándolo mucho tiempo y siempre me ha dado muy buenos resultados.

WordPress Global Translator Plugin, traducciones de tu blog en 34 idiomas

Llevaba un tiempo con la idea de añadir traducciones de los artículos más leídos pero no quería tener que hacerlo a mano. Había barajado la posibilidad de linkar directamente a las herramientas de idioma de Google, sin embargo esta mañana encontré un plugin que lo hace todo automáticamente de manera mucho más elegante ya que, utilizando las API’s de distintos servicios de traducción (Google, Babelfish…), genera los artículos en los demás idiomas completamente integrados en tu blog y, además, los cachea para mejorar el rendimiento.

traduccion.jpg

Una vez instalado debes activar el plugin desde el panel de administración de tu WordPress y configurarlo indicando qué motor de traducción vas a utilizar, cuál es el idioma nativo de tu blog y cuáles de las 34 traducciones posibles vas a mostrar en tu blog. Es recomendable reducir al principio el parámetro “Allow only a traslation request every X seconds” a un valor pequeño para que se generen rápidamente las traducciones de todos tus artículos y se cacheen correctamente, posteriormente podrás aumentarlo sin problemas.

Eso es todo, verás en la sidebar de tu blog el nuevo bloque con las banderas de los idiomas que hayas habilitado.

Os recuerdo que un sistema de traducción automático es éso mismo, automático, no esperes que las traducciones sean correctas ni mucho menos, es algo aproximado para entender el texto traducido, no una traducción fiel y real.

Mi nuevo juguetito, LG X110

Es lo bueno de la Navidad, los regalos 😛 . Sin esperarlo me ha caído un netbook, el LG X110. Llevaba mucho tiempo mirándolos en todas las tiendas y leyendo comparativas y he de decir que, junto al Samsung NC10, era el que más me gustaba. En general son los dos el mismo modelo y vienen del famoso MSI Wind al igual que muchos otros netbooks (Medion Akoya, Advent 4211, Ahtec Netbook N011…).

LG X110

Las prestaciones, las típicas, son todos muy parecidos, Atom 1,6Ghz, 1Gb de Ram, 160Gb de disco, webcam, wifi y bluetooth en algo menos de 1,2kg . Es precisamente el bluetooth lo que lo diferencia de los demás modelos ya que es de los pocos que lo traen.

Todavía no he podido probarlo mucho, pero puedo decir que va ligero, sin agobios y arranca rápido. En cuanto a pegas, la primera que he notado es el ratón, la superficie es algo rugosa lo cual quita agilidad y, sobre todo, los botones (izquierdo y derecho), son realmente malos, poco sensibles y de baja calidad en general.

La otra pega es la típica en este tipo de dispositivos, la batería de 3 celdas es completamente insuficiente, no llega a las dos horas (1:45 aproximadamente) funcionando con wifi (y con el bluetooth apagado, si lo enciendes es aún peor). Éste era el punto fuerte del Samsung NC10 que comentaba antes ya que viene con batería de 6 celdas de serie.

También se echa de menos hoy en día un modem 3G, creo que todos estos netbooks deberían traerlo ya puesto que todos acabaremos con uno de ellos. Yo me lo compraré durante las próximas semanas  para utilizar con Simyo, mientras tanto lo utilizaré junto a mi Nokia E51 a través del cable USB, una opción más que satisfactoria ya que ofrece conectividad HSDPA.

Decir ante todo que me viene de lujo para llevarme encima en las escapadas y viajes que suelo hacer y poder hacer frente a las urgencias que puedan surgir (muchas más de las que me gustarían). Ahora viene lo peor, los complementos al juguete: batería de 6 o 9 celdas (imprescindible), la funda (sería una pena que se rayase) y el modem 3G. El caso es seguir gastando 😛 .

Otras utilidades para un servidor de correo

A veces un servidor de correo puede sernos de muchísima utilidad si sabemos cómo manejarlo correctamente. En el artículo de hoy veremos como utilizar nuestro MTA para ejecutar automáticamente acciones cuando se recibe un determinado email o con los parámetros que definamos. Una vez conozcamos la teoría plantearemos dos casos prácticos como ejemplo.

Para comenzar necesitaremos un servidor Linux con Qmail como MTA. Supongo que cualquier otro servidor de correo servirá (Sendmail, Postfix), yo lo personalizo en Qmail porque es el que conozco y utilizo, pero estoy seguro de que con los demás se puede hacer lo mismo.

La teoría

Para entender cómo funciona la idea debemos entender primero cómo Qmail realiza la entrega de mensajes en los buzones locales. Es un tema sobre el que hay bastante literatura buscando en Google pero que puede no quedar muy claro en una lectura rápida. Es el famoso lío de los archivos .qmail.

Cada vez que se crea un usuario del sistema se debe crear, si va a recibir emails, un archivo .qmail-default en su directorio de usuario.

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-default
./Maildir/

Normalmente este archivo se crea automáticamente ya que al instalar qmail se habrá creado una copia de este archivo en el esqueleto de creación de usuarios /etc/skel:

[jiglesias@lerez ~]# ls -la /etc/skel
total 56
drwxr-xr-x  4 root root  4096 Jul 29 18:29 .
drwxr-xr-x 97 root root 12288 Dec 30 04:08 ..
-rw-r--r--  1 root root    33 Feb  1  2008 .bash_logout
-rw-r--r--  1 root root   176 Feb  1  2008 .bash_profile
-rw-r--r--  1 root root   124 Feb  1  2008 .bashrc
drwx------  5 root root  4096 Aug 29  2007 Maildir
-rw-r--r--  1 root root    12 Jan  2  2008 .qmail-default
-rw-r--r--  1 root root   658 Sep 12  2006 .zshrc

Para el que no lo sepa, el esqueleto son los archivos que se copiarán al directorio de usuario (con los permisos de éste) cada vez que se crea uno nuevo. Si quieres que todos tus usuarios tengan algún archivo automáticamente, éste es tu sitio. En nuestro caso vemos que además del .qmail-default está el directorio Maildir, el de entrega por defecto del correo en qmail. Teniendo un usuario este archivo y este directorio, podrá recibir correo.

Vale vale, vas muy deprisa. Todavía no has explicado para que sirve el .qmail-default ese.  Cierto. Los archivos .qmail indican las reglas de entrega de los mensajes en base a dos parámetros:

  • El nombre del archivo .qmail-xx hace referencia a la cuenta de correo sobre la que actúa.
  • El contenido indica qué hacer con el correo.

Supongamos un usuario (jiglesias)  que recibe el correo de dos cuentas distintas (jiglesias@… y osus@…).

Por defecto todo su correo irá a su buzón ya que es lo que indica el archivo .qmail-default. Queremos ahora que el comportamiento sea distinto dependiendo de la cuenta a la que vaya dirigido, creamos entonces los archivos .qmail para las direcciones:

  • .qmail-jiglesias : controla el correo que vaya a jiglesias@…
  • .qmail-osus : controla el correo que vaya a osus@…

Podemos incluso ir un poco más lejos con un archivo .qmail-jiglesias-default, y controlaríamos el correo que vaya a cualquier dirección del tipo jiglesias-XXXX@…, es decir, cualquier dirección que comience por jiglesias- será controlada por este archivo .qmail.

En el caso básico, que es el que veíamos, la entrega se realiza al buzón de correo del usuario (el directorio Maildir) pero podríamos hacer otras cosas en función del contenido del archivo .qmail encargado de procesar la entrega del correo:

Reenvío a otra cuenta:

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-jiglesias
[email protected]

Reenvío a un programa/script:

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-osus
|preline /usr/bin/programa

Combinación de los anteriores

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-jiglesias
./Maildir/
[email protected]
|preline /usr/bin/programa

El caso que nos interesa es el segundo, es decir, pasar la entrega del email a un script que se encargará de analizar el email y tomar decisiones.

Te habrá llamado la atención el |preline del archivo .qmail. Es el sistema que prepara un email para ser procesado y entregado a otro script añadiendo algunas cabeceras. La salida del script que reciba el email es importante ya que de ella depende el resultado de la entrega final de email, en concreto es importante saber que si queremos rechazar un email habrá que terminar el script con un exit (100), esto indicará a qmail que debe rechazar ese mensaje. Veremos más adelante la utilidad de esta salida.

La práctica

Una vez sabemos cómo pasar el control de un email recibido a un script, veamos como tratarlo. Lo haremos con un script PHP. En nuestro archivo .qmail haremos algo como:

[jiglesias@lerez ~]# more .qmail-jiglesias
|preline /usr/bin/php /home/jiglesias/prueba.php

Con esto hemos terminado el trabajo en el servidor de correo. Veamos ahora como parsear el email desde PHP.

Lo primero que debemos hacer es recoger el contenido del email desde el script a través de la entrada estándar,  después ya podemos procesar el email como una cadena de texto.

<?php
$email=file("php://stdin");
$email=implode("", $email);
?>

Con estas sencillas dos líneas de código tendremos en nuestro script el contenido del email. Ahora sólamente debemos procesarlo. Podemos hacerlo línea por línea por nuestra cuenta o apoyarnos en alguna librería. Yo utilizo Mail_mimeDecode de Pear. La ventaja de esta librería es que podemos obtener, además del texto del email, los archivos adjuntos.

<?php
$email=file("php://stdin");
$email=implode("", $email);
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $email;
$structure = Mail_mimeDecode::decode($params);
$subject = trim($structure->headers['subject']);
$ddate = trim($structure->headers['date']);
$from = addslashes(trim($structure->headers['from']));
if(ereg("<(.*)>", $from, $p)) $from=$p[1];
if(ereg(""(.*)"", trim($structure->headers['from']), $pp))
    $nombre=$pp[1];
?>

Así podemos ya procesar el email y tomar las decisiones que consideremos oportunas. Podremos insertarlo en una base de datos, lanzar otros procesos automatizados, enviar avisos por SMS… lo que se nos ocurra.

Casos prácticos

La pregunta clave, después de ver la teoría, sería ¿para qué me sirve esto?.  Os propongo dos aplicaciones que yo he hecho.

Sistema de soporte

El típico sistema de tickets de soporte. En el asunto del email se arrastra el identificador del ticket, por ejemplo [#123445]. Tendremos que analizar el asunto y comprobar si aparece el patrón predefinido. Si no existe estamos ante un nuevo ticket e insertamos los datos en nuestra base de datos, en caso contrario es una respuesta a una incidencia anterior y ahí tendremos el identificador. Sencillo ¿no?. Podemos incluso adjuntar a nuestras indicendias archivos que puedan llegar en el email.

Envío de archivos desde el movil

El segundo ejemplo sería semejante al anterior técnicamente pero distinto conceptualmente. La mayoría de los móviles (salvo los de gama alta) no pueden enviar archivos desde los formularios wap (<input type=”file”>). La alternativa es que el usuario envie un email o un MMS (la mayoría de operadoras permiten el envío a direcciones de email) con sus archivos. Nuestro script procesará el contenido del mail recibido, decodificará los archivos y los tratará como sea oportuno.

Son dos sencillos ejemplos de cómo utilizar el email para automatizar tareas, pero, como he comentado, podríamos hacer todo lo que se nos ocurra, desde enviar un SMS de aviso hasta incluso reiniciar nuestro servidor o lanzar cualquier otra tarea.

Centro de Sistemas de la Xunta de Galicia, las cosas bien hechas

Hace algo más de un mes recibí un email de Marcos avisándome que no podía enviar emails a cuentas del dominio xunta.es, a los diez días le venían rebotados con un error de conexión. Hasta entonces siempre había funcionado bien, pero llevaban ya unos días con el problema. Haciendo una análisis detallado desde el servidor obteníamos lo siguiente:

[osus@lerez ~]# dig xunta.es
; <<>> DiG 9.3.4-P1 <<>> xunta.es
;; global options: printcmd
;; connection timed out; no servers could be reached

[osus@lerez ~]# dig @85.91.64.171 xunta.es
; <<>> DiG 9.3.4-P1 <<>> @85.91.64.171 xunta.es
; (1 server found)
;; global options: printcmd
;; connection timed out; no servers could be reached

[osus@lerez ~]# dig @85.91.64.172 xunta.es
; <<>> DiG 9.3.4-P1 <<>> @85.91.64.172 xunta.es
; (1 server found)
;; global options:  printcmd
;; connection timed out; no servers could be reached

[osus@lerez ~]# ping 85.91.64.171
PING 85.91.64.171 (85.91.64.171) 56(84) bytes of data.
64 bytes from 85.91.64.171: icmp_seq=1 ttl=45 time=184 ms
--- 85.91.64.171 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 184.025/184.025/184.025/0.000 ms

[osus@lerez ~]# ping 85.91.64.172
PING 85.91.64.172 (85.91.64.172) 56(84) bytes of data.
64 bytes from 85.91.64.172: icmp_seq=1 ttl=45 time=173 ms
-- 85.91.64.172 ping statistics ---
2 packets transmitted, 1 received, 50% packet loss, time 1000ms
rtt min/avg/max/mdev = 173.111/173.111/173.111/0.000 ms

[osus@lerez ~]# telnet 85.91.64.172 53
Trying 85.91.64.172...
Connected to 85.91.64.172 (85.91.64.172).
Escape character is '^]'.
Connection closed by foreign host.

Donde 85.91.64.171 y 85.91.64.172 son los servidores DNS de xunta.es.

Como se puede ver en el resultado de las pruebas, conectividad con los servidores DNS sí que había, respondían al ping, no había ningún tipo de bloqueo, sin embargo el servidor DNS no aceptaba nuestras solicitudes, con lo cual no podíamos resolver ningún host de xunta.es. Era ése precisamente el error que reportaba nuestro MTA cuando devolvía los emails, no se ha encontrado el servidor de destino (como no podía resolver los servidores MX asumía que el dominio no existía).

Decido entonces ponerme en contacto con el centro de sistemas y el primer mensaje no se me ocurre otra cosa que escribirlo con una cuenta desde la misma máquina que fallaba. Me llegó devuelto a los diez días tal como acabo de describir, pero me sirvió para ver con mis propios ojos el problema. Volví a escribir con una cuenta de otra máquina explicándoles el problema y las pruebas que os he copiado.

En un primer momento me contestan que, tras abrir una incidencia con el centro de gestión de red,  no tienen ningún problema de conectividad y que deberíamos tener acceso.

Abrín incidencia co centro de xestión de rede da Xunta de Galicia, e dinme que en principio non debería haber ningún problema co acceso ó noso servidor dende a vosa ip, polo que deberíades poder enviar sen problemas.

Entre otras cosas me indican, además, que haga una prueba de acceso al servidor de correo. Obviamente no han entendido bien que el problema es sólamente la resolución DNS, el resto funciona correctamente.

El 23 de noviembre vuelvo a escribirles explicando que el problema no es la conectividad, es sólo la resolución DNS y que al no poder resolver estamos cerrando a nuestra máquina cualquier host de xunta.es, adjuntando de nuevo las pruebas realizadas.

Unos días después me contestan que han hecho algunos cambios en sus DNS, que comprobemos si ya funciona, pero sigue sin hacerlo y así se lo hago saber el 1 de diciembre y les indico además, por si quieren hacer pruebas, el entorno (sistema operativo, versión de bind…).

10 días despues me contestan, atención:

Non me olvidei do voso problema co dns da Xunta… Simplemente comentarche que escalei a incidencia ó Centro de Xestión de Rede e como non me respostaran onte volvín a enviarlle a consulta e dinme que están preparando un escenario para reproducir o voso problema, porque en principio non hai ningún filtro no dns que impida que unha ip como a vosa realice consultas ó dns… Creo que van montar unha máquina cunha ip como a vosa para facer probas, mantereite informado dos progresos nas súas probas.

Es decir, que escalaron de nuevo la incidencia al centro de gestión de red y que, como no encontraban ningún problema,  iban a replicar nuestro entorno con nuestra misma IP para probar y ver in situ la situación.

Al día siguiente nos informan que, efectivamente, han visto el error que comentábamos y que nos avisarían cuando lo solucionasen. La verdad, temía que a ellos sí que les funcionase, pero no fue así.

Un par de días más tarde nos avisan que la incidencia está ya resuelta, que hagamos las pruebas oportunas para comprobarlo. En efecto, ahora todo volvía a funcionar correctamente.

En todo momento pensé que el problema iba a quedar sin solucionar, era bastante escéptico y creía que jamás se preocuparían por ver qué estaba pasando, sin embargo ocurrió todo lo contrario. Muchos centros de soporte y de sistemas deberían tomar nota y aprender de este caso. Hay ocasiones en que aunque parezca que tus sistemas están bien porque a todo el mundo le funcionan, puede haber algún caso aislado que presente una incidicencia que sea problema tuyo y no de él. El clásico “si a todo el muno le funciona es que funciona y si a uno no le va, será problema de él“, puede no ser siempre correcto, pero hay que molestarse en comprobarlo. Sé de buena tinta que en la inmensa mayoría de sitios habrían pasado de nosotros y mucho menos aún se habrían tomado las molestias de replicar nuestro escenario para comprobar lo que les contábamos.

Desde aquí dar las gracias a Silvia, la persona que se responsabilizó de nuestra incidencia y que puso todo su empeño en encontrar la solución, y agradecer a todo el Centro de Xestión de Rede de la Xunta de Galicia su colaboración y ayuda. No me han dicho el origen del problema, entiendo que puede ser información confidencial en cuanto a tipología de redes, firewalls, DMZ’s… pero el trabajo ha sido excelente.

Conversión de vídeos a 3gpp bajo demanda en un entorno web

Hoy veremos como aplicar conversiones de vídeo en un entorno web donde los usuarios suben sus vídeos en cualquier formato. Sí, tienes razón, ni más ni menos que lo que hace YouTube, de hecho utilizaban un sistema muy similar a lo que veremos ahora y basado en el mismo software. En realidad el artículo se podría aplicar a prácticamente cualquier tipo de conversiones, incluso para iPod o PSP, sólo hay que utilizar los parámetros adecuados. Nosotros nos centraremos en la conversión a 3gp para después poder hacer streaming con ellos además de permitir su descarga.

Nuestro entorno se basará en un servidor con Linux (Centos5 en mi caso). Como software sólamente necesitaremos ffmpeg, herramienta imprescindible para cualquier aplicación (tanto web como de escritorio) bajo Linux.

¿Qué es ffmpeg?

Hace unas semanas veíamos cómo utilizar ffserver para convertir flujos de vídeo y hacer streaming. ffmpeg es la utilidad en la que se apoya ffserver para realizar las conversiones.

ffmpeg es una herramienta de software libre que permite realizar conversión entre la mayoría de formatos de vídeo más utilizados. Una inmensa mayoría de programas de conversión bajo Windows no son más que frontends gráficos para ffmpeg.

Normalmente los paquetes precompilados de ffmpeg no vienen con las extensiones adecuadas para las conversiones que necesitamos, así que deberemos compilar nuestra propia versión.

Necesitas instalar los siguientes paquetes, son más de los imprescindibles, pero así nos ahorraremos problemas futuros:

libmp4v2
libvorbis
libvorbis-devel
lame
lame-devel
faac
faac-devel
faad2
x264
x264-devel
xvidcore
xvidcore-devel

Debo decir que para mi Centos no están todos disponibles como rpm con lo cual habrá que compilar manualmente algunos de ellos. No deberías tener ningún problema para localizar cada librería.

Finalmente habrá instalar los siguientes paquetes:

http://ftp.penguin.cz/pub/users/utx/amr/amrnb-7.0.0.2.tar.bz2

http://ftp.penguin.cz/pub/users/utx/amr/amrwb-7.0.0.3.tar.bz2

Con esto tenemos ya todo preparado para compilar nuestro propio ffmpeg. Descarga el paquete desde la web oficial, descomprímelo y:

./configure --enable-libmp3lame --enable-libvorbis --enable-libogg --enable-libamr-nb --enable-libamr-wb --enable-libfaac --enable-gpl --enable-libxvid --enable-libx264 --enable-libfaad --enable-shared
make
make install

Si has seguido bien todos los pasos tendrás el software de conversión preparado.

Convirtiendo a 3gp

Para realizar las conversiones algo tan sencillo como:

ffmpeg -y  -i original.avi -s qcif -r 12 -b 30 -ac 1 -ar 8000 -ab 12200 video.3gp
/usr/local/bin/MP4Box -3gp -mtu 1450 -hint video.3gp

Cuando vimos cómo hacer streaming a móviles veíamos como utilizar la utilidad MP4Box para que nuestros vídeos 3gp se puediesen utilizar para emitir en vivo.

Para nuestro proyecto es probable que necesitemos algo más. Si queremos que también se puedan visualizar los vídeos desde una web necesitaremos convertirlos a flv:

ffmpeg -y -i original.avi -acodec libmp3lame -ac 2 -ar 22050 -r 12 -b 196 -s 176x144 video.flv
/usr/bin/flvtool2 u video.flv

Flvtool es una herramienta que inserta en los flv los metadata necesarios para que funcione bien en el reproductor flash.

Y necesitaremos capturar algún fotograma del vídeo para mostrar como demo:

ffmpeg -i original.avi -y -ss 00:00:01 -vframes 1 -an -sameq -s 160x120 -f image2 thumbnail.jpg

Ahora ya sabemos:

  • cómo crear nuestro vídeo 3gp que nos sirva tanto para descarga como para streaming.
  • cómo crear el vídeo flv que nos sirva para ver vía web.
  • cómo generar thumbnails de escenas del vídeo.

Creando el entorno web

Supongamos que queremos desarrollar una web al estilo Youtube donde el usuario sube vídeos desde un formulario y posteriormente se desea mostrarlos categorizados, con un buscador, una preview (flv), descarga para móviles, etc.

La parte de la web propiamente dicha resulta obvia, no vamos a entrar en detalles. Lo que nos ocupa aquí es como realizar la conversión según las instrucciones que hemos visto. Obviamente no podemos ejecutar la conversión cada vez que un usuario sube un vídeo, sería un proceso lento y pesado. La mejor manera es crear una cola de conversión. Cuando se sube un nuevo vídeo no esta disponible públicamente (no se ha convertido todavía). Podríamos definir tres estados diferentes para un video:

  1. Sin procesar (convertir).
  2. Procesando.
  3. Procesado.

Según esto sería sencillo tener en una tabla el estado de los vídeos. Sólo los procesados se listarían públicamente.

Por otro lado tendríamos una tarea encargada de buscar vídeos en estado “sin procesar” y realizar su conversión. Esta tarea podría ser o bien un demonio residente que está permanentemente buscando vídeos o bien, si el tráfico de nuevos vídeos no va a ser elevado, podría ejecutarse periódicamente para realizar las conversiones.

Si el tráfico fuese muy elevado podría incluso haber varias tareas en paralelo ya que una vez una de ellas encuentra un vídeo “no procesado” actualiza su estado a “procesando” de manera que la siguiente tarea ya no escogerá ese mismo vídeo.

La teoría es mucho más sencilla de lo que parece. La tarea que realiza la conversión creará los formatos que estimemos oportunos según ya hemos visto antes.

Convirtiendo a otros formatos

Con ffmpeg se pueden generar los vídeos para casi cualquier formato existente incluyendo PSP, iPod/iPhone/iTouch… Googleando un poco encontrarás los parámetros adecuados para cada formato.

Conclusiones

En este artículo he explicado cómo realizar conversiones de vídeos a distintos formatos y cómo aplicarlo a un entorno web dónde los usuarios suben sus propios vídeos. He dado los pasos básicos para entender el sistema, vosotros tendríais que adaptarlo a vuestras necesidades.

Oh-la-la, París ida y vuelta

Desayuné en Valencia, comí en París y cené en Valencia. Fin a una semana de estrés y tensión.

Hace un par de semanas, nos avisaron un viernes a mediodía de que teníamos que exponer oralmente (en inglés) la parte ténica de un proyecto al que nos habíamos presentado ante un comité de expertos de nuestro potencial cliente. La reunión sería el martes siguiente, así que tendríamos tres días, de los cuales dos eran fin de semana, para preparar nuestra presentación. Conseguimos posponerlo hasta el jueves, así que allí nos fuimos Guillermo y yo hacia París tras una semana trabajando como chinos (con todo el respeto al colectivo oriental).

Estas son nuestras caras a las seis de la mañana en el aeropuerto de Valencia, sin apenas haber dormido en los cinco días anteriores y con los nervios a flor de piel.

img_4571.JPGimg_4572.JPG

Impresionante la vista aérea de los Pirineos con ese manto de nieve…

Pirineos

Ya desde nuestra llegada a París el inglés se convirtió en nuestro idioma, no sólo con el cliente sino también con nuestros partners en Francia. Al final fueron cerca de 8 horas hablando y pensando exclusivamente en inglés.

La presentación consistía en tres partes:

  1. Arquitectura funcional
  2. Arquitectura técnica
  3. Calidad y SLA

Yo exponía la segunda. Habíamos preparado concienzudamente el contenido de nuestras presentaciones puesto que, además de comentar nuestra solución al proyecto, era más que probable que nos disparasen cañonazos de preguntas, como así fue.

Inicialmente estaban estipuladas dos horas de exposición, pero al final estuvimos cerca de dos horas y media vendiendo nuestra idea y nuestra solución. Mi exposición en particular se alargó más de una hora con constantes intervenciones de los asistentes por parte del cliente y al final se abrió un pequeño “ruegos y preguntas” aunque prácticamente se había contestado todo sobre la marcha.

Parece que les gustaron nuestras ideas y opiniones a los galos.

img_4582.JPGimg_4583.JPG

Al final, entre que se nos alargó la exposición más de la cuenta y que el tráfico en París es un caos, estuvimos a punto de perder el avión de vuelta.

La prueba de que, en efecto, era París 😛 .

Aeropuerto de Paris

Conclusiones

¿Qué he aprendido de esta experiencia?

  • Tenemos muy mal concepto de nosotros mismos al hablar en inglés, tal como nos decía uno de nuestros colaboradores en Francia, habláis claro y fluído, más que suficiente para mantener una conversación sin dificultades. Puede que gramaticalmente no sea perfecto, pero entendéis y se os entiende y se puede mantener una conversacion con vosotros sin ningún problema. Nos puso como ejemplo a los indios (de la India), que hablan un inglés gramaticalmente perfecto pero a los que no se les entiende absolutamente nada por el acento que tienen. He hecho muchas referencias al inglés porque, en realidad, era nuestro único problema. Ni hablar en público ni exponer tus conocimientos nos supone un problema, la parte técnica la tenemos ampliamente controlada, no en vano es nuestro trabajo. La barrera idiomática sí que es un hándicap, y salimos airosamente. Sólo decir que acabamos hablando de la crisis y de la burbuja inmobiliaria en España 😉 .
  • Otro de nuestros partners salía de la reunión asombrado de la manera en que habíamos sacado adelante la situación, en cómo habíamos jugado nuestras cartas ante la indiferencia inicial del cliente y su interés final.  Y todo esto “en inglés”. A veces las cosas son mucho más sencillas de lo que creemos. Si no vendes humo, si conoces el entorno y la materia sobre la que tienes que hablar, es difícil que te dejen quedar mal. Recuerda también que, igual que no hay que decir a todo sin razón,  NO hay que saberlo todo y no es malo decir “No lo sé, no dispongo de esa información, pero mañana podría enviarosla por email“.
  • A veces nos sentimos cohibidos a la hora de tratar con clientes como importantes y conocidas multinacionales, sin embargo, ten en cuenta que:
    • si buscan externalizar un servicio es porque necesitan a alguien como tú.
    • si te han llamado para que les cuentes de viva voz tu propuesta es porque algo en ella les ha gustado o llamado la atención
    • es difícil que alguien escoja un partner para un proyecto sin ver la cara de la gente que trabajará en él (no sólo técnica, también comercialmente), cuestión de confianza. Más aún si ellos son franceses y tu español.
    • es posible que lo que para ti es la mejor solución al problema, por obvia que parezca, no se le haya ocurrido antes a ninguno de los otros potenciales candidatos y el cliente se sorprenda de lo que le propones.
  • No lo había pensado antes pero es importante que el cliente participe y pregunte durante tu exposición, significa que le interesa lo que le estás contando. Si te pasases dos horas hablando sin que te interrumpiesen, probablemente estarían, además de dormidos, pensando en lo que van a hacer después de que termine “este pesado”, es decir, no le interesa tu propuesta. No tengas miedo a las preguntas, si hay preguntas es porque están atentos a tu exposición.

Y esto es todo. A pesar de la tensión de esta semana, es probable que nos haya venido muy bien como ejercicio práctico tanto de conversación en inglés como de exposición “colaborativa” de un proyecto. Despues de esto creo que nos va a tocar más veces repetir experiencia en otros países.

Congreso de Webmasters 2008 y I Foro de Startups

Casualidades de la vida, aunque el próximo fin de semana estaré en Madrid no será para asistir al Congreso de Webmasters 2008, donde más de 30 expertos descubrirán la realidad del sector a través de ponencias, talleres, mesas redondodas y, sobre todo, networking, mucho networking.

Quien sí estará será mi buen amigo y socio Marcos García que el domingo a las cinco de la tarde participará en una mesa redonda sobre la actualidad de la blogosfera hispana. Debatirá nada más y nada menos que con Fernando Tellado, Javier Martín (Loogic), Luís Rull, y Wicho (Microsiervos).

Además de esto, mañana martes 18 de noviembre se celebra en Barcelona el I Foro de Satartups organizado por First Tuesday (Carlos Blanco y Amaia Helguera)  donde se buscará al mejor de los siete proyectos seleccionados de entre los 21 presentados. Los ganadores se repartirán los premios cedidos por distintas empresas y emprendedores (anda que algunos se han estirado…). Es aquí precisamente donde desde Cucharete colaboraremos con una cena para 2 personas en el restaurante La Alacena de Serrano.

Depurando condiciones Rewrite en Apache

Últimamente he tenido que utilizar bastante ModRewrite de Apache en distintos proyectos, algunos de migración y otros de Internet Móvil donde se necesitan ciertas URL’s para que las operadoras lancen sus sitemas de billing.

Con ModRewrite es muy fácil convertir URLs antiguas al formato nuevo en caso de migración (de manera que no pierdes el SEO que tengas). En el caso del billing de las operadoras móviles es todavía más sencillo puesto que simplemente lo usamos para simular una URL premium. Por ejemplo:

http://tudominio.com/premium.php?noticia=3

Se convierte en:

http://tudominio.com/index.php?noticia=3

De este modo no es necesario hacer scripts independientes y separados por operadora sino que todo queda integrado en nuestro framework.

El problema es que es bastante tedioso depurar lo que hace ModRewrite para ver si las condiciones que has escrito son correctas o si algún filtro no se está ejecutando correctamente. Para solucionarlo lo mejor que podemos hacer es decirle a Apache que “logee” todas las decisiones que va tomando sobre nuestros filtros. Tan fácil como esto:

RewriteEngine on
RewriteLog "/logs/rewrite.log"
RewriteLogLevel 4

RewriteCond %{REQUEST_URI} ^/premium.php$
RewriteRule ^/premium.php /index.php

Este sencillo ejemplo nos permite comprobar qué veremos en el log:

213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (3) applying pattern '^/premium.php' to uri '/premium.php'
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (4) RewriteCond: input='/premium.php' pattern='^/premium.php$' => matched
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) rewrite /premium.php -> /index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) local path result: /index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) prefixed with document_root to /var/www/tudominio.com/index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (1) go-ahead with /var/www/tudominio.com/index.php [OK]

Por cada URL que se solicita al servidor, Apache va comprobando las posibles condiciones que has escrito por si coincide con el patrón (matched) o no (not matched). Si la URL cumple los requisitos, la reescribe según se indica en la regla, en caso contrario la deja pasar tal cual. Con toda esta información podemos hacer un completo seguimiento de las reglas que queremos aplicar para comprobar si hay algún error o por qué determinada URL no hace lo que esperamos que haga.

El nivel del log indica la cantidad de información que se guardará, de 0 a 9. A  mayor valor, más información.

Algo muy sencillo pero que pasa desapercibido para la mayoría y acabamos perdiendo muchísimo tiempo probando reglas sin saber qué está ocurriendo en el interior de nuestro servidor web.

Fotomatón, o haciendo fotos instantáneas online

La idea es sencilla, conectas con la webcam de tus usuarios, les haces una foto y la envías a una galería donde se pueden ver los caretos de tus visitantes. La implementación es casi tan sencilla como la teoría y el resultado es increíble y original.

El sistema es el mismo que utilizaba BloggerSnap, un servicio que tuvo un increíble éxito en su lanzamiento y que parece cerrado desde abril. Hace un año estaba por encima del puesto 40.000 en Alexa, seguramente estuvo incluso más alto. Imagino que sería muy complicado mantener el coste del ancho de banda con tanta popularidad. Hace un par de años estuvimos a punto de lanzar un servicio similar y lo desestimamos ya que no veíamos la manera de monetizarlo mientras que, a poco que tuviese éxito, los gastos se dispararían.

En un escenario normal dependerías de software que el usuario tendría que instalar para que se hiciese la foto y posteriormente te la enviase, con lo cual no conseguirías el objetivo de la instantaneidad, pero existe una solución que permite hacerlo todo mediante una aplicación online: Flash, en nuestro caso Flex 😛 .

La potencia de la plataforma Flash en el tratamiento de audio y vídeo va mucho más allá de lo que pueda parecer y permite crear aplicaciones multimedia avanzadas con participación del usuario de manera bastante rápida. Si además dispones de dinero suficiente, puedes combinarlo con Flash Media Server y los límites los pondrá tu imaginación. Otro día crearemos un videochat 😉 .

La clave es el acceso a la cámara y al micrófono del equipo que permite la plataforma Flash previa autorización del usuario, obviamente. Si lo autorizas, el player conectará con tu webcam y comenzará a mostrar el vídeo de la misma y, si la aplicación lo requiere, enviarlo a otros usuarios. Lo mismo se puede hacer con el audio.

En el taller de hoy haremos una pequeña aplicación para crear una galería de fotos instantáneas en web/blog. Los usuarios que lo deseen pueden hacerse la foto con su propia webcam y ésta quedará alojada en la galería. Simple pero llamativo.

La aplicación constará de dos partes:

  • Zona de capturas: una aplicación desarrollada en Flex que permitirá a los usuarios hacerse fotos sin más necesidad que tener una webcam.
  • Galería: una sencilla página html donde se listan todas las fotos que se han hecho los usuarios.

Capturando imágenes

Aunque pueda parecer algo muy complicado veremos a continuación que la facilidad de conectar con la webcam en Flex es impresionante.

Nuestra aplicación consta de dos únicos componentes, una imagen y un botón. La imagen nos aportará simplemente algo de estilo y el botón lo utilizaremos de disparador de nuestra cámara de fotos online.

Hay tres tareas bien diferenciadas:

  • Conectar con la webcam.
  • Capturar la foto.
  • Enviarla a nuestro servidor.

Conectar con la webcam

Con este sencillo código estaremos visualizando en nuestra aplicación la webcam que el usuario tenga conectada a su equipo.

private function insertWebcamVideo():void{
	var videoHolder:UIComponent = new UIComponent();
	if(Camera.names.length>0){
	   camera = Camera.getCamera();
	   if(camera==null || camera.width==-1 || camera.height==-1 || camera.fps==-1){
	   		Alert.show("Lo sentimos, no tienes cámara", "Error", 4, null, null, iconoAlerta);
	   		captura.enabled=false;
	   		camera=null;
	   }else{
		   camera.addEventListener(StatusEvent.STATUS, cerrar);
		   video = new Video(camera.width, camera.height);
		   video.attachCamera(camera);
		   videoHolder.addChild(video);
		   videoHolder.width=video.width;
		   videoHolder.height=video.height;
		   videoHolder.visible=true;
		   videoHolder.y=0;
		   caja.addChildAt(videoHolder, 0);
		   caja.removeChild(fotillo);
	   }
	}else{
   		Alert.show("Lo sentimos, no tienes cámara", "Error", 4, null, null, iconoAlerta);
   		captura.enabled=false;
	}
	//Security.showSettings(SecurityPanel.CAMERA);
}

Tan fácil como comprobar primero si tiene webcam (sino, obviamente, no puede hacerse fotos 😛 ) y posteriormente añadirla a un componente de vídeo que habremos incorporado a un UIComponent para mostrarlo en la aplicación. En este momento ya tenemos la cámara del usuario en vivo en la aplicación.

Capturar la foto

Teniendo el flujo de vídeo en la aplicación, queremos que cuando el usuario presione el botón “Capturar” se le haga la foto.

private function getSnapshot():void{
	var snapshot:BitmapData = new BitmapData(video.width, video.height, true);
	var m : Matrix = new Matrix();
	snapshot.draw(video, m);
	var jpegEnc:JPGEncoder=new JPGEncoder(75);
	var jpegDat:ByteArray = jpegEnc.encode(snapshot);
	var img_src:String = base64Encode(jpegDat);

	if(img_src.length>1600){
		//imagen correctamente capturada
	}else{
		Alert.show("La imagen capturada parece estar vacía", "Error", 4, null, null, iconoAlerta);
	}
}

Con este otro código conseguimos este efecto. Se obtiene una captura bit a bit del objeto de vídeo y se comprime en JPEG para enviarla al servidor. ¡Ya tenemos la foto hecha!

Enviar la foto

Utilizaremos un HTTPService para enviar por POST la foto que hemos realizado y que guardaremos en una base de datos. Añadimos a la función anterior el código para enviar la foto.

private function getSnapshot():void{
	var snapshot:BitmapData = new BitmapData(video.width, video.height, true);
	var m : Matrix = new Matrix();
	snapshot.draw(video, m);
	var jpegEnc:JPGEncoder=new JPGEncoder(75);
	var jpegDat:ByteArray = jpegEnc.encode(snapshot);
	var img_src:String = base64Encode(jpegDat);

	if(img_src.length>1600){
		var temp:Object=new Object();
		temp.imagen=img_src;
		httpService.send(temp);
		cargandoWindow = ventanaEspera(PopUpManager.createPopUp(this as DisplayObject, ventanaEspera, true));
	}else{
		Alert.show("La imagen capturada parece estar vacía", "Error", 4, null, null, iconoAlerta);
	}
}

<mx:httpservice id="httpService" showbusycursor="false" useproxy="false" method="POST" resultformat="text" url="upload.php" result="onResult()"
fault="onHTTPFault(event)" />

Ya está. El script upload.php de tu servidor recibirá por POST la variable “imagen” con el contenido de tu foto. Sólo habrá que guardarla en un archivo y habrás terminado la parta más ¿complicada? del proyecto.

if($_POST['imagen'] & strlen($_POST['imagen'])!=0 & strlen($_POST['imagen'])>1600){
        $bmd=base64_decode($_POST['imagen']);
        $im = fopen("fotos/foto.jpg",'w');
        fwrite($im,$bmd);
        fclose($im);
}

Antes de guardar la imagen en disco podrías añadir un registro a una base de datos que te permita generar después la galería. Esa parte queda a tu elección.

Generando la galería

Esta es la parte fácil, simplemente creas un script PHP (o en el lenguaje que prefieras) que liste las fotos que has ido guardando en la base de datos paginando como creas oportuno. Creo que sobran más comentarios para algo tan fácil.

Conclusiones

Hoy hemos visto cómo de una manera extremadamente rápida y sencilla se puede conectar con la webcam (y el micrófono) de los usuarios. Sólo hemos visto como hacer una fotografía instantánea de lo que se está viendo a través de la cámara, pero el sistema abre un inmenso mundo de posibilidades.

Descárgate aquí el código del proyecto.