Nei giorni scorsi ho provveduto a ripristinare la “webcam” sul sito dei Radioamatori RAI. Dico “webcam” perchè non è una webcam vera e propria: trattasi di una vecchia telecamera analogica Sony, 3CCD, collegata a una altrettanto vecchia scheda di acquisizione analogica consumer Pinnacle DC10+. L’obbiettivo, realizzare un sistema che automaticamente scatti una foto ogni minuto, ne salvi una copia su un ftp esterno, alla mezzanotte realizzi un timelapse pulendo successivamente la cache locale. Come ottenere tutto questo? Semplice, con Linux, un po’ di Python e un altro po’ di script shell.
Acquisizione del video analogico
Partiamo dall’inizio: la telecamera genera un segnale video a colori in standard PAL, trasmesso in composito su un singolo cavo coassiale a 75?. Noi vogliamo farlo acquisire dalla nostra scheda video, montata in una macchina che gira in ambiente Linux. La scheda DC10+ è, per nostra fortuna, ampiamente supportata a partire dal kernel 2.6 e il kernel 4.X.x della distro in uso non fa eccezione. Dobbiamo però utilizzare alcuni accorgimenti perché la scheda è un po’ rognosetta. Innanzitutto, per una questione di continuità del buffer di memoria, dobbiamo limitare la memoria che verrà utilizzata dal sistema, riservandone un blocco per i nostri scopi video…
In Ubuntu 16.04 LTE Server, dobbiamo inserire la seguente riga nel file /etc/default/grub
GRUB_CMDLINE_LINUX="mem=950m"
dobbiamo poi creare il file /etc/modprobe.d/zr36067.conf che conterrà i parametri specifici del modulo zr36067 (Zoran 36067 è il chip effettivamente in uso nella scheda. Vedere la pagina su video4linux per dettagli). Il file consta di una sola riga:
options zr36067 v4l_bufsize=2048 card=2 v4l_nbufs=32
nel dettaglio, indica alla macchina i dettagli del modulo zr36067, la dimensione del buffer video (2048), l’ID della scheda video (2, per la Pinnacle DC10+) e il numero di buffer. Il valore di default di v4l_bufsize è 512 (Kb) che è troppo poco per i nostri scopi. Se lanciaste l’acquisizione con tale valore avrete un bel errore “not enough menory”.
A questo punto rigenerate il ramdisk iniziale e riavviate la macchina:
update-initramfs -u
shutdown -r now
L’hardware adesso “è vivo e lotta con noi”, è il momento di occuparsi del software. Ho scelto di utilizzare fswebcam per la sua semplicità di configurazione. Ci sono altri software che permettono l’acquisizione di still da video, si può fare direttamente con ffmpeg, anche. Dipende un po’ dalle vostre esigenze e dal tempo che potete spenderci dietro.
Dicevamo di fswebcam. Per prima cosa va installato, Ubuntu server non lo fa di default (ovviamente) per cui lanciamo il nostro
apt-get install fswebcam
creiamo poi il file di configurazione /root/.fswebcam.conf
device v4l2:/dev/video0
loop 60
skip 20
background
resolution 768x576
set brightness=60%
set contrast=50%
crop 758x576,10x1
font /usr/share/fonts/truetype/futura/FuturaBoldBT.ttf:12
title "IQ2RD - Gruppo ARCAL Radioamatori Rai Milano"
subtitle "WWloc: JN45nl"
timestamp "%d-%m-%Y %H:%M:%S (%Z)"
save /var/www/html/viewcam.png
palette YUYV
exec /root/rename.sh
Lanciate l’applicazione con il comando
fswebcam -c .fswebcam.conf
Per una spiegazione dettagliata delle opzioni di fswebcam vi rimando alla Manpage di Ubuntu oppure a quest’altra di R3UK, molto dettagliata (in inglese). Fate solo molta attenzione alla prima riga: specificate che è un device v4l2 (Video forl Linux V.2). Se omettete il device o utilizzate il semplice /dev/video0 non sarete in grado di acquisire correttamente il full-frame SD (che ricordo essere 768×576 pixel). Diventerete pazzi, darete testate agli spigoli ed evocherete divinità varie cercando di capire dove stia l’inghippo. Fidatevi, v4l2.
Se non avete la necessità di condividere le immagini della vostra camera sul web, l’articolo per voi può anche finire qui. Diversamente, ora vi spiego come aggiungere un overlay (un’immagine che può essere un logo, una scritta…) utilizzando imagemagick.
Dopo averlo opportunamente installato, andiamo a creare uno script di shell che si occuperà di automatizzare il processo rendendoci la vita più semplice. Create con il vostro editor di testo preferito il file rename.sh (mi sembra superfluo, ma vi ricordo che potete chiamarlo come volete. In ambiente Linux potete anche omettere l’estensione, io la uso per comodità mia e per capire a distanza di mesi che cos’è un determinato file):
#!/bin/bash
DATE=`date +%Y%m%dT%H%M`.png
cp /var/www/html/viewcam.png /var/www/html/archive/$DATE
composite -alpha on /root/iq2rd.png /var/www/html/viewcam.png /var/www/html/last.png
/usr/bin/python /root/ftpput.py
Questo script si occupa di rinominare il file in modo che il nome sia composto da AnnoMeseGiorno+T+OreMinuti (es. 20170804T1600) e lo va a collocare in una directory archivio. In seguito, con il comando composite imagemagick, va a sovrappore il file di overlay al file generato da fswebcam e lo salva come last.png. Questo script viene lanciato dal parametro exec presente in .fswebcam.conf.
L’ultima riga lancia un ulteriore script, questa volta in Python, che si occupa del upload sul server ftp, come vedremo nel prossimo paragrafo.
Upload delle immagini su server ftp
Molto bene, adesso il nostro computer scatta una foto ogni minuto e la va a salvare da qualche parte nei meandri dell’hard disk. Ora, a meno che il nostro computer non sia direttamente accessibile da Internet, dobbiamo fare in modo che la nostra still sia visibile al mondo, occorre quindi copiarla in una cartella del nostro server web, utilizzando il protocollo ftp. Lo script che abbiamo appena visto lancia alla fine un programma in python, ftpput.py
#!/usr/bin/env python
import os
import ftplib
session = ftplib.FTP('nomehost','username','password') # hostname, user e password del nostro account ftp
file = open('/var/www/html/last.png','rb') # file LOCALE da inviare
session.storbinary('STOR /webcam/last.png', file) # nome e percorso del file REMOTO
file.close() # close file and FTP
session.quit()
Avendo inserito la chiamata di questo programma in uno script a sua volta lanciato da fswebcam, il caricamento dell’immagine averrà ogni minuto (o meglio, al termine del processo di acquisizione di ogni nuova immagine).
Creazione del timelapse con ffmpeg
Abbiamo il nostro bel archivio di immagini, tante immagini se anche voi ne creerete una ogni minuto. Utilizzeremo ffmpeg per creare il timelapse, uno script python simile al precedente per caricare il video sul server e uno script shell per automatizzare il tutto
#!/bin/bash
cat /var/www/html/archive/*.png | ffmpeg -y -f image2pipe -framerate 24 -an -i - /var/www/html/archive/ieri.mp4
rm /var/www/html/archive/*.png
/usr/bin/python /root/movieput.py
In tal modo creiamo un file video mp4, con un framerate di 24 fps. Ffmpeg è un software molto potente e con svariate opzioni e possibilità. Non sto dicendo che questa è la migliore, sicuramente si può fare di meglio. Però questa funziona.
La seconda riga cancella tutte le immagini dall’archivio;
La terza riga lancia lo script python, identico al precedente tranne che (ovviamente) nei nomi dei file, che si occupa del upload.
Chiamiamo il nostro script purge.sh e lo andiamo a inserire nel crontab (crontab -e)
1 0 * * * /root/purge.sh
In tal modo, ogni giorno alle ore 00:01 la macchina genererà il timelapse e lo caricherà automaticamente.