Eliminar el fondo de un vídeo

Hoy me ha llegado otro reto que he terminado resolviendo con IA :)

Se trata de un vídeo en el que aparece una persona y detrás una fea y arrugada sábana blanca que en el vídeo se ve amarillenta. El pedido ha sido eliminar el fondo.

Las opciones iniciales eran hacerlo con kdenlive o con blender y muchas horas de marcar puntitos para cada uno de los frames. El vídeo en cuestión tiene un total de 7933 frames y como que no…

He empezado a buscar opciones y he encontrado clipdrop (cerrado aunque tiene opción de API) y he decidido seguir buscando. En la búsqueda he encontrado backgroundremover interesante pero con resultados deplorables y finalmente rembg (con mejores resultados pero enfocado a imágenes).

Así que de nuevo la solución ha sido crear un script. Esta vez me he decantado por bash.

#!/bin/bash

# Fix video's FPS
echo "Converting video to 30 FPS..."
ffmpeg -i video.mp4 -r 30 -c:v libx264 -crf 18 -preset fast -c:a copy video_30.mp4

# Crea temp directories
#mkdir -p original_images
#mkdir -p processed_images

# Generate one image for each frame and save to original_images directory
echo "Extracting frames as images..."
ffmpeg -i video_30.mp4 -vf "fps=30" original_images/frame_%04d.png

# Delete the background of each image of original_images to processed_images
echo "Removing backgrounds from images..."
for img in original_images/frame_*.png; do
    output_name="processed_images/$(basename "$img")"
    rembg i "$img" "$output_name"
done

# Join all the images from processed_images to a video and use audio from video_30.mp4
echo "Combining processed images into a video with 

Script para generar el fichero sitemap.xml de una web estática

Hace unos años hice el crawling de la web antigua de kaosenlared. Ahora tiempo mas tarde el analytics de google les estaba dando muchos errores de páginas no encontradas, así que he tenido que generar los ficheros sitemap.xml para que google indexe el sitio.

He hecho un primer script para listar todas las páginas index.html del directorio y generar el fichero sitemap.xml que ocupaba la friolera de 150Mb pero al metérselo a google analytics daba errores de tamaño de archivo. Buscando los límites, nos encontramos que el sitemap.xml no puede ser más grande de 50Mb ni contener más de 50.000 entradas. Así que ha sido necesario crear un índice y separar los sitemap.xml en ficheros más pequeños.

A continuación el script de como lo he hecho

#!/bin/bash

# Directori on es troben les pàgines html
DIRECTORI=/home/virtualmin/archivo.kaosenlared.net/public_html

# URL base del lloc web
URL_BASE=https://archivo.kaosenlared.net

current_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

# Funció per generar el sitemap.xml
generar_sitemap() {
  # Initialize the URL count and the file number
  url_count=0
  file_number=1

  # Initialize the sitemap file name
  sitemap_file="sitemap_${file_number}.xml"
  sitemap_index="sitemap.xml"

  # Inicialitza el fitxer sitemap.xml
  echo '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' > $sitemap_index

  echo '<?xml version="1.0" encoding="UTF-8"?>' > $sitemap_file
  echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">' >> $sitemap_file


  echo "  <sitemap>" >> $sitemap_index
  echo "    <loc>$URL_BASE/$sitemap_file</loc>" >> $sitemap_index
  echo "    <lastmod>$current_date</lastmod>" >> $sitemap_index
  #echo "    <changefreq>monthly</changefreq>" >> $sitemap_index
  echo "  </sitemap>" >> $sitemap_index


  # Recorre els fitxers html del directori i subdirectoris
  find $DIRECTORI -type f -name "*.html" -not -path "*mailto*" -not -path "* *" -not -path "*&*" | while read 

Ficheros mp3

Este fin de semana en un curso el profesor comentaba que los ficheros mp3 se degradaban con el uso y terminaban dando problemas como cortes y que era mejor usar otros formatos como WAV o FLAC. Me sorprendió lo comentado, ya que según mi entendimiento, cuando abres un fichero mp3, este se carga en memoria (RAM) y desde ahí se realiza todo el proceso de descompresión.

Así que el objetivo de este post es el de comprobar y demostrar lo comentado. Esto también me sirve para corroborar a nivel de perito informático qué ocurre con la reproducción de ficheros de audio, vídeo y fotografías (el concepto es el mismo).

Para ello voy a usar un script que reproduzca 100 veces un clip de audio y compruebe en cada reproducción el hash del fichero.

Antes de empezar voy a instalar sox y libsox-fmt-mp3 para reproducir el mp3 en consola

# apt install sox libsox-fmt-mp3

Y voy a usar el siguiente script

$ vi play_mp3_and_check_hash.sh
#!/bin/bash

AUDIO_FILE=duck_quack.mp3

for ((i=1;i<=100;i++));
do
   SUM=`md5sum ${AUDIO_FILE}`
   echo "Loop number: ${i}, hash is: ${SUM}"
   play -q ${AUDIO_FILE} 2>/dev/null
done

Le doy permisos y lo ejecuto

$ chmod +x play_mp3_and_check_hash.sh
$ ./play_mp3_and_check_hash.sh
Loop number: 1, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 2, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 3, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 4, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 5, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
[...]
Loop number: 97, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 98, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 99, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3
Loop number: 100, hash is: 50c8fa8d674e6598951ab69bf2596c5d  duck_quack.mp3

Y la conclusión es que, …

Script para reiniciar nginx cuando han caducado los certificados de letsencrypt

Últimamente estoy de scripts para automatizar mi vida de sysadmin ;) aquí os dejo otro que comprueba si se han renovado los certificados y reinicia nginx en caso de que si haya ocurrido

