Simpl varnostna kamera z motion detekcijo

Bolj kot proof of concept, kot zaradi česar drugega sem si vzpostavil doma video nadzor enega prostora. Za kamero sem izbral Full HD kamero pri priljubljenem kitajcu, ki je skupaj z dvema dodatkoma za PoE (da imam do kamere le en kabel, ki vključuije tudi napajanje), prišla cirka 40 USD. Kamera ima sicer fajn sliko, sicer pa je gledana iz vidika uporabnika eno navadno kitajsko sranje. Namreč spletna stran kamere, preko katere lahko gledaš kaj snema, je samo v kitajščini, za samo gledanje pa uporablja neke čudne plugine, ki jih v 50% nisem uspel inštalirati. Priložen CD pa tako ali tako nisem imel kam vtakniti, ker moji maci pač ne podpirajo malih CDjev. Sicer sem nato prenesel programsko opremo iz spletne strani proizvajalca, ampak kaj več, kot da sem kameri spremenil IP, bolj primeren za moje domače omrežje, nisem uspel narediti.  Sploh, ker je ves software za windowse, ki jih pač nimam.

Ampak kamera deluje, in na spletu sem našel podatke, kako lahko sliko iz nje dobim z recimo VLC programov, kar mi v bistvu zadošča.

Ampak pregledovanje ur in ur videa, da vidiš, če se je kaj dogajalo je pač nerealno, zato je bil naslednji korak, kako izvesti “detekcijo gibanja”, da dobiš potem le dele videa, kjer se je dejansko kaj dogajalo. Izbral sem motion, ki teže na linuxu in dela točno to. Z to težavo, da kot video vhod ne zna sprejeti RTSP streama iz kamere. Ker pa kot vhod podpira posamezne slike, sem ta del pač moral narediti sam. Po specifikacijah kamere, naj bi kamera sicer podpirala FTP in s tem verjetno avtomatsko pošiljanje slik na nek ftp naslov, kjer bi jih nato motion zagrabil, ampak se s kamero dejansko nič takšnega nisem uspel zmeniti.

Del do generiranja slike tako izgleda takole:

#!/bin/bash
NOW=`date +"%Y%m%d-%H%M%S"`
cd /mnt/ext1TB/cam
/usr/bin/openRTSP -d 60 -b 200000 -B 200000 -F $NOW "rtsp://192.168.0.31:554//user=admin&password=&channel=1&stream=1.sdp"
nice /usr/bin/avconv -i ${NOW}video-H264-1 -c copy $NOW.mp4
rm ${NOW}video-H264-1
rm ${NOW}audio-PCMA-2
nice /usr/bin/avconv -threads 1 -i $NOW.mp4 -r 5 thumbs/${NOW}_%03d.jpg
rm $NOW.mp4

openRTSP iz kamere pobere 1 minuto videa in ga shrani v datoteko. 1 minutko zato, ker se je to izkazalo za stabilno, če sem poiskušal z 10 minutami, je vmes že nekaj crkovalo. Tiste nastavitve bufferja pa so se iz enakega razloga pokazale kot potrebne.
Nato sledi konverzija videa v mp4, ker izgleda da openRTSP stream iz kamere ne zapiše ravno berljivo za ostale, in ta konverzija to reši. Je pa to zelo hitra operacija, ker se dejansko nič ne prekodira, ampak samo zapiše na malenkost drugačen način.
Sledi brisanje vmesnih datotek in nato dejansko generiranje slik. Omejitev, da naj se uporabi le 1 thread je bolj zaradi omejevanja obremenitve strežnika, podaljšanje časa procesiranja pa je zaradi tega praktično nepomembno. Generiram pa 5 slik na sekundo.

Kot sem že pisal, je ta konverzija na Raspberry PI-ju kar obremenila procesor. Če sem uporabil Full HD video. Ampak dejansko za detekcijo premikov to ni potrebno. In ker kamera omogoča tudi manjšo kvaliteto, sem uporabil kar to, kar pa se potem sprocesira mimogrede. Tako, po občutku bi Raspberry PI 2, komot obdelal vsaj 4 takšpne kamere za ta namen. Seveda pa ne glede na to, da procesiram le video v najnižji kvaliteti shranjujem tudi video v Full HD kvaliteti, če bi bilo slučajno potrebno si ogledati več detajlov. Samo pobiranje videa pa tako ali tako računalnika ne obremeni skoraj nič.

Ko imamo enkrat slikice, pa je le te potrebno podtakniti motion-u, ki do njih lahko dostopa direktno na datotečnem sistemu, ali preko web servisa. Najprej sem poiskusil s prvo rešitvijo, in sicer z bash skripto kopiral zaporedne datoteke na ustrezno mesto, kar pa se ni izkazalo za ustrezno, saj je očitno prevečkrat sovpadlo kopiranje in branje slike, kar je povzročilo napake v samem motion-u. In to se je dogajalo tudi, če slik nisem kopiral ampak zgolj preimenoval. Tako da sem raje spisal kratko skripto v javascriptu, ki jo potem zaganjam z node.js. Motion pa dostopa preko http-ja.

motion.conf
// dve nastavitvi sta pomembni, kje naj pobira
netcam_url http://192.168.0.23/cam.jpg
// in v kakšnem intervalu. Glede na to, da mu podtikamo vedno novo sliko, lahko postavimo framerate višji od dejanskega intervala slik, saj bodo tako hitrejše
// sprocesirane, potem bo pa pač čakal
framerate 10
---
var http = require('http');
var fs = require('fs');
var sleep = require('sleep'); 

process.on('uncaughtException', function (err) {
  console.log(err);
  process.exit();
})

// Configure our HTTP server to respond with Hello World to all requests.

var dir = fs.readdirSync("/mnt/ext1TB/cam/thumbs/");
  var server = http.createServer(function (request, response) {
  if (dir.length<=0) dir = fs.readdirSync("/mnt/ext1TB/cam/thumbs/");
  if (dir.length<=0) {
    // ce ni nobene slikice naredim pauzo, da ne gre motion prehitro po novo, ki je tako ali tako verjetno še ne bo, in je tako server manj procesira
    console.log("Nothing new.");
    response.writeHead(404);
    sleep.sleep(10);
    response.end();
  } else {
    response.writeHead(200, {"Content-Type": "image/jpeg"});
    var file = dir.shift();
    console.log("Sending "+file+" ("+dir.length+")");
    var readStream = fs.createReadStream("/mnt/ext1TB/cam/thumbs/"+file);
    readStream.pipe(response);
    readStream.on('end', function() {
      response.end();
      fs.unlink("/mnt/ext1TB/cam/thumbs/"+file);
      console.log("delete "+file);
    });
  }
});

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(80,"0.0.0.0");
// Put a friendly message on the terminal
console.log("Server running at http://192.168.0.23:80/")

In kot rezultat dobimo vide delov, kjer se je kaj dogajalo. Edina težava opažena do sedaj je v času, ko se dan spreminja v noč, in se neko obdobje kamera odloča ali že vklopi IR diode ali ne, in takrat pride do migotanja, ki je razpoznano kot premikanje. Pa še to ne vsak dan. Sicer pa dela zelo zanesljivo.

Za 100 EUR si tako lahko omislite polno varnostno video rešitev. Za 200 pa takšno s 4 kamerami, kar je verjetno dovolj, da pokrijete lastno hišo pa še izveste kaj dogaja pri sosedu.