raspberry py live streaming

I was going on a month long vacation and I wanted to monitor my appartment. Given I have pan tilt camera with facial recognition, I thought of implementing a live feed, control camera and add motion detection to it. Its been working for two months and not even a glitch. I just need to implement motion detection though.

Checkout ffmpeg source and compile on raspberry pi. It will take overnight to compile, so run make and have a good nights sleep. You may get some missing library errors (libfaac-dev), you need to install them.

 git clone git://source.ffmpeg.org/ffmpeg.git
 cd ffmpeg/
 ./configure
 make 
 sudo make install

Following command captures the video and pipes the output to ffmpeg. Ffmpeg converts the source video to hls format and stores the fragments on disk and keeps updating the manifest file. ffmpeg also cleans up the old fragments

raspivid -n -ih -t 0 -ISO 800 -ex night -w 200 -h 100 -fps 25 -b 2000000 -o - | sudo ffmpeg -y  -i -  -c:v copy  -map 0  -f ssegment -segment_time 4 -segment_format mpegts -segment_list "/usr/share/nginx/www/live/stream.m3u8" -segment_list_size 10 -segment_wrap 20 -segment_list_flags +live -segment_list_type m3u8 "/usr/share/nginx/www/live/%03d.ts"

Configure apache server to serve fragments from the disk. Contents of pache config file.

<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /usr/share/nginx/www/
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /usr/share/nginx/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Following is the html index file <html> <head> <title>PiVid</title> </head> <body> <video controls="controls" width="1280" height="720" autoplay="autoplay" > <source src="stream.m3u8" type="application/x-mpegURL" /> </video> </body> </html>

Cgi Scripts that increment the angle of servo. The script simply reads the current value from pipe and writes back the new angle. File : /usr/lib/cgi-bin/plus.cgi

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# enable debugging
import cgitb
cgitb.enable()

print "Content-Type: text/plain;charset=utf-8"
print

mpipe = open('/usr/share/nginx/www/live/pipe')
line = mpipe.readline()
angle = int(line)
newangle = angle + 10
print 'Got %d %d' % (angle, newangle )
mpipe.close()

mpipe = open('/usr/share/nginx/www/live/pipe','w')
mpipe.write(str(newangle))
mpipe.close()

Following code reads from the pipe and controls the servo. please refer to my servo repo for more info.

#include "servo.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
//#include <ncurses.h>
//#include <thread>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

const char *npipe = "/usr/share/nginx/www/live/pipe";

using namespace std;
int main () {
   char tmp[32];
   PCA9685 pwm;
   pwm.init(1,0x40);
   usleep(1000 * 100);
   printf ("Setting frequency..");
   pwm.setPWMFreq (61);
   usleep(1000 * 1000);

   while(true) {
      int fd = open(npipe, O_RDONLY) ;
      if ( fd < 0 ) {
         printf("Error opening pipe");
         return 0;
      }
      if( read(fd, tmp, sizeof(tmp)) > 0) { 
         printf("\n %d ", atoi(tmp));
      }
      int val = atoi(tmp);
      close(fd);
      if(val > 240 && val < 480) {
     pwm.setPWM(0,0,val);
      }  
      sleep(1);
   }
} 

Now modify the router to open port 80 to outside world. umm. Reach the live feed on your phone at http://IP/live/index.html To control servo use following http://IP/cgi-bin/plus.cgi http://IP/cgi-bin/minus.cgi

How to add motion detection to this? Maybe redirect the feed to opencv program that can read frame by frame and compute the diff. And if there is diff send an alert email?


Written on November 30, 2015