El blog de Julián :-)!

Información para compartir :-)!

Posts Tagged ‘gstreamer

Smartphone como GNU/Linux webcam

with 2 comments

Motivación

Luego de usar mi Lenovo N500 por más de diez años, nunca me preocupé de hacer funcionar la cámara web integrada, y ya con la pandemia y la avalancha de video reuniones encima, descubrí que el driver para GNU/Linux (Debian 10 en mi caso) no funcionaba. Y al mismo tiempo, las aplicaciones usuales para reuniones (ZOOM / Google Meet) ya pesan bastante para mi vieja notebook, así que consideré usar una PC de escritorio que tenía disponible, y que es un poco más nueva. Sin embargo, esta PC, no tiene cámara web.

Con esto en mente, las alternativas eran:

  1. Trabajar para lograr que funcione la cámara web integrada en la notebook.
  2. Comprar una cámara web externa
  3. Usar una cámara digital como cámara web,

La primera alternativa, se descartó por dificultosa. La segunda se descartó por el costo: una cámara web acá (Argentina) cuesta unos $5000, que representa más del 25% de la mensualidad de un jubilado, lo que es un precio considerable. Así que se exploró la tercera opción.

Créditos

Los teléfonos inteligentes que quedan en desuso casi nuevos son tan abundantes que nos dejan piezas de tecnología muy versátiles y poderosas a costo casi cero y todos tienen por lo menos una buena cámara digital. Después de una breve búsqueda en internet aparecieron varias soluciones que implementaban cámaras web usando teléfonos celulares. En especial estos dos vínculos

https://www.atareao.es/software/video/utiliza-tu-android-como-webcam-en-ubuntu/

https://github.com/bluezio/ipwebcam-gst/

El primer vínculo realmente refiere al segundo y siguiendo las instrucciones que da, se puede instalar un smartphone como cámara web en un sistema GNU/Linux. En el segundo link aparece el «driver para Linux», que en realidad es un gran trabajo que ha hecho Antonio García Domínguez, el autor, escribiendo dos scripts de shell que instalan y combinan software ya existente para que todo funcione. Esto demuestra la potencia y versatilidad de GNU/Linux como sistema capaz de adaptarse a usos peculiares y la potencia del software libre que además de proveer herramientas poderosas nos deja la información al alcance de la mano para que quién quiera aprender pueda hacerlo. A continuación muestro una implementación simplificada del trabajo de Antonio, hecha con dos cosas en mente

  1. Aprender para poder explicar el proceso
  2. Poder usar otras aplicaciones de cámara que la que muestra el trabajo original. Ya veremos de qué se trata.

La idea

La idea es tomar el streaming de la cámara, que normalmente saldría por la interfase de red, y redirigirlo al puerto USB para evitar demoras, y enviarlo a la PC. Ya en la computadora, de nuevo se redirecciona a la interfase loopback (que siempre tiene la dirección 127.0.0.1 ó localhost) desde donde se vuelve a tomar el streaming para procesarlo y enviarlo al dispositivo /dev/video0, lugar que lo hará disponible para cualquier aplicación como si se tratara de un dispositivo de captura convencional

El esquema propuesto en el trabajo de Antonio para usar el teléfono cómo cámara es el siguiente

Lo que es cada cosa…

Cámara y streaming en android

Este planteo requiere correr en el dispositivo android una aplicación que tome el video que produce la cámara y que genere el streaming que se quiere transmitir. Hay varias aplicaciones que hacen eso. Antonio propone usar IP-webcam, y de hecho, es obligatorio usarla para utilizar su script, pero no es una aplicación libre. Lamentablemente, buscando en F-droid (que es un repositorio de software libre para android), si bien hay algunas aplicaciones de este tipo, no funcionan adecuadamente o no trabajan completamente sobre http, cuestión aparentemente insalvable en este esquema de trabajo, como veremos después.

Finalmente, se decidió usar #LiveDroid, porque aunque no es software libre, es relativamente pequeña (5,8 MB), funciona completamente sobre http y no contiene ni anuncios ni compras integradas. Se puede instalar desde Google Play, como indica el link mostrado recién. Agradezco a su autor Akshay Chopde por esta amigable y eficaz aplicación.