# vi /root/scripts/check_certificates2.sh

#!/bin/bash

ADMIN_MAIL=""
DOMAINS=($(nginx -T |grep server_name |grep ";" |grep -v "#" |awk '{print $2}' |sed 's/;//' |grep -v "_" | sort -u))
CHECK_DIR="/root/scripts/check_domains"
REBOOT_NGINX=0

mkdir -p ${CHECK_DIR}

for i in "${DOMAINS[@]}"
do
   if [[ -f ${CHECK_DIR}/$i ]]; then
       OLD=`cat ${CHECK_DIR}/$i |awk '{print $1}'`
       CURRENT=`sha1sum /etc/letsencrypt/live/${i}/cert.pem |awk '{print $1}'`
       if [[ ${OLD} != ${CURRENT} ]]; then
           echo "hashes don't match for domain ${i}, please restart nginx"
           REBOOT_NGINX=1
           sha1sum /etc/letsencrypt/live/${i}/cert.pem ${CHECK_DIR}/$i
       fi
   else
       if [[ -f /etc/letsencrypt/live/${i}/cert.pem ]]; then
           sha1sum /etc/letsencrypt/live/${i}/cert.pem ${CHECK_DIR}/$i
       else
           echo "Domain ${i} has no certificate file"
       fi
   fi
done

if [[ ${REBOOT_NGINX} == "1" ]]; then
    echo "I reboot nginx due there are changes on certificates"
    service nginx restart
fi

Luego hago que se ejecute cada 10 minutos y listos

# vi /etc/crontab
*/10 *  * * *   root    /root/scripts/check_certificates2.sh

Script para realizar un sha1sum recursivo de los ficheros un directorio

Volvemos a la carga con mas scripts de bash. Esta vez necesito realizar un sha1sum para obtener el hash sha1 de unos ficheros que están dentro de muchos directorios. Como sha1sum no soporta la opción recursiva (en mi opinión un fallo), no queda otra que recurrir a nuestro amado bash.

Aquí el script para la ocasión

#!/bin/bash

DIRECTORY="material"

