Sistema de CCTV con Linux Publicado por Deimos el20/Nov/2017 - 03:19 PM



Hace rato que tenía algunas cámaras de CCTV por ahí y quería darles uso, aunque no lo había hecho por falta de un DVR; se me ocurrió utilizar mi laptop para grabar el video, aunque claro, quedaba el problema de la recepción de video. Lo primero que llega a la mente es una tarjeta de video, de esas con entrada BNC, pero claro que no iba a entrar en una laptop. 

En fin, hace un par de semanas me compré un adaptador de video a USB, bastante económico ($170.00 MXN), por lo que mi preocupación de que fuera compatible o no con Linux ya no aumentaba por el precio. El adaptador que compre es un Easycap, aunque ya físicamente es de la marca KaiPing. Cuenta con entrada de video compuesto y super video, además de entrada de audio estèreo. 

Por supuesto, todo esto se puede hacer con una webcam. Dejo el link del adaptador:
https://articulo.mercadolibre.com.mx/MLM-542089153-easycap-tarjeta-capturadora-usb-20-rca-s-video-audio-video-_JM 



Linux (Ubuntu 16.04) ha reconocido sin problemas el dispositivo, conectè directamente la salida de video de una càmara AvTech y pude visualizarla con el programa VLC. La cuestión entonces era poder grabar el video en mi disco duro, y para ello me ayudé de ffmpeg

Podemos probar la grabación con el siguiente comando: 

$ ffmpeg -f video4linux2 -i /dev/video1 test_record.wmv

Es posible cambiar el formato del video, aunque para ahorro de espacio, wmv me ha servido bien. Entonces para realizar una grabación continua bastaría con crear un script como éste: 

$ nano record_now
#!/bin/bash
# By +DEIMOS+  Record video

cd /home/deimos/cctv
#Wait until device not busy
while fuser -v /dev/video1 > /dev/null 2>&1; do
   #printf '%s\n' "device in use wait..."
   sleep 1
   #WAIT ....
done

NOW=`date +"%b_%d_%Y_%T"`
NAME="rc_"$NOW
echo "Record in "$NOW
LOCAL_PATH="./records/"$NAME
if [ -d "$LOCAL_PATH" ]; then
    DAT=$(date +"%m-%d-%Y %H:%M:%S")
    echo "[$DAT] File '$LOCAL_PATH' already exists."
    exit
fi

ffmpeg -f video4linux2 -i /dev/video1 -t 00:59:00  -an -r 20 $LOCAL_PATH.wmv

Grabará hasta 59 minutos de grabación, excluyendo el audio y a 20 cuadros por segundo. algo así como 15.5 MB por cada archivo. Lo que seguiría sería configurar nuestro cron para que ejecute el script cada hora: 

$ crontab -e
# CCTV Record
00 * * * * /home/deimos/cctv/record_now

Todo va muy bien, comienza a grabar en archivos de 1 hora, pero, ¿Qué pasa cuando queremos visualizar en tiempo real? El problema es que el script de grabación está haciendo uso del dispositivo, por lo que si queremos conectarnos a èl nos darà el error de dispositivo ocupado. 

La solución está en hacer un streaming del video hacia nuestra red local, estará disponible para que el script de grabación tome el video de ahí, ademàs de que podemos visualizar el video en cualquier momento, y además, si así lo queremos, permitir acceso en nuestra LAN o a nivel de internet. 

Lo primero es levantar el servidor de streaming, para ello utilizaremos ffserver; vamos a editar el archivo de configuración: 

$ sudo nano /etc/ffserver.conf

Añadimos el siguiente stream: 

# FLV output - good for streaming
<Stream camara1.flv>
# the source feed
Feed feed1.ffm
# the output stream format - FLV = FLash Video
Format flv
VideoCodec flv
# this must match the ffmpeg -r argument
VideoFrameRate 20
# generally leave this is a large number
VideoBufferSize 800
# another quality tweak
VideoBitRate 200
# quality ranges - 1-31 (1 = best, 31 = worst)
VideoQMin 1
VideoQMax 15
VideoSize 512x384
# this sets how many seconds in past to start
PreRoll 0
# wecams don't have audio
Noaudio
</Stream>

Ya podríamos lanzar el servidor con: 

$ sudo ffserver -f /etc/ffserver.conf

Lo que sigue es capturar el video de la cámara y enviarla al servidor para que haga el straming:

$ nano transmit_video_to_server
#!/bin/bash
# By +DEIMOS+  Record video

# Wait until device not busy
while fuser -v /dev/video1 > /dev/null 2>&1; do
   sleep 1
   #WAIT ....
done

ffmpeg -f video4linux2 -i /dev/video1 http://localhost:8090/feed1.ffm

Ahora, vamos a crear un script que realice las grabaciones tomando el video desde el streaming: 

$ nano record_from_streaming
#!/bin/bash
# By +DEIMOS+  Record video

cd /home/deimos/cctv
NOW=`date +"%b_%d_%Y_%T"`
NAME="rc_"$NOW
echo "Record in "$NOW
LOCAL_PATH="./records/"$NAME
if [ -d "$LOCAL_PATH" ]; then
    DAT=$(date +"%m-%d-%Y %H:%M:%S")
    echo "[$DAT] File '$LOCAL_PATH' already exists."
    exit
fi

ffmpeg -i http://localhost:8090/camara1.flv -t 01:00:05  -an -r 20 $LOCAL_PATH.wmv

Básicamente es el mismo script de grabación, pero ya no tenemos que esperar por el dispositivo y tomamos como entrada el streaming. Ahora actualizamos cron: 

$ crontab -e
# CCTV Record
00 * * * * /home/deimos/cctv/record_from_streaming

Vualá, tenemos un pequeño sistema de CCTV en nuestro Linux. Ojo: todo esto lo he montado en un pequeño momento de ocio, funciona bien, pero necesita mejoras. Lo que he hecho hasta ahora es configurar estos script como servicios para facilitar las cosas. 

Algunas cosas pendientes que haré en cuanto tenga algo de tiempo son: Si el dispositivo se desconecta y vuelve a conectarse, la grabación se detiene y comienza de nuevo hasta la siguiente hora; además sería bueno que detecte la ruta donde se encuentra el dispositivo, por ahora, asumimos que se encuentra en /dev/video1. Sin mencionar que hace falta una etiqueta mostrando la marca de tiempo.

Eso ha sido todo por ahora, espero que haya sido interesante. Suscríbete para que estés al tanto de actualizaciones del post.

Luis Manuel Ramírez +DEIMOS+

Fuentes: 
https://gist.github.com/iabaldwin/1298713