Octubre 16, 2012 Uncategorized

Emitir video con tu dispositivo móvil con Node.js, Express.js y Socket.IO

En este post quiero mostrar lo sencillo que puede ser desarrollar aplicaciones que procesen información en tiempo real mediante la utilización de Node.js y websockets. En concreto, como ejemplo para esta demostración, he desarrollado una aplicación que captura vídeo a través de la cámara de tu dispositivo móvil y lo emite a través de una página web.

La aplicación está publicada en Heroku, una plataforma de cloud computing que permite publicar tu aplicación gratuitamente. Puedes probar la aplicación en la siguiente dirección: http://jlmonteagudo-cam.herokuapp.com/

El código fuente de la aplicación lo he subido a github y se puede acceder desde la siguiente URL: https://github.com/jlmonteagudo/jlmonteagudo-cam

 

Estructura de la aplicación

La aplicación está estructurada en tres piezas distintas:

Página web que emite el vídeo: Esta página captura vídeo a través de la cámara de tu dispositivo móvil y lo envía mediante web sockets a un servidor. Utiliza el método getUserMedia de los navegadores para capturar el vídeo.

Servidor: El servidor simplemente se encarga de recibir los frames que envía la página que emite el vídeo y hace un broadcast de estos frames a otra página web.

Página web que visualiza el vídeo: Esta página web simplemente visualiza los frames enviados por el servidor.

 

Gráficamente la estructura sería la siguiente:

 

 

Emit.html

La página emit.html es la que se encarga de capturar el vídeo a través del dispositivo móvil y lo envía al servidor. El código principal de la página es el siguiente:

El script primero comprueba si el navegador implementa el método getUserMedia, y en caso afirmativo al tag video se le asigna el flujo de datos que el navegador captura de la cámara del dispositivo:

A continuación el script configura la librería Socket.IO para conectarse al servidor al que tiene que enviar las capturas de vídeo. La función que se encarga de enviar las capturas de vídeo es la siguiente:

Para enviar las capturas de vídeo al servidor, el script utiliza un elemento canvas, que se crea a través de JavaScript, en el cual se dibuja cada segundo lo que el elemento video está emitiendo en ese momento:

Display.html

La página display.html es muy sencilla y lo único que hace es conectarse al servidor y mostrar en un elemento img aquellas capturas que le llegan a la página a través de websockets:

Servidor

El servidor está desarrollado con Node.js y es muy sencillo de implementar. Simplemente tenemos que crear una aplicación con el framework Express.js e importamos una librería que implementaremos a continuación (streamingService). Esta librería será la encargada de configurar Socket.IO para recibir las capturas de vídeo y distribuirlas a todos los clientes conectados al servidor. El código del servidor (casi en su totalidad generado por Express.js) es el siguiente:

Y por último, así es cómo quedaría la implementación de la librería streamingService:

Como vemos, toda información que le llega al servidor, la librería hace un broadcast de esa misma información a todos los clientes. Otro punto a tener en cuenta es que Heroku, al igual que otras plataformas cloud computing, no soporta el uso de websockets, por ello es que hay que especificar que Socket.IO realice el transporte a través de xhr-polling.

Consideraciones

La cantidad de información que transmite esta solución de emisión de vídeo es relativamente elevada, ya que cada frame que emite la página emit.html al servidor pesa alrededor de 50K. Hemos configurado el sistema para que envíe únicamente un frame por segundo, ya que emitir más de 50K por segundo sería demasiado pesado. Es por esto que para probar el sistema es recomendable que el dispositivo que emite el vídeo esté conectado a una red ADSL o de alta velocidad y no a través de 3G, ya que de lo contrario la emisión no funciona correctamente.

Conclusión

Como hemos podido comprobar, las posibilidades que nos ofrece Node.js y Socket.IO son muy interesantes, y la combinación de ambas herramientas nos permite desarrollar aplicaciones que procesen información en tiempo real de forma muy sencilla.

  1. MaTECH dice:

    Muy bueno el tuto, me ayudo bastante a hacer algo que queria.
    Probe tu demo con IE, Firefox y Chrome pero no me funciona en ningun navegador.
    Puede que haya encontrado un error.

    No deberias hacer lo siguiente antes de esto:

    if(navigator.getUserMedia) {
    navigator.getUserMedia(‘video’, successCallback, errorCallback);

    Creo que deberias hacer esto:

    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    if(navigator.getUserMedia) {
    navigator.getUserMedia(‘video’, successCallback, errorCallback);

    Espero que me respondas si estoy en lo correcto y si funciona como digo.

    Saludos

  2. jl_monteagudo dice:

    HOla MaTECH,

    No he probado lo que comentas, pero ciertamente lo que propones es mucho mejor, ya que así podemos abarcar más navegadores que con la implementación que yo hice.

    En su día se me olvidó comentar en el artículo que, en el momento de yo publicarlo, creo que sólo el navegador Opera soportaba la llamada a getUserMedia, aunque no estoy muy seguro de ello.

    Gracias por tu comentario.

  3. Eduardo dice:

    Hola, cargue el programa en mi celu y lo puse a trasmitir, sin ninguna configuracion a donde estaria transmitiendo, me puedo conectar desde mi notebook para ver lo que trasmito?
    Saludos y gracias.

  4. ricardo dice:

    como seria si quiero transmitir audio?

  5. luis dice:

    saludos, que tan complejo seria esto implementarlo a un proyecto con sailsjs?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Back to top