Normalmente estas aplicaciones hacen el streaming sobre la red en la dirección IP del teléfono, de manera que si nos conectamos a la misma red podemos acceder al video desde un navegador. Por ejemplo, si el teléfono está conectado a un access point con la dirección 192.168.1.20 y nuestra computadora está conectada al mismo access point con la dirección 192.168.1.5, si ponemos http://192.168.1.20:puerto/algo en la computadora, podremos ver la imagen que está tomando la cámara del teléfono por intermedio de la red local.

Por lo general, puerto es 8080, y comunmente se puede configurar desde la aplicación. Una relativa dificultad es conocer qué es algo en la dirección de arriba, porque en general debemos tener la dirección completa para acceder al streaming de la cámara. Para el caso de IP-webcam se puede usar el url http://ip_del_telefono:puerto/videofeed según el trabajo de Antonio.

Para #LiveDroid es http://ip_del_telefono:puerto/?action=stream cosa que se descubrió analizando el flujo de datos con wireshark, que es un excelente analizador de flujos de red libre con una utilidad superlativa. Es probable que descubrir el url completo sea el paso clave que permita adaptar otras aplicaciones de cámaras que hacen streaming para que funcionen con GNU/Linux. Como veremos más adelante, al final se usa la dirección 127.0.0.1 (localhost) para acceder a la cámara, así que se apunta wireshark hacia allí, y con un poco de suerte, se puede verificar el url donde la aplicación sube el streaming.

Software de redirección en Android y en GNU/Linux

Existe un software llamado adb por Android Debug Bridge, que permite hacer cosas asombrosas. Si ya está instalado, se puede consultar información al respecto tecleando man adb desde la consola. Y si no está instalado, es imprescindible instalarlo usando apt o synaptic. Desde la consola podemos instalarlo poniendo

$apt-get install adb

adb tiene tres partes: un servidor que corre en segundo plano en la máquina GNU/Linux y un demonio que se ejecuta también en segundo plano en el dispositivo android. Finalmente, hay un cliente que también se ejecuta en la computadora GNU/Linux.

La idea es que los clientes nos permiten enviar comandos al servidor local para luego enviarlos al demonio remoto en el dispositivo.

Usaremos adb para redirigir el tráfico de la interfase de red del teléfono hacia el puerto USB. Para hacer esto tenemos que hacer dos cosas.

  1. En el dispositivo android, habilitar primero el modo de desarrollador y luego habilitar el modo de depuración por USB. Esto permitirá al demonio adb redirigir el tráfico tcp y otras cosas.
  2. Luego, desde la consola, tipear
$adb forward tcp:8080 tcp:8080

Con lo cual se hace el reenvío de los paquetes tcp entre el puerto 8080 en la máquina GNU/Linux con el puerto tcp 8080 del dispositivo android. Volveremos sobre esto más adelante con más detalle.

El modo de desarrollador puede estar habilitado en el dispositivo android, o quizá sea necesario habilitarlo. Para hacerlo, por lo general hay que ir a Ajustes -> Acerca del teléfono -> Información de Software -> Número de compilación y golpear 7 veces en esa última opción. Luego de esto, deberá aparecer la opción Ajustes -> Opciones del desarrollador y dentro, deberemos habilitar la opción Depuración de USB.

GStreamer

GStreamer es un software de procesamiento de audio y video que permite separar la complejidad del procesamiento del streaming de la aplicación que finalmente muestra esos datos.

GStreamer se basa en tuberías que es un concepto muy usado en sistemas tipo UN*X y consiste en la idea de que un flujo de datos (stream) puede ser la entrada de un programa que lo procesa, dando una salida que a su vez se puede usar como entrada de otro programa y así sucesivamente. En el caso de GStreamer, el operador que conecta la tubería, es decir, la salida de un programa con la entrada del siguiente, es » ! «.

