Recientemente he empezado a grabar algunos vídeos de demo para el trabajo y me he visto en la necesidad de mostrar por pantalla las pulsaciones del teclado.
Para este propósito he encontrado la herramienta de Screenkey, la cual está muy bien (las cosas como son).
Sin embargo esta herramienta tiene una pega que me molesta mucho, y es que cuando pulsas una tecla, la CPU se dispara al 100% mientras esta permanezca pulsada. Para mí esto no es aceptable ya que no tiene sentido tal derroche de CPU.
Por suerte es posible solucionarlo limitando la CPU asignada al proceso encargado de correr el programa. Y es eso lo que explicaré aquí.
Para ello haremos uso de systemd y de los Control Groups v2. No entraré en detalles de que es cada una de estas cosas porque hay suficiente literatura sobre ello. Solo decir que systemd es el sistema encargado de arrancar todo el Linux y cgroup es una tecnología perteneciente al kernel de Linux encargada de limitar los recursos.
Es cgroup importante que sea en su versión v2 ya que así podremos correr el screenkey sin privilegios de administrador.
Para poder controlar los límites de la CPU, hay que seguir los pasos aquí mencionados. Concretamente nos interesa los siguientes.
Esto editará el servicio de user@.service añadiendo la línea del Delegate=. Este servicio es el que luego el sistema usará como plantilla para cargar la configuración de nuestro usuario user@1000.service en el caso de que nuestro usuario tenga el id 1000.
Ahora es necesario reiniciar el sistema.
Una vez iniciado, volvemos a comprobar los controllers:
En mi trabajo tengo que realizar un seguimiento de mis tareas para después computar las tareas por horas. Este proceso resulta un engorro, pero hay que hacerlo por ley.
El caso es que si tenemos un portal donde computar las horas pero no una herramienta concreta para hacer ese seguimiento.
En mi caso decidí utilizar la herramienta de Watson. Esta es una herramienta de CLI que permite realizar seguimiento de tus propias tareas añadiéndoles etiquetas.
La herramienta es bastante decente, pero tiene algunas carencias. La más importante para esta entrada, es que no dispone de ningún tipo de interfaz gráfica. Es decir hay que gestionar toda la herramienta mediante comandos, algo que no resulta muy apetecible. Aquí lo que he tratado de hacer es construir una interfaz TUI (Terminal User Interface) mediante la herramienta fzf y bash.
He añadido alguna funcionalidad nueva como la de poder pausar una tarea arrancada.
No he tratado de implementar todas las opciones, pero la versión actual (v0.0.1) resulta una opción usable incluso mediante Docker. He creado el Dockerfile pero no lo he subido a DockerHub.
Una vez contemos con esto, abrimos la aplicación en el móvil y la configuramos al gusto.
Nota: Tengo que avisar que aunque la aplicación está muy bien y cumple con lo deseado, la interfaz es algo fea, pero desde luego no seré yo quien critique eso.
Esquema con la configuración de red.
IP Webcam. Configuración básica.
Nota: Aunque en esta entrada solo mencione el uso de la app como webcam, tengo que decir que tiene muchos otros usos, ya que podemos usarla como vigila-bebes, como cámara de seguridad (tiene incluso detección de movimiento), tiene compatibilidad con Automagic(gracias al plugin de Tasker). Como suele decirse ¡El cielo es el límite!
Lo primero será permitir la ejecución en segundo plano de la aplicación, esto solo será necesario si quieres poder apagar la pantalla del móvil mientras lo utilizas como webcam o si quieres minimizar la aplicación para hacer otras cosas. Por ejemplo mantener una ventana de chat abierta, alguna nota, un servidor x11, etc. Para ello vamos a la app y en Permisos adicionales encontraremos la opción.
En la parte de Preferencias de vídeo podemos cambiar tanto la cámara principal (trasera/delantera) como la resolución. Esta segunda opción nos será muy útil en Skype.
En la parte de Retransmisión local estableceremos el usuario y contraseña (recomendable).
Finalmente cuando tengamos todo configurado a nuestro gusto, podemos ir a la parte de abajo del todo y pinchar en Iniciar servidor. Esto nos mostrará nuestra cámara y nos dará algo de información en la parte inferior sobre como podemos conectarnos.
Captura del móvil una vez iniciado el servidor.
Capturar la señal de vídeo desde el ordenador.
El proceso será el mismo que en la entrada anterior, así que iré rápido.
Aquí lo importante es la entrada (el parámetro -i). En este ejemplo:
Mi usuario es: geek
Mi contraseña es: erratico
La ip de mi móvil es: 192.168.1.31
El puerto en el que escucha la app es: 8080
Si todo ha ido bien, se quedará el ffmpeg ejecutando la captura hasta que decidamos pararlo. Para ello pulsamos "Ctrl + c" o bien cerramos la aplicación en el móvil.
Ver correctamente la cámara en Skype.
Por motivos que desconozco, Skype no admite cámaras con una resolución superior a 800x600. Esto es algo que descubrí a golpe de prueba y error, pero que me frustró mucho las primeras veces hasta que me dí cuenta del detalle.
Para solucionar esto hay dos opciones:
Cambiar la resolución en la configuración de la aplicación móvil.
Redimensionar con el ffmpeg.
Yo personalmente recomiendo la primera. El motivo es que poner una resolución más alta y después redimensionar no hará que la imagen gane calidad, sino más bien lo contrario (puede deformar la imagen). Además a veces me pasa que con resoluciones más altas el vídeo va con retraso.
Por cierto, si os pasa esto, reiniciar el ffmpeg y/o la app, a veces se soluciona.
Esto es como quedaría el comando si decidimos redimensionar (útil si queremos emitir otro contenido como un vídeo de Youtube o un stream de OBS).
Finalmente dejo el script que uso para iniciar el ffmpeg sin tener que calentarme mucho la cabeza:
#!/bin/bash
# Script: ipcam.sh# Autor: McA# Sitio: http://geekerratico.blogspot.com# Versión: 1.0# Variables:# SKYPE : Forzar la imagen a 800x600 (sin este tamaño no funciona la cámara en Skype).# MIRROR: Voltear la imagen como en un espejo.# HOLD : Dejará cargado el módulo de kernel al terminar (opción ideal si se usa el script el un bucle).# Dependencias:# v4l2loopback-dkms, v4l-utils, ffmpeg.# Skype:# En el móvil configurar la resolución de la cámara a 800x600 (otras resoluciones no he conseguido hacerlo funcionar).# Otra opción es usar el parámetro "-s" ejemplo:# ffmpeg -re -i $input -map 0:v -vcodec rawvideo -vf format=yuv420p -s 800x600 -f v4l2 $video
label="Android camera"
input=${1:-https://mca:wololo@192.168.1.31:8080/videofeed}load_v4l2(){
sudo modprobe v4l2loopback video_nr=0 card_label="$label" || exit 1
video=/dev/video0
}
lsmod | grep -q v4l2loopback && {
for video in /dev/video*; do
v4l2-ctl --info -d "$video" | grep -q -E "Card type +: +$label$" && breakdone
} || load_v4l2
ffmpeg \
-re \
-i "$input" \
-map 0:v \
-vcodec rawvideo \
-vf format=yuv420p${MIRROR:+,hflip} \
${SKYPE:+-s 800x600} \
-f v4l2 \
$video
[[ -z $HOLD ]] && sudo rmmod v4l2loopback
Le he puesto varias opciones.
SKYPE=1 MIRROR=1 ipcam.sh video_gracioso.mkv
Por ejemplo con el siguiente comando ocurrirá que:
Se emitirá un "vídeo gracioso" en vez de usar la cámara del móvil.
Se voltea horizontal el vídeo ya que sino salen los textos invertidos.
Hay una opción más que es la del HOLD=. Esta opción evitará que se desmonte el módulo una vez termine el vídeo. Es ideal si se quiere usar el script en bucle. Por ejemplo:
while :; do
sudo SKYPE=1 MIRROR=1 HOLD=1 ipcam.sh video_gracioso.mkv
sleep 1
done
sudo rmmod v4l2loopback
Y esto es todo. Espero que te sea útil el tutorial.
Durante este confinamiento todos hemos empezado a usar mucho más el ordenador para hacer vídeollamadas, bien sea por motivos de teletrabajo, clases o lo que sea.
Esto nos ha obligado a muchos a estar comprando cámaras web que no teníamos. La cuestión es ¿Para que comprar una cámara web si nuestros dispositivos móviles ya cuentan con varias? Y en muchos casos nada malas precisamente.
Bien pues en este tutorial y en el siguiente os enseñaré como hice yo para poder configurar la cámara de mi Android como si fuese una cámara web compatible con Skype.
Parte 1: Cómo configurar una cámara virtual.
En esta primera parte crearemos una cámara virtual la cual usaremos para poder colocar cualquier vídeo como fuente de entrada. Esto resulta bastante interesante ya que si se tiene suficiente imaginación se pueden hacer cosas interesantes. Por ejemplo:
Reproducir vídeos de Youtube en una vídeollamada de Skype.
Colocar una grabación vuestra haciendo como que hacéis un examen.
Esto dará como resultado el dispositivo nuevo /dev/video0.
video_nr: Indica que queremos crear la cámara 0 (Parámetro opcional).
card_label: Indica el nombre que le queremos dar a la cámara (Parámetro opcional).
Es posible crear más de una cámara, de esta forma podemos simular que tenemos muchas cámaras. Para ello solo habría que especificar los números y labels separados por comas. Por ejemplo:
sudo modprobe v4l2loopback video_nr=0,3,5 card_label="Mi webcam 1","Mi otra webcam","La 5 pero que es la tercera"
Aquí se pueden consultar todas las opciones del driver.
-re: Nos vale para que el vídeo se reproduzca como mucho a x1.
-i: Indica la fuente de vídeo.
-vf hflip: Voltea el vídeo horizontalmente (sino los textos salen del revés).
-f v4l2 /dev/video0: Indica la cámara virtual por la cual saldrá el vídeo.
Y listo. Ahora podemos abrir el VLC (por ejemplo) y ver lo que sale por la cámara:
Abrimos el VLC -> Pulsamos sobre el botón de play -> Dispositivo de captura:
- Capture mode: Vídeo cámara.
- Nombre del dispositivo de vídeo: /dev/video0
Reproducir.
Extra: Mandar un vídeo de Youtube.
Buscamos un vídeo de Youtube, copiamos la URL. Con la URL lo primero será listar las distintas fuentes de vídeo, donde seleccionaremos el tamaño de la imagen:
Nota: Si no quieres leer paja y quieres ir directo al grano, pasa directo a la parte de "Algo de configuración previa".
Hace mucho tiempo que no publico nada en el blog y creo que ya va siendo hora de compartir algo interesante.
En este caso, se trata de una serie de scripts que uso para transcodificar vídeos a x265.
Avisos previos.
Mi idea con esto no es hacer una aplicación, sino compartir algo que hice y que me soluciona un problema en mi vida. No obstante, si alguno tiene dudas sobre lo aquí explicado, no tengo ningún problema en contestarlas por simples que sean.
ToDo y mejoras.
Reemplazar el progreso del FFmpeg por una barra de progreso.
Respetar la estructura de directorios en el script de transcodificación.
Motivación.
El motivo que me llevó a realizar estos scripts es el de que cada vez que grababa un vídeo con el móvil estos ocupaban muchísimo. Estamos hablado que un vídeo de 2min ocupa del orden de 300MB. Contando con que la memoria interna de mi móvil de gama media se queda en unos 64GB es inaceptable estas cantidades.
Este problema lo achaco a que para poder grabar vídeos de gran calidad, el móvil necesita o bien un procesador muy potente o mucha memoria. Un procesador potente, implicaría un móvil muy caro, además de mucho consumo de batería y mucho calor generado. Por ello supongo que los fabricantes optan por gastar mucha memoria que es más barato y genera menos problemas.
No obstante si post-procesamos estos vídeos podemos reducir el tamaño de estos en aproximadamente un 90%. Esto solo nos repercutirá en un consumo elevado de batería y tiempo, algo que se soluciona dejando el móvil conectado a un cargador por la noche.
Herramientas.
Para realizar este proceso de transcodificación, he usado varias herramientas.
FFmpeg:
Esta es la más importante de todas. Es la que nos permite pasar el vídeo de su codec original a uno de x265.
ExifTool:
Esta la he usado para renombrar los fichero y para preservar en la medida de lo posible las fechas en las que fueron creados los vídeos.
Esta herramienta está escrita en perl y por tanto será necesario contar con algunas dependencias.
Termux:
Se trata de una potentísima APP que nos permite dotar a nuestro Android de la que quizá sea la mejor consola que podamos usar en este dispositivo.
Esta APP cuenta con un gestor de paquetes que nos permitirá instalar todo tipo de herramientas del mundo Linux sin necesidad de ser root en el teléfono.
El primero: Nos servirá para transcodificar los vídeos de una carpeta y dejarlos en otra preservando siempre que sea posible la fecha de creación.
El segundo: Lo usaremos para extraer la fecha de creación del fichero (la del vídeo original) y renombrarlos a un formato común. Además, borrará el fichero original si se ha especificado.
Forma en la que uso estos scripts:
Uso el primer script para transcodificar toda una carpeta en otra destino.
Visualizo los vídeos con alguna herramienta para ver que están bien.
Uso el segundo script para renombrar las transcodificaciones y borrar los originales.
Algo de configuración previa.
Lo primero de todo será instalar el Termux. Unas pocas lineas más arriba, he dejado el enlace a la web de la aplicación donde hay enlaces tanto al Play como al F-Droid.
Tengo que decir que aunque la aplicación principal es gratuita, la aplicación de los Widget es de pago, pero solo si la instalamos desde el Play.
No es imprescindible, pero más adelante explicaré por qué es buena idea tenerla.
IMPORTANTE: Cada teléfono es un mundo, por lo que todo lo que cuente en esta sección puede variar significativamente según tú modelo.
Una vez instalada, tendremos que concederle permisos al Termux para poder acceder al almacenamiento, que es donde estarán los vídeos de la cámara.
Hay dos formas de hacer esto.
Una es ir directamente a los ajustes de tu teléfono y allí en el apartado de aplicaciones buscar el Termux y concederle permisos (no se crean links ni carpeta "storage").
Otra forma más cómoda, es abrir el Termux y ejecutar:
termux-setup-storage
Si Termux no tiene permisos para acceder al almacenamiento, se mostrará una ventana donde tendremos que aceptarlos.
Como tarea extra, creará la carpeta ~/storage con distintos links a distintas partes del almacenamiento.
Ahora abrimos el Termux y en la línea de comandos ejecutamos lo siguiente para crear un par de carpetas:
# En esta dejaremos los 2 scripts principales.
mkdir scripts
# Estas es imprescindible que tenga este nombre si queremos usar Termux Widget.
mkdir .shortcuts
Termux cuenta con un repositorio de paquetes del estilo de APT de Debian desde el cual podremos instalar infinidad de herramientas.
En nuestro caso solo nos interesan 3 (Enter a todas las preguntas).
apt update
apt install ffmpeg exiftool perl
Y ahora instalamos una dependencia de perl necesaria para el ExifTool.
Esto irá lanzando preguntas, dejamos todo por defecto (enter, enter, enter....) y listo.
cpan -i Image::ExifTool
Pasar los scripts al móvil
Nota: Con el tiempo puede que lo suba a GitLab, pero de momento esto es lo que hay.
Ahora toca pasar estos scripts a la carpeta previamente creada y darles permisos de ejecución.
Existen muchas formas de hacerlo, ADB, usar el WiFi Keyboard, escribirlos a mano, scp, netcat, etc. Yo explicaré una forma.
Se puede abrir este post con el navegador del móvil, copiarlo y después abrimos el Termux y ejecutamos:
# Solo por asegurar que tenemos el editor de ficheros.
apt install nano
nano -t ~/scripts/transcode.sh
Esto abrirá el editor, pegamos el contenido y presionamos: Ctrl+x
Nota: Si no contamos con la tecla virtual de Ctrl en nuestro teclado, se puede pulsar el botón físico de bajar volumen del teléfono.
Ahora solo queda darle permisos de ejecución:
chmod u+x ~/scripts/transcode.sh
Una vez hecho esto, repetimos estos dos pasos para el script 2 (rename.sh).
#!/data/data/com.termux/files/usr/bin/bash
# Transcodifica uno o más videos en una carpeta por defecto o específica# preservando el timestap de cada vídeo.## origen := { video | carpeta_de_videos }# $0 origen [[origen...] carpeta_destino]## La extensión va definida en la variable $video_ext.## v1.1# Autor: McA
video_ext="${video_ext:-mp4}"# Default dst folder.
[[ -d ${@: -1} ]] || set"$@" ~/storage/dcim/Transcode
# Transcodifica un vídeo en otra carpeta.# En la carpeta de destino ($2) se creará un fichero con el código de# error y el nombre del fichero de origen con la ruta canonicalizada.## transcode <fichero origen> <ruta destino>transcode(){
local ret
local dst_file
[[ -f $1 ]] || return 1
[[ -d $2 ]] || return 2
dst_file="$2"/"${1##*/}"
dst_file="${dst_file%.*}.mkv"# Si existe el fichero.
[ -f "$dst_file" ] && return 3
# -progress http://127.0.0.1:8080/automagic/ffmpeg \
ffmpeg \
-y \
-i "$1" \
-c:v libx265 \
-c:a aac \
-b:a 128k \
-map_metadata 0 \
"$dst_file"
ret=$?
touch -cr "$1""$dst_file"echo"$?: $1" >> "$2"/done.txt
return$ret
}
dst_folder=$(readlink -f "${@: -1}")
[[ -d $dst_folder ]] || exit 2
unset folders files
# Pasar los parametros a 2 vectores.# Uno de ficheros y otro de carpetas.for (( i=1; i<$#; i++ )); do
tmp=$(readlink -f "${!i}")
[[ -f $tmp && $tmp =~ \.$video_ext$ ]] && files+=("$tmp")
[[ -d $tmp ]] && folders+=("$tmp")
done# Buscar todos los vídeos de cada carpeta y# subcarpeta y pasarlos al vector de ficheros.for i in"${folders[@]}"; dowhileread f; do
files+=("$f")
done < <(find "$i" -type f -name "*.$video_ext")
done# Transcodificar todos los vídeos encontrados.for i in"${files[@]}"; do
transcode "$i""$dst_folder" ||
echo"Ocurrio algún error: $?." >&2
done
#!/data/data/com.termux/files/usr/bin/bash
# $0 transcode destino [original]## Mueve de una carpeta <transcode> o otra <destino> todos los ficheros mkv y jpg# y renombra por fecha.## Si se especifica una carpeta <original>, se borrarán de esta carpeta todos los# ficheros que coincidan con los ficheros de <transcode> antes de haber sido# renombrada sin tener en cuenta la extensión.# Autor: McA# v1.2# Notas varias:# Recuperar todas las tags:# exiftool -s -G $fichero## # Extraer solo el valor de un tag:# exiftool -NombreDelTag -s -s -s $fichero## # Pasar el tag DateTimeOriginal de UTC a la hora local.# date -d $(exiftool -DateTimeOriginal -s -s -s -d @%s $fichero) +%Y-%m-%d_%H-%M-%Serr(){
echo -e "\e[31m[ERROR]:\e[0m $1" >&2
exit$2
}
type exiftool &> /dev/null || err "No se pudo encontrar el programa: exiftool" 3
perl -MImage::ExifTool -e 1 &> /dev/null || {
# apt install make
e="No se encuentra instalado el modulo de perl Image::ExifTool."
e+="\n\e[33m[Info]\e[0m: Puedes instalarlo con \e[36m'cpan -i Image::ExifTool'\e[0m"
err "$e" 3
}
# Extrae la fecha más fiable de entre los tags del vídeo $1.## NOTA 1: Algunos tags se encuentran en UTC, por lo que la hora recuperada# podría no ser la esperada. Para ello se pasa la hora UTC a la GMT+X según# la configuración del dispositivo. Esta zona puede controlarse mediante la# variable $TZ (TimeZone). Por ejemplo:# export TZ=America/Mexico_City# Para más opciones se puede consultar /usr/share/zoneinfo/**.## NOTA 2: Esta pensada para ser usada con tags de ficheros Matroska (mkv), pero# puede funcionar igualmente con otros tags.# Para otros tags consultar: https://exiftool.org/TagNames/get_date(){
local i date
for i in DateTimeOriginal CreateDate FileModifyDate; do
date=$(exiftool -$i -s -s -s -d %s "$1" 2>/dev/null)
[[ $date -gt 0 ]] && breakdone
date -d @$date +%Y-%m-%d_%H-%M-%S
}
# Añade números al final del nombre del fichero ($1)# hasta que no exista o sea igual a $2 (shasum).unico(){
local nom=${1%.*}local ext=${1##*.}local z=0
local ret=$1local sha=$(shasum "$2"|sed 's/\( \+\).*/\1/')
while [[ -f $ret ]]; doecho"$sha$ret" | shasum -cs && break
z=$(($z + 1))
ret=${nom}_$z.$extdoneecho -n "$ret"
}
dir_t="${1%/}"# Transcode.
dir_d="${2%/}"# Destino.
dir_o="${3%/}"# Original.
[[ -d $dir_t ]] || err "No se ha especificado el directorio: transcode" 1
[[ -d $dir_d ]] || err "No se ha especificado el directorio: destino" 2
echo -e "Origen: \e[31m$dir_t\e[0m"echo -e "Destino: \e[32m$dir_d\e[0m"whileread i; doecho -n "$i: "
old="$dir_t/$i"
datef=$(get_date "$old")
dst=$(dirname "$i")/$datef.${i##*.}
new=$dir_d/$dst
new=$(unico "$new""$old")
if [[ -f $new ]]; thenecho -e "Ya existe \e[31m$new\e[0m."
rm "$old"elseecho -e "Moviendo a \e[32m$dst\e[0m."
mkdir -p "${new%/*}"
mv "$old""$new"fi
[[ $? -eq 0 && -d $dir_o ]] && {
rm -f "$dir_o/${i%.*}".*
}
done < <( \
find "$dir_t" \
-type f \( \
-iname "*.jpg" -o \
-iname "*.jpeg" -o \
-iname "*.mkv" \) \
-printf %P\\n)
Widget de accesos directos (opcional)
Estos scripts son la base para realizar de manera semiautomática la transcodificación de los vídeos, pero resulta mucho más cómodo contar con accesos directos que hagan la tarea con solo un clic sin tener que entrar en la línea de comandos.
Para ello será necesario instalar la APP del termux-widget (de pago si se instala desde el play).
Una vez instalada, hay que crear los siguientes scripts.
Es importante mencionar que en este ejemplo, se pasarán los vídeos de la carpeta DCIM/Camera a DCIM/Transcode (script 1). Y de DCIM/Transcode a DCIM/Done (script 2).
Esto mismo se puede aplicar por ejemplo a los vídeos de Whatsapp.
Script 1 (~/.shortcuts/transcode-Camera.sh)
#!/data/data/com.termux/files/usr/bin/bash
# Carpeta intermedia donde quedarán los vídeos a repasar antes de renombrar.
mkdir -p ~/storage/dcim/Transcode
~/scripts/transcode.sh ~/storage/dcim/{Camera,Transcode}
# Bell x3.for i in 1 2 3; doecho -n $'\007'
sleep 0.3
doneechoecho -e "\e[1;36m-- \e[1;32m¡Listo! \e[1;36m--\e[0;0m"read -sn1
Script 2 (~/.shortcuts/Rename-Transcode.sh)
#!/data/data/com.termux/files/usr/bin/bash
# Carpeta donde quedarán los vídeos una vez renombrados.
mkdir -p ~/storage/dcim/Done
~/scripts/rename.sh ~/storage/dcim/{Transcode,Done,Camera}
# Bell x3.for i in 1 2 3; doecho -n $'\007'
sleep 0.3
doneechoecho -e "\e[1;36m-- \e[1;32m¡Listo! \e[1;36m--\e[0;0m"read -sn1