find "$DIRECTORY" -type d -print0 -maxdepth 4 | while read -r -d '' d; do
  echo "#### SHA1SUM Directorio: $d #####"
  sha1sum $d/*
done

script para dividir pdf en pdf mas pequeños con pdftk o pdfjam

Mi buen amigo Bruno, hace unos días me pasó una extracción de un teléfono móvil con la friolera de más de 51.000 páginas. Mi pobre y humilde portátil sacaba humo sólo al abrirlo así que he tenido que ingeniármelas para dividir el fichero en ficheros más pequeños y poder gestionar la información cómodamente. La solución, un script.

El script tiene dos opciones, usar pdftk o pdfjam. Deberemos comentar y descomentar la línea que nos interese.

Si queremos usar pdftk será necesario instalarlo

# apt install pdftk

Para usar pdfjam, que me ha procesado la información más rápido que con pdftk, será necesario instalar texlive-extra-utils

# apt install texlive-extra-utils

Otra herramienta que será necesario instalar es pdfinfo que se encuentra dentro del paquete poppler-utils

# apt install poppler-utils

A continuación el script

#!/bin/bash

INPUT_FILE=Redmi7-ASPERTIC.pdf
PAGES=`pdfinfo ${INPUT_FILE} |grep Pages |awk -F '           ' '{print $2}'`
FILENAME=`basename ${INPUT_FILE} |awk -F '.' '{print $1}'`
SPLIT=500
START=1
echo "Total Pages: ${PAGES}"
echo 

COUNTER=$START
ITER=1

while [ "$COUNTER" -le "$PAGES" ]
do
    START=$(($COUNTER))
    END=$(($START + $SPLIT - 1))
    echo 
    echo "#################"
    echo "start ${START} end ${END} iter ${ITER}"
    if [[ "$PAGES" -le "$END" ]]
    then
       END=$PAGES
       echo "last end is ${END} of total pages ${PAGES}"
    fi
    #pdftk ${INPUT_FILE} cat ${START}-${END} output ${FILENAME}_${ITER}.pdf
    pdfjam ${INPUT_FILE} ${START}-${END} -o ${FILENAME}_${ITER}.pdf
    COUNTER=$(($COUNTER + $SPLIT))
    ITER=$(($ITER + 1))
done

Y listos, lo mismo de siempre, crear el fichero, darle permisos de ejecución y ejecutarlo!

Aquí una captura del final de la ejecución del script sobre el susodicho fichero

Una utilidad …

script para identificar registros duplicados en sqlite3

En uno de mis proyectos estamos ya en la recta final a punto de poner en producción el nuevo programa. A último momento siempre te encuentras con aquellas puñetitas que hacen que la migración no salga como es lo esperado, es por esto que es muy importante practicar la migración al igual que si de una audición se tratase.

La puñetita con la que me he encontrado trata precisamente de la importación de datos mas grande, la de una tabla de 4Gb de datos, que contiene las lecturas de unos sensores, he decidido separarlas en alrededor de 4.000 ficheros de base de datos sqlite3, uno para cada uno de los sensores. Al realizar la importación de cada uno de los sensores de forma individual, de maravilla, pero a la que se hace el proceso de migración de todos los sensores, algunas de las lecturas se duplican y no he conseguido hallar el porqué ocurre.

Ya hace unos días puse un par de controles que si el fichero ya existía o la base de datos estaba siendo usada, pasase al siguiente sensor, aún así seguían duplicandose los datos. La solución era añadir un tercer control que comprobase que el registro ya estaba guardado, pero que ralentizaría la migración de los datos de forma significativa y la primera migración el interés es que sea lo más ágil posible. Así que dándole un par de vueltas y muy importante, tras más de 24h de no tocar el código (se llama descansar), he encontrado …

Subir un directorio por ftp por consola

Tengo un cliente al que le tengo que migrar el servicio a un hosting de estos con cpanel y estas mierdas. Para subir los ficheros tengo que subirlos por FTP pero el wordpress que tengo que subir tiene mogollón de ficheros y subirlos uno a uno es para morirse. Además quiero hacer la transferencia de los ficheros directamente desde el servidor.

El cliente ftp básico no me permite subir un directorio completo, así que estoy usando otro cliente ftp, ncftp.

Lo instalo usando

# apt -y install ncftp

Y me posiciono en el directorio donde tengo el wordpress

# cd /var/www/

y lo subo usando

# ncftpput -avR -u  -p   

directorio_remoto: es el directorio del servidor remoto, en mi caso public_html
directorio_local: donde tengo el wordpress en mi servidor, wp…

Generar certificado autofirmado con openssl

Llega el momento de poner a producción un programa que llevas más de un año desarrollando, para montarlo necesito generar unos certificados autofirmados para cuando el dominio apunte a mi servidor generar los certificados de letsencrypt. De mientras el apunte de como generarlos con openssl:

# cd /etc/autosigned-certs/
# mkdir domain.com
# cd domain.com
# openssl req -nodes -newkey rsa:2048 -keyout domain.com.key -out domain.com.csr
# openssl x509 -req -in domain.com.csr -signkey domain.com.key -out domain.com.crt

En nginx comento las líneas que corresponderían al certificado de letsencrypt y añado los certificados autofirmados

        #ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
        #ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
        #include /etc/letsencrypt/options-ssl-nginx.conf;
        #ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
        ssl_certificate /etc/autosigned-certs/domain.com/domain.com.crt;
        ssl_certificate_key /etc/autosigned-certs/domain.com/domain.com.key;

Tip del día.…

script para convertir pdf a png

Uno de los recursos que necesito al crear un informe pericial es convertir un documento pdf a imágenes png para poder añadirlo en el anexo el informe.

Os dejo el script que uso para convertir los pdf a png. Lo pones y lo ejecutas en el directorio donde tienes los pdf y te genera todos los png.

#!/bin/bash

for p in *.pdf
do
   pdftoppm "$p" "$p" -png
done

Para ejecutarlo, primero le damos permisos de ejecución y luego lo ejecutamos

$ chmod +x convert_pdf_to_png.sh
$ ./convert_pdf_to_png.sh

Y listos! Tip rápido y útil del día.…