miércoles, 25 de noviembre de 2020

TUI para Watson mediante fzf + bash

 Esta será una entrada breve.

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.

Podéis descargar en mi repositorio de GitLab.

lunes, 10 de agosto de 2020

Usar la cámara de tu Android como webcam

En esta parte 2 vamos a ver como usar la cámara de nuestro Android como webcam.

Para ello necesitaremos de:

  • Un teléfono con Android (obvio).
  • La aplicación de IP Webcam.
  • Lo ya contado en el artículo anterior.

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 de red
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.

Imagen de la APP
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.

# Crear la cámara virtual:
sudo modprobe v4l2loopback video_nr=0 card_label="Android camera"

# Iniciar la cámara:
input=https://geek:erratico@192.168.1.31:8080/videofeed
ffmpeg                 \
    -re                \
    -i $input          \
    -map 0:v           \
    -vcodec rawvideo   \
    -vf format=yuv420p \
    -f v4l2            \
    /dev/video0

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:

  1. Cambiar la resolución en la configuración de la aplicación móvil.
  2. 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).

input=https://geek:erratico@192.168.1.31:8080/videofeed
ffmpeg                 \
    -re                \
    -i $input          \
    -map 0:v           \
    -vcodec rawvideo   \
    -vf format=yuv420p \
    -s 800x600         \
    -f v4l2            \
    /dev/video0

Configuración Skype
Pantalla de configuración de la cámara en Skype

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$" && break
    done
} || 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:

  1. Se emitirá un "vídeo gracioso" en vez de usar la cámara del móvil.
  2. 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.

¡Un saludo!

viernes, 7 de agosto de 2020

Mandar contenido a la cámara

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.
  • Usar como fuente de entrada para OBS.
  • Etc.

Cargar el driver de v4l2loopback.

Antes de nada tengo que avisar que esto lo he realizado en un Ubuntu 20.04, así que en otras distribuciones algunos pasos pueden ser algo distintos.

Lo primero que necesitaremos es instalar algunas dependencias:

  • v4l2loopback-dkms: Esta nos permitirá crear la cámara virtual.
  • v4l-utils: Esta nos permitirá controlar los detalles de la cámara.
  • ffmpeg: Esta nos permitirá mandar contenido a ella.
  • youtube-dl: Esta nos permitirá usar vídeos de Youtube como fuente (opcional).
sudo apt install v4l2loopback-dkms v4l-utils ffmpeg youtube-dl

Una vez tengamos las dependencias descargadas e instaladas, hay que crear la cámara virtual. Para ello hay que:

sudo modprobe v4l2loopback video_nr=0 card_label="Mi webcam 1"

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.

Para ver sus detalles se puede ejecutar:

v4l2-ctl --info --device 0
v4l2-ctl --info --device 3
v4l2-ctl --info --device 5

Mandar contenido a la cámara.

Una vez creada la camara, solo queda enviarle contenido:

ffmpeg -re -i vídeo.mkv -vf hflip -f v4l2 /dev/video0
  • -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:

youtube-dl -F https://www.youtube.com/watch?v=t9sK3mD5kzc

En mi caso he optado por la 135.

Ahora para mandarlo a la cámara:

fuente=$(youtube-dl -g -f 135 https://www.youtube.com/watch?v=t9sK3mD5kzc)
ffmpeg -re -i $fuente -f v4l2 /dev/video0

Aquí lo único diferente es que he decidido trocear el comando en 2 partes por claridad.

Y esto es todo.

En la próxima entrada comentaré como hice para usar la cámara de mi Android como webcam mediante la WiFi. 

sábado, 13 de junio de 2020

Transcodificar vídeos con el móvil

Avisos previos.

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.

Nota: No es necesario, pero recomiendo por comodidad el teclado Hacker's Keyboard o WiFi Keyboard.

Como funciona.

Los script se dividen en 2.

  • 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:

  1. Uso el primer script para transcodificar toda una carpeta en otra destino.
  2. Visualizo los vídeos con alguna herramienta para ver que están bien.
  3. 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).

Scripts.

Script 1 (transcode.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[@]}"; do while read 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

Script 2 (rename.sh)

#!/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-%S err(){ 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 ]] && break done 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=$1 local sha=$(shasum "$2"|sed 's/\( \+\).*/\1/') while [[ -f $ret ]]; do echo "$sha$ret" | shasum -cs && break z=$(($z + 1)) ret=${nom}_$z.$ext done echo -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" while read i; do echo -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 ]]; then echo -e "Ya existe \e[31m$new\e[0m." rm "$old" else echo -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; do echo -n $'\007' sleep 0.3 done echo echo -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; do echo -n $'\007' sleep 0.3 done echo echo -e "\e[1;36m-- \e[1;32m¡Listo! \e[1;36m--\e[0;0m" read -sn1

domingo, 26 de noviembre de 2017

Como poner un contenedor LXD en tu misma red local

