Live video stream from the Raspberry Pi using nginx and rtmp-module

There is currently no way to stream the raw h264 data into a HTML5 browser for live video streaming. The best option if to use a RTMP server that can repackage and distribute the video stream in flash. This sucks for iPhone and Android users but there is support for slightly delayed video for these platforms.

Raspberry Pi Server Essentials Book
Buy Raspberry Pi 2 Server Essentials.
Contains NEW information
about this article. 
I did everything as root and I over clocked my Pi using raspi-config to the medium setting.I also made sure I have the latest firmware(raspi-update) and packages(apt-get update) - Otherwise you might have stability issues. Over clocking helps in the compile time and lowers general CPU load.

You going to compile ffmpeg your self without any extra parameters (using rtmp-lib causes big CPU usage- don't use) (it takes 5 hours!)

Using the rtmp-module for nginx does not require the psips script. The rtmp-module handles all that internally. You should use psips if you want to stream direct like to VLC - But that has nothing to do with this article, sorry.

I also used the patched version of raspivid that you can find here (with some other stuff like ffmpeg)


We need to install nginx using apt-get and then remove it. This step is necessary to get the startup scripts and some other dependencies in place.

  sudo apt-get -y install nginx   
  sudo apt-get -y remove nginx   
  sudo apt-get clean   

Make sure that the /etc/nginx folder is empty. Make install won't overwrite existing files and this will cause issues with your installation.
Go to src folder where we will download and clone the files we need for compiling.

 cd /usr/scr  
 #clone the latest version of rtmp module for nginx  
 git clone git://github.com/arut/nginx-rtmp-module.git  
 #dowload nginx source tested with- 1.4.1  
 wget http://nginx.org/download/nginx-1.4.1.tar.gz  
 tar xzf nginx-1.4.1.tar.gz  
 cd nginx-1.4.1  

Now you need to install some other dependencies and build tools. If you already have these apt-get will either update them or ignore them.

 apt-get update  
 apt-get install -y curl build-essential libpcre3-dev libpcre++-dev zlib1g-dev libcurl4-openssl-dev libssl-dev  

This will configure the installer to work with Raspbian (Debian wheezy) and  include rtmp-module for video streaming.

 ./configure --prefix=/var/www \  
             --sbin-path=/usr/sbin/nginx \  
             --conf-path=/etc/nginx/nginx.conf \  
             --pid-path=/var/run/nginx.pid \  
             --error-log-path=/var/log/nginx/error.log \  
             --http-log-path=/var/log/nginx/access.log \  
             --with-http_ssl_module \  
             --without-http_proxy_module \  
             --add-module=/usr/src/nginx-rtmp-module \  

Create the www folder that will contain all the root files.


  sudo mkdir -p /var/www  

Make the binaries. About 10 minutes.


 make  

Install binaries to the correct location for raspbian (debian wheezy configuration)

 make install  

Now you can check if the correct version has been installed. The result should be: nginx version: nginx/1.4.1. Start nginx and point your browser to the Pi's ip address. You should see some default message.

#check if the correct version of nginx is installed
 nginx -v   
#start nginx and check if you get the default site
 service nginx start
#its all OK then stop it
 service nginx stop

You can look inside the /var/www directory and notice allot of files that were made. You store your html files in the HTML directory.

The default configuration needs to be changed to be used with RTMP streaming. edit the /etc/nginx/nginx.conf file and replace all the content with this. Then read over the settings to see if there is anything you want to enable or disable.

user root;
#Root is only OK if the server is not public. Otherwise you need to increase security on your own.
# user www-data;
 #use up to 4 processes if you expect allot of traffic. But this causes issues with rtmp /stat page and possibly pushing/pulling  
 #worker_processes 4;  
 worker_processes 1;

 events {  
   worker_connections 1024;  
 }
  
 http {  
      include /etc/nginx/mime.types;  
      default_type application/octet-stream;  
      sendfile on;  
      keepalive_timeout 65;  
      #if you want gzip enabled  
      #gzip on;  
      #gzip_disable "msie6";
  
 server {  
     listen    80;  
     server_name localhost;
  
     # sample handlers  
     #location /on_play {  
     #  if ($arg_pageUrl ~* localhost) {  
     #    return 201;  
     #  }  
     #  return 202;  
     #}  
     #location /on_publish {  
     #  return 201;  
     #}  
     #location /vod {  
     #  alias /var/myvideos;  
     #}  
     # rtmp stat  
     location /stat {  
       rtmp_stat all;  
       rtmp_stat_stylesheet stat.xsl;  
     }
  
     location /stat.xsl {  
       # you can move stat.xsl to a different location  
       root /usr/src/nginx-rtmp-module;  
     }
  
     # rtmp control  
     location /control {  
       rtmp_control all;  
     }  
     error_page  500 502 503 504 /50x.html;  
     location = /50x.html {  
       root  html;  
     }  
   }  
 }  
 rtmp {  
   server {  
     listen 1935; 
     #chunk_size 8192;
     ping 30s;  
     notify_method get;  
     application rtmp{  
       live on;

       # You can push this stream to an external rtmp server while accessible locally.
       # If you experience artefacts and delays on external server lower the bitrate.
       # There seems to be a bug. When watching local stream and pushing to remote, the remote
       # stream become really weird with random blocks and strange shadows.(consider 1 one for now)
       # push rtmp://ip-address-external-rtmp/app/stream;  

       # sample play/publish handlers  
       #on_play http://localhost:80/on_play;  
       #on_publish http://localhost:80/on_publish;  
       # sample recorder  
       #recorder rec1 {  
       #  record all;  
       #  record_interval 30s;  
       #  record_path /tmp;  
       #  record_unique on;  
       #}  
       # sample HLS  
       #hls on;  
       #hls_path /tmp/hls;  
       #hls_sync 100ms;

      #This will start/stop our ffmpeg script and camera stream (thanks #towolf)
      exec_static /root/rtmp-nginx.sh;
      exec_kill_signal term;
  
     }  
     # Video on demand  
     #application vod {  
     #  play /var/Videos;  
     #}  
     # Video on demand over HTTP  
     #application vod_http {  
     #  play http://localhost:80/vod/;  
     #}  
   }  
 }  

Thanks to the service scripts installed using apt-get you can start the new nginx server using

 sudo service nginx start  

Create an executable bash file in root (/root/rtmp-nginx.sh). This is the file that nginx will start on the rtmp-module begins. This has extra settings for no preview and matrix metering mode.

 #!/bin/bash  
 on_die () {  
   # kill all children  
   pkill -KILL -P $$  
 }  
 trap 'on_die' TERM  
 raspivid -n -mm matrix -w 1280 -h 720 -fps 25 -g 100 -t 0 -b 5000000 -o - \  
  | ffmpeg -y \  
    -f h264 \  
    -i - \  
    -c:v copy \  
    -map 0:0 \  
    -f flv \  
    -rtmp_buffer 100 \  
    -rtmp_live live \  
    rtmp://localhost/rtmp/live &  
 wait  

An alternative stand alone script using FIFO - For reference only- not useful with rtm-module exec

 #!/bin/bash  
 urllocal="rtmp://localhost/myapp/mystream"  
 fifo="live.fifo.h264"  
 rm -f "$fifo"  
 mkfifo "$fifo" 
 
 #this uses the patched version of raspivid with infinite time and -g option  
 raspivid \  
  -fps 25 -g 100 \  
  -t 0 -b 500000 -o "$fifo" & 
 
 ffmpeg -y \  
  -f h264 \  
  -i "$fifo" \  
  -c:v copy \  
  -map 0:0 \  
  -f flv "$urllocal"   

I decided to use strobe strobemediaplayback from osmf player because it gives near instant feed when watching within wifi on a browser that supports flash 10+ - I don't know why its faster than the others... but it is!

Links to other stuff you might want...

Tips:

Configuration for strobemediaplayback to disable buffering and let it stream as live as possible, ignoring missed packets and just getting on with it. You just got be careful with what size, fps and bit rate you stream at. If your network cant handle it you will get "slowmo" movements or lots or artefacts. good ffmpeg settings are (you can adjust bit rates as you like - these are in order of overall quality) :

  •  -w 854 -h 480 -b 4000000 (480p at 4mb/s - should run pretty well everywhere)
  •  -w 1280 -h 720 -b 5000000 (720p at 5mb/s - runs fine on wireless N, LAN and BT Infintiy)
  • -b 6000000 (1080p at 6mb/s - should really be used on LAN)


 var parameters = {  
         src: "rtmp://your-ip-here/myapplive/mystream",  
                     autoPlay: false,  
         controlBarAutoHide: false,  
         playButtonOverlay: true,  
         showVideoInfoOverlayOnStartUp: true,  
                     optimizeBuffering : false,  
                     initialBufferTime : 0.1,  
                     expandedBufferTime : 0.1,  
                     minContinuousPlayback : 0.1,  
         poster: "images/poster.png"  
       };  


Issues:

Flipping local stream will only synch right at the start. using psips or not. not sure what the issue is. When pushing RTMP to external crtmp-server from ffmpeg it works fine. Driving me nuts...

Consider donating to some of these authors. All credits to them. Thanks!

Comments