Ya contamos con varias instalaciones desplegadas con nuestro software de digital signage (señalización digital) Buzzk para espacios públicos, como bares, restaurantes o comercios. Es un software con cierta madurez, que está basado en HTML 5 y requiere de clientes relativamente ligeros, ya que únicamente hace falta una navegador web con aceleración 3D.
Tradicionalmente, hemos venimos utilizando Odroid o Raspberry Pi 2 como anfitriones de nuestros Buzzk. Son económicos y fiables y su configuración en modo kiosko resulta muy sencillo con ciertas herramientas open source… Matchbox, Unclutter o Chromium son algunos ejemplos muy habituales en este tipo de instalaciones. Pero hace varias semanas se nos planteó el reto de integrar nuestro sistema de digital signage en otro sistema de digital signage algo old school, ya desplegado en una instalación bastante grande. Se trataba de cerca de una docena de pantallas con sus correspondientes equipos “ligeros” controlados desde un servidor… con un sistema propietario, montado con una interfaz bastante soviética en HTML y corriendo todo ello sobre PHP (¡Cómo nos gusta PHP!).
Añadiendo streaming de video a Buzzk
El problema es que era una instalación propietaria que cuenta con una licencia un tanto restrictiva y que no le permitía configurar una simple URL como contenido a consumir. El sistema soporta imágenes, vídeos, ficheros swf… infinidad de opciones bastante complicadas a priori, pero la versión en cuestión no tenía un campo URL para invocar a nuestro pequeño cliente Buzzk… Aunque por debajo corrían sobre Linux y un navegador web, la configuración resultaba bastante compleja y, por supuesto, no teníamos acceso a los equipos de ninguna manera más o menos sana.
Dicho rápidamente: teníamos un «marronaco». Había que mostrar nuestro cliente Buzzk en un sistema hermético del que el cliente no quiere desprenderse. Algo complicado. Aunque, de repente, vimos la luz: esos clientes eran capaces de reproducir un video-stream sobre http. La misión era crear un stream de vídeo en directo, directamente con la salida de nuestro navegador:
- Lanzar un navegador con Buzzk corriendo sobre unas X
- Capturar en tiempo real la salida de ese DISPLAY
- Generar un stream live hacia el sistema «hostil» de digital signage
- Que el sistema hostil entienda y reproduzca nuestro stream (obvio)
X descabezadas
La idea inicial era levantar un servidor X real en nuestro servidor y, desde ahí, capturar el stream que posteriormente se mostraría a través de un servidor de video al los clientes «reales» del sistema. Pero se nos antojaba algo demasiado «manual»: el servidor necesitaría una tarjeta gráfica concreta, deberíamos forzar la resolución gráfica… Nos parecía algo poco tolerante a errores, excesivamente «real» para nuestro propósito.
Entonces nos acordamos de XvFb. XvFb es parte de la implementación XFree86 de un servidor X11 normal y corriente, con la particularidad de que utiliza la memoría para realizar todas las operaciones gráficas. No necesita ningún hardware específico y es 100% parametrizable. En otras palabras, es como un servidor X fantasma. Es bastante utilizado para realizar tests de integración con Selenium o herramientas similares.
Su ejecución es simple:
/usr/bin/Xvfb :10 -screen 0 1024x768x24
Con las X levantadas, ya solo nos quedaba configurar el ~/.xinitrc para arrancar gestor de ventanas, el chromium en modo kiosk… pero esa es otra historia que ya contaremos en otra ocasión.
Y voilá! ya tenemos nuestro buzzk ejecutándose en modo fantasma en nuestro pequeño servidor.
Si quieres probarlo, lo tendrás seguro disponible en el sistema de paquetes de tu distribución de Linux favorita.
Video Stream
Como (casi) siempre que tenemos que tirar de temas de vídeo, echamos mano de ffmpeg… en este caso, le tocaba arrancar a ffserver.
Necesitamos que el stream generado (f.mpg), sea de calidad suficiente (no teníamos problemas de ancho de banda), y en esta ocasión no necesitábamos sonido…
Después de varias pruebas, comprobamos que esta configuración cumplía con un mínimo de calidad más que aceptable:
HttpPort 8090 HTTPBindAddress 0.0.0.0 MaxHTTPConnections 2000 MaxClients 20 MaxBandwidth 200000 CustomLog - <Feed f.ffm> File /tmp/f.ffm FileMaxSize 10000K </Feed> <Stream buzzk.mpg> Feed f.ffm Format mpeg VideoCodec mpeg1video VideoFrameRate 25 VideoSize xga VideoBitRate 516 VideoBufferSize 1024 VideoGopSize 1 NoAudio StartSendOnKey VideoHighQuality </Stream>
Más información sobre como tunear ffserver, aquí.
Con ffserver corriendo, solo hace falta un “agente” pusheador que genere ese Feed. Gracias al device x11grab de ffmpeg, es relativamente sencillo capturar el DISPLAY que está generando xvfb. Solo nos quedaba ajustar los parámetros de captura, y se lo enchufamos al ffserver:
/usr/bin/ffmpeg -re -override_ffserver -f x11grab -s 1024x768 -r 28 -i :10 -q:v 2 -an -qmin 1 -qmax 31 -cpu-used 0 -quality good -b:v 128k http://127.0.0.1:8090/f.ffm
Básicamente le indicamos al ffmpeg que capture la salida del servidor x11, en el DISPLAY :10, a una resolución xga (1024×768) a 28 frames por segundo, y que lo «pushee» hacía el Feed f.ffm que está escuchando desde el ffserver.
Dicho y hecho, funcionaba perfectamente con el seevidor Xvfb. Incluso las transiciónes CSS3 se visualizan perfectamente en nuestro reproductor de vídeo.
Únicamente nos queda probar que el stream funciona correctamente. Utilizamos nuestro reproductor multimedia favorito (VLC por ejemplo) y ya tenemos buzzk en directo:
vlc http://localhost:8090/buzzk.mpg
Orquestando todos las ejecuciones
Finalmente solo nos queda ejecutar todo esto, y ejecutarlo en un este orden concreto.
1. ffserver
2. Servidor X11 (Xvfb)
3. Cliente Chromium
4. ffmpeg pusheador
Y para esto nada mejor que montar 4 ficheritos «.service» con systemd. Por ejemplo, el «pusher» ffmpeg es lanzado después de que haya arrancado el servidor X, así como el ffserver:
[Unit] Description=Buzzk Stream (pusher) Requires=buzzk-xserver.service, buzzk-ffserver.service [Service] User=irontec EnvironmentFile=/etc/default/buzzk ExecStart=/usr/bin/ffmpeg -re -override_ffserver -f x11grab -s ${RESOLUTION} -r 28 -i ${DISPLAY} -q:v 2 -an -qmin 1 -qmax 31 -cpu-used 0 -quality good -b:v 128k http://127.0.0.1:8090/f.ffm ExecStop=/bin/kill -9 $MAINPID Restart=always RestartSec=3 [Install] WantedBy=multi-user.target
Si te gusta nuestro blog, ¡vótanos!
Conclusión: pronto más marketing tecnológico
Xvfb nos ha dejado bastante buen sabor de boca y es más que probable que esta no sea la última instalación con este software… Tenemos varios proyectos en la cabeza: desde integrar de alguna manera el photocall con Chromecast, hasta visualizar el SmartWall en una smartTV sin necesidad de ningún cliente adicional. Responsables de marca, marketing managers y agencias de publicidad: estad atentos a nuestras novedades de marketing tecnológico en los próximos meses 😉
Lo que seguramente vamos a probar rápidamente es esta joyita: xvfb disponible en npm… Buenísima pinta 🙂
Queremos tu opinión :)