Anton Sarukhanov

Full-Stack Developer

Livestreaming with a Raspberry Pi

Broadcast video privately, cheaply, and without ads.

These are my notes on broadcasting a USB camera to a webpage. A Raspberry Pi streams from the camera, and a server running nginx distributes the stream to many viewers at once.

Server setup🔗

These instructions assume you are using Debian, but should work on just about any Linux. While the Raspberry Pi can be on a private network, this server needs a public IP address to be accessible from the internet.

Note: Streaming video can use a lot of bandwidth. Do the math to ensure adequate capacity and avoid billing surprises.

nginx🔗

Build nginx with the RTMP module. Install and configure it, using the config below as an example.

Note: If ./configure complains about missing zlib, install zlib1g-dev.

worker_processes  1;
error_log logs/error.log debug;

events {
  worker_connections  1024;
}


http {
  include mime.types;
  default_type application/octet-stream;
  sendfile on;
  keepalive_timeout 65;

  server {
    listen 80;
    server_name streamer.example.com;

    # Uncomment if you have an SSL cert.
    # listen     443 ssl;
    # ssl_certificate /etc/ssl/certs/streamer.example.com.crt;
    # ssl_certificate_key /etc/ssl/private/streamer.example.com.key;

    # Configure HLS playback
    location /hls {
      add_header Cache-Control no-cache;

      # CORS header (allow embedding on other domains)
      add_header 'Access-Control-Allow-Origin' '*' always;

      # MIME types for HLS playlist and video files
      types {
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
      }

      # See hls_path below.
      root /tmp;
    }

  }

}

rtmp {
  server {
    listen 1935;
    ping 30s;
    notify_method get;
    application video {
      live on;           # Enable live streaming
      hls on;            # Enable HLS output
      hls_path /tmp/hls; # Where to write HLS files
    }
  }
}

See the nginx-rtmp-module wiki for details on these settings.

Raspberry Pi Setup🔗

Note: The original Raspberry Pi lacks hardware acceleration for video transcoding, making it unsuitable for this project. I used a Raspberry Pi 2.

Install Raspbian on your Raspberry Pi. It will need a network connection (eg. WiFi) to access the server.

Plug in your camera, and make sure it is detected.

ls /dev/video*
/dev/video0

You will need avconv, a fork of ffmpeg.

apt update
apt install avconv

Finally, you can start the stream. These settings worked well for me.

avconv
    -f video4linux2   \  # Input format
    -i /dev/video0    \  # Path to your webcam.
    -c:v libx264      \  # Use H.264 encoding.
    -pix_fmt yuv420p  \  # Some browsers (eg. Safari) need this.
    -an               \  # No audio (I don't need it).
    -f flv            \  # Output format
    rtmp://streamer.example.com/video/example-stream  # see below
  • video corresponds with the nginx rtmp application name.
  • example-stream will be the name of your stream, change as desired.

Set up the viewer🔗

Using hls.js for cross-browser HLS support, create a page for viewing the video.

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="live-stream"></video>
<script>
  if(Hls.isSupported()) {
    var source_url = 'http://streamer.example.com/hls/example-stream';
    var video_element = document.getElementById('live-stream');
    var hls = new Hls();
    hls.loadSource(source_url);
    hls.attachMedia(video_element);
    hls.on(Hls.Events.MANIFEST_PARSED, function() {
      video.play();
    });
  }
</script>

Live demo🔗

Here's a live stream using this setup.