En la figura de abajo se muestra este concepto, en donde el origen de datos se llama source (fuente) y el destino recibe el nombre de sink (sumidero). (Las dos figuras siguientes se han tomado de https://es.wikipedia.org/wiki/GStreamer, lugar en donde se puede encontrar una muy buena explicación sobre GStreamer)

GStreamer Technical Overview.svg
GStreamer example pipeline.svg

Para instalar gstreamer en Debian GNU/Linux (según la página oficial de gstreamer) ponemos

$apt-get install libgstreamer1.0-0 gstreamer1.0-plugins-base  gstreamer1.0-plugins-good gstreamer1.0-plugins-bad  gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc  gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl  gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

v4l2loopbak

Un dispositivo de video real constituye un punto en dónde se puede tomar una señal de streaming proveniente de un dispositivo de captura real, como por ejemplo, una cámara de video física conectada a la computadora. Por el contrario, un dispositivo de video virtual, toma su streaming de otra fuente, pero la hace disponible a cualquier aplicación de la misma forma que uno real. en nuestro caso, esta característica resulta muy conveniente y se logra utilizando el módulo v4l2loopback.

Bajo Debian, este módulo puede venir para construir en formato dkms como directamente en formato binario y se puede instalar usando tanto apt como synaptic.

Si elegimos usar el que viene para construir con dkms, hay que prestar atención a un asunto muy importante: la versión de este módulo debe coincidir con la versión del kernel que correrá cuando hemos de cargarlo. Es sencillo, pero es algo que hay que resolver a mano, porque ni el script de Antonio ni los programas de instalación lo resuelven de manera automática. Una forma de asegurarse de esto es usar synaptic y mirar la versión de kernel que figura al final del nombre del paquete v4l4loopback, para luego buscar las imágenes (linux-image-*) y verificar que coincida con la versión que también aparece al final del nombre del archivo de la imagen del kernel. Si la imagen no es la activa, sencillamente instalamos la que nos hace falta y la elegimos desde el menú de inicio cuando la computadora arranque la próxima vez.

Por ejemplo, si nuestro paquete es v4l2loopback-modules-4.9.0-13-686-pae, entonces, tendremos que instalarlo junto con la imagen del kernel que viene en linux-image-4.9.0-13-686-pae.

Para este caso, desde la consola habría que teclear, como root

$apt-get install v4l2loopback-modules-4.9.0-13-686-p linux-image-4.9.0-13-686-pae

Ahora tenemos que construir e instalar el módulo con module-assitant, de tal manera que si no está instalado, hay que instalarlo. Siempre como root, desde la terminal ponemos

$apt-get install module-assistant

Una vez instalado el asistente para la construcción de módulos, lo usamos para construir e instalar el módulo que nos interesa

$ module-assistant auto-install v4l2loopback

Esto iniciará un proceso de compilación e instalación que culminará con nuestro módulo disponible. La ventaja de este método sobre el clásico make install es que el sistema lleva la cuenta de que el módulo se instaló y lo considera para futuras dependencias.

Si por el contrario, instalamos el binario, hacemos directamente podremos instalarlo (como root) tecleando en la terminal

$ apt-get install v4l2loopback-dkms

Una vez instalado por cualquiera de los dos métodos, el módulo queda disponible para cargar poniendo, como root

$modprobe -v v4l2loopback

Y si no hay errores, ya tendríamos que tener nuestro /dev/video0 listo para usar.

Ponemos todo junto…

En este punto ya se puede unir todo, con el siguiente esquema

  1. Conectamos el teléfono con #LiveDroid instalado a la computadora mediante un cable USB. En mi caso usé un viejo y pequeño LG20. Para verificar que está bien conectado podemos teclear, como root, desde la terminal
$ adb devices -l
 List of devices attached
 * daemon not running; starting now at tcp:5037
 * daemon started successfully
 LF5SP7AIHIRG8DVO       unauthorized usb:2-5 transport_id:1 d:1 
$

Al ingresar este comando, en el teléfono debe aparecer algo como esto

Pantalla del LG 20 al ser conectado mediante adb

Esa es una reacción de seguridad del teléfono, así que debemos contestar «ok» para poder conectar el teléfono. Si vamos a usar siempre la misma computadora, también podemos tildar la casilla y ya no nos va pedir nada la próxima vez que nos conectemos al teléfono.

Si esto no sucede, se puede matar al servidor adb en la computadora y volver a intentarlo. Por ejemplo

$ps -C adb
   PID TTY          TIME CMD
 28244 ?        00:03:15 adb
$kill 28244

Esto mataría al servidor adb para poder volver a intentar.

Retomando, si apretamos «ok» en el teléfono, ya podremos conectarnos

$adb devices -l
 List of devices attached
 LF5SP7AIHIRG8DVO       device usb:2-5 product:luv20ss_global_com model:LG_D100 device:luv20ss transport_id:1

Notar que ha desaparecido la palabra unauthorized de la salida del comando, lo cual significa que podremos conectarnos.

2. Ahora redireccionamos el puerto tcp 8080 del dispositivo android al puerto tcp 8080 de la computadora GNU/Linux. Esto significa que los datos que las aplicaciones del teléfono envíen a ip_telefono:8080 aparecerán en 127.0.0.1:8080, y habrán viajado por el cable USB, no por el WiFi. Usamos el comando adb forward tcp:puerto_local tcp:puerto_remoto, que en realidad permite redireccionar dos puertos cualquiera de los dos lados. El comando es

$ adb forward tcp:8080 tcp:8080

(Si da error, verificar la conexión con el teléfono: si no permitimos siempre la depuración desde esta computadora en la pregunta que nos hizo el dispositivo antes, tendremos que autorizar de nuevo la conexión)

3. Ahora hay que cargar el módulo v4l2loopback para tener disponible nuestro dispositivo de video /dev/video0

$ /sbin/modprobe -v v4l2loopback
 insmod /lib/modules/4.19.0-6-686-pae/kernel/drivers/media/v4l2-core/v4l2-common.ko 
 insmod /lib/modules/4.19.0-6-686-pae/updates/dkms/v4l2loopback.ko 

4. Ahora ejecutamos gstreamer para habilitar el procesamiento y redirección del streaming

$ gst-launch-1.0 souphttpsrc location=http://localhost:8080/?action=stream do-timestamp=true is-live=true ! queue ! multipartdemux ! decodebin ! videoconvert ! video/x-raw,format=YUY2 ! v4l2sink device=/dev/video0 sync=false

5. Si no hubo errores, ya podemos intentar ver lo que está capturando la cámara del teléfono. Una alternativa es teclear lo siguiente en la consola

$ webcamoid /dev/video0

Veremos aparecer webcamoid y si apretamos play tendría que aparecer en vivo la imagen que captura nuestro dispositivo

El teléfono funcionando como webcam

En síntesis…

Una vez que tenemos todo el software instalado, cada vez que queremos habilitar la cámara sólo tenemos que ingresar tres órdenes para habilitar la cámara

$ adb forward tcp:8080 tcp:8080
$ /sbin/modprobe -v v4l2loopback
$ gst-launch-1.0 souphttpsrc location=http://localhost:8080/?action=stream do-timestamp=true is-live=true ! queue ! multipartdemux ! decodebin ! videoconvert ! video/x-raw,format=YUY2 ! v4l2sink device=/dev/video0 sync=false

Luego de esto, la cámara debería estar disponible, como se muestra en el video que sigue

Como una forma de hacerlo más simple, puse esos tres comandos juntos en un pequeño script llamado webcam.sh: se puede bajar, hay que hacerlo ejecutable y correrlo cada vez que se necesite usar la cámara web. El archivo se puede bajar desde acá.

Si no se quiere cambiar los permisos al archivo, se lo puede ejecutar poniendo, como root:

$ bash webcam.sh

Conclusión

Se presentó una manera sencilla y económica de agregar una cámara web a una computadora GNU/Linux: no se gasta un céntimo, se hace todo con lo que hay a mano, y se da nuevo uso a celulares que de otro modo terminarían en la basura. Y por si fuera poco se aprenden cosa nuevas.

Por supuesto, cualquier comentario, corrección o ampliación de este trabajo es bienvenida. En especial sería muy agradable que alguien acerque el dato de una aplicación libre de cámara web para ejecutar en el teléfono, que fue el único software propietario que no se pudo evitar usar.

Written by jrpk

noviembre 5, 2020 at 10:31 pm