En esta entrada me gustaría habar de LXD y un problema que considero que es común pero al que no he encontrado una respuesta satisfactoria por ningún lado.
Se trata de como poner un contenedor en la misma red local en la que se encuentra el anfitrión (la máquina sobre la que está montado el LXD).

Antes de nada decir que no explicaré como instalar o configurar LXD, ya que considero que hay literatura de sobras al respecto (y muy buena).
No obstante decir que LXD es una forma "suave" de crear "maquinas virtuales" en linux (dicho pronto y mal).

Al lio.

Método 1: MacVlan

NOTA: Para todos los ejemplos asumiré que existe un contenedor llamado "miContenedor" y que cuenta con una interface llamada "ethContenedor". También asumiré que la máquina anfitriona ("Anfitrión") tiene una interface llamada "ethHost".
NOTA2: También asumiré que el anfitrión es un Debian (o basado en Debian como por ejemplo Ubuntu) sin ningún gestor de redes como "network-manager" que inhabilite el fichero "/etc/network/interfaces".

Cuando queremos poner un contenedor en nuestra misma red local, se nos aconseja añadir una interface de tipo "macvlan". Este sería el comando para hacer dicha tarea:
 lxc network attach ethHost miContenedor ethContenedor

Con eso ya tendríamos el contenedor en la misma red local que el anfitrión utilizando el DHCP que tenga la propia red. Así de simple. El resultado podéis verlo en la imagen siguiente.



Ahora, esto tiene un gran "Pero...".
Si deseas comunicar el anfitrión con el contenedor por esa interface, simplemente no puedes. En el momento en el que creas una macvlan, anfitrión y contenedor quedan incomunicados por esa interface. El resto de dispositivos de la red podrán ver a ambos.
Por tanto según el esquema de antes, "otroEquipo" podría ver a todos los equipos de la red, pero "miContenedor" no podría ver a "Anfitrión" y viceversa.
Si esta limitación no te importa, este es el mejor procedimiento para meter tu contenedor en tu misma red local, así que no necesitas seguir con el post.

Una forma de soslayar el problema es tener 2 interfaces entre anfitrión y contenedor, de tal forma que comuniques por una con la red local y por la otra con el anfitrión. Otra forma, es usando un puente.

Método 2: Puente

Otra forma de conseguir meter al contenedor en la misma red local sin limitaciones, es hacerlo a través de un puente virtual. De tal manera que tendríamos un escenario como el de la siguiente imagen.

Como se aprecia, ambas máquinas, anfitrión y contenedor están conectados al mismo puente virtual, de tal forma que no hay problemas de conectividad.

Para llegar a esto, haremos 2 cosas. La primera quitar la configuración de red a la interface por la que se comunica la maquina anfitriona y pasarla al puente. Supongamos que la maquina tiene la siguiente configuración:
ip -4 addr show
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
   inet 127.0.0.1/8 scope host lo
     valid_lft forever preferred_lft forever
 3: ethAnfitrion: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
   inet 192.168.1.3/24 brd 192.168.1.255 scope global ethAnfitrion
     valid_lft forever preferred_lft forever
 4: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
   inet 10.137.142.1/24 scope global lxdbr0
     valid_lft forever preferred_lft forever

Bien, pues tendríamos que configurar nuestro fichero de "/etc/network/interfaces" algo así:
Nota: omitiré la de "lo" y "lxdbr0" (si está) ya que no hay que tocarlas:
auto ethAnfitrion
allow-hotplug ethAnfitrion
iface ethAnfitrion inet manual

auto mibr0
iface mibr0 inet static
    address 192.168.1.3/24
    gateway 192.168.1.1
    bridge_ports ethAnfitrion
    dns-nameservers 8.8.8.8 8.8.4.4

Ahora para hacer los cambios efectivos sin reiniciar, hay dos formas:
Reiniciando los servicios de red:
sudo service networking restart

O la que me parece más correcta. Crear el puente a mano.
Primero eliminamos la ip de la interface anterior:
sudo ip address flush dev ethAnfitrion

Ahora creamos el puente y agregamos la interface:
sudo ip link add name mibr0 type bridge
sudo ip link set mibr0 up
sudo ip link set dev ethAnfitrion master mibr0

Finalmente restablecemos la ip:
sudo ip address add 192.168.1.3/24 dev mibr0

Si por algún motivo no salimos a internet, tal vez sea necesario restablecer la puerta de enlace:
sudo ip route delete default
sudo ip route add default via 192.168.1.1


Si todo ha ido bien, ahora nuestra configuración tendría que quedar algo así:
ip -4 addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
  inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
4: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
  inet 10.137.142.1/24 scope global lxdbr0
    valid_lft forever preferred_lft forever
5: mibr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
  inet 192.168.1.3/24 brd 192.168.1.255 scope global br0
    valid_lft forever preferred_lft forever

Si os fijáis, "ethAnfitrion" no aparece en la lista. Esto es normal, ya que ahora no tiene dirección IPv4. Si se quiere ver todas las interfaces independientemente de si tienen o no dirección, hay que ejecutar:
ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    valid_lft forever preferred_lft forever
3: ethAnfitrion: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master mibr0 state UP mode DEFAULT group default qlen 1000
    link/ether 00:12:34:56:78:9A brd ff:ff:ff:ff:ff:ff
4: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 12:51:0d:22:19:6c brd ff:ff:ff:ff:ff:ff
5: mibr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether A0:98:76:54:32:10 brd ff:ff:ff:ff:ff:ff

Meter el contenedor en la red

Con la red ya configurada, solo queda el paso final. Para ello solo hay que ejecutar:
lxc network attach mibr0 miContenedor ethContenedor

Y eso es todo. Espero que si has llegado hasta aquí esto te sea de utilidad.
Si tienes dudas o encuentras errores, te invito a comentar.

Un saludo!

miércoles, 8 de marzo de 2017

Yo (no) Robot. (El problema de los Robots).

Desde hace años me ronda la cabeza una cuestión a la que Bill Gates le dio "solución" hace unos días. Esa cuestión es el tema de la mano de obra robot.

Antes de seguir, me gustaría aclarar el concepto de robot, ya que creo que hay mucha gente que tiene un concepto desacertado sobre ellos.
Ha de entenderse un robot no como un individuo, un ente o entidad capaz de realizar una tarea cualquiera de forma autónoma y sobre todo de forma independiente. Hay que sacarse de la cabeza el estereotipo de robot humanoide que se nos presentan en novelas como "Yo Robot" o películas como "Autómata" o "Terminator". Un robot es mucho más que eso. Es una maquinaria que generalmente es de propósito específico capaz de realizar una o varias tareas concretas de forma extremadamente precisa y eficiente. Puede tratarse de un ordenador que recomiende viajes, un coche que se desplace solo, un brazo que realice soldaduras en una fabrica de coches, etc.

Echando la vista atrás, desde los tiempos de la revolución industrial, la maquinaría ha ido desplazando el trabajo humano. Primero fueron las fabricas textiles y ahora son los taxis y vehículos de reparto. Este desplazamiento se debe a que las maquinas pueden realizar el mismo trabajo que una persona de forma más rápida y precisa. Este hecho está llevándonos a una situación inevitable en la que la gran mayoría de trabajos serán remplazados por robots.

Cuando imaginamos un futuro en el que vivir, a todos nos gusta pensar en una sociedad utópica en la cual no hay que trabajar ya que todo el trabajo lo realizan los robots. Y creo que este futuro poco a poco se acerca, pero no como nos gustaría.
Si en una empresa trabajan 100 personas de las cuales 90 son reemplazadas por robots, son 90 sueldos que se ahorra la empresa.
También se puede ver esto desde otra perspectiva:
Si en una empresa trabajan 100 personas de las cuales 90 son reemplazadas por robots, son 90 personas menos que dejan de recibir un salario.
Si juntamos esto, nos topamos en este ejemplo con una sociedad en la cual solo el 10% de las personas tienen acceso al dinero existente, lo cual hace que la sociedad utópica que comentaba antes, deja de ser utópica.

Para solucionar esta desigualdad, Bill Gates propone algo muy razonable. Que los robots paguen impuestos.

Pienso que no sería acertado decir que los robots paguen impuestos, ya que los robots no son personas y no pueden pagarlos, pero sí las empresas que los controlan. También es evidente que no pueden ser pagados de la misma manera en la que lo haría un trabajador, ya que un robot podría realizar la tarea de uno o más operarios. Según lo veo yo, tendría que tratarse de un impuesto tecnológico a la empresa, en el cual, el porcentaje de ese impuesto tendría que ir determinado por el volumen de trabajo realizado por robots.
Como se ve es una medida sencilla que asegura un mínimo reequilibrio social. Sin embargo es un equilibrio ficticio, ya que los impuestos irían a parar al estado, y eso significa que no necesariamente las personas ven ese dinero. Por ejemplo ¿Qué haría el estado si de pronto se encuentra con un presupuesto mayor para sanidad? Pues en el mejor de los casos, gastar más en sanidad. Pero ¿Y si necesito un coche, una tablet o unas vacaciones en Cancun? ¿Va a pagar el estado esos? Rotundamente no.

Como se ve, según este planteamiento, una sociedad "ideal" donde los trabajos estén 100% automatizados no resultaría para nada beneficiosa para las personas.

A modo de opinión, creo que este problema tiene muy mala solución dentro del mundo capitalista tal y como lo conocemos. No es posible tratar de repartir la riqueza entre la población sin que salgan sentimientos como "caridad" o "parasitismo". Algo que considero muy negativo.
No parece justo que cada vez más gente pierda su empleo, o mejor dicho, su acceso a un salario, cuando la industria siguen avanzando a la vez que reduce sus puestos de trabajo.

Esta entrada está un poco fuera de lo que esperaba para este blog, pero me parecía interesante ponerla como reflexión.