Achieving high frame rate with a Raspberry Pi camera system

When you read about using Raspberry Pi cameras as part of your home security system, most of the information you will find will point you in the direction of running motion which is the de-facto standard for doing video motion detection on Linux. There are also variants of motion such as MotionEye or motionEyeOS which provide a nicer UI on top of motion.

Motion requires some horsepower to handle the video processing to detect motion, and also to run the web server and other features. On the modest hardware on the Raspberry Pi, I was only able to reliably achieve 4-10 frames-per-second at 800×600, depending on the Raspberry Pi model in use.

Using this technique below, my camera system is now able to get the full resolution for each Raspberry Pi camera which is 1920×1080 at 30 frames per second.

The problem with using motion on the Raspberry Pi

After much experimentation and time trying to make it work, I found the motion solution is not that great in practice. I have spent countless hours writing scripts, web pages, and various hacks to build a robust 4 camera home security system using this setup.

The cameras suffered from low FPS, high load average, frequent lockups, and SD cards dying. This slow FPS is due to the high CPU needed by motion performing image processing on the low powered Pi. The high load average and SD card death is being caused by the high number of writes (images and video files) on the SD card.

Managing all the video files was a problem as well. Files from the multiple cameras need to be remotely viewable in one central location. The SD card fills up fast and old files need to be deleted to make room for new files.

There has to be a better way!

The Solution

The solution I found was to take as much of the processing off of the Raspberry Pis as possible. I wanted to get the devices to send video, and not write anything on the local SD card. The image processing needed to be centralized on a more powerful machine.

For your camera server, you could choose any NVR hardware or software which supports the RTSP standard for video streams.

In my case I had an old Mac Mini in the closet, and went on the hunt for software that would work on MacOS. After some research, I came across a software called SecuritySpy from Ben Software. This software provides so many capabilities that I was attempting to create myself and now I am a huge fan of it. For the purpose of this article I will go through how I set up SecuritySpy, but you can use any video recording software that you want.

SecuritySpy is a paid software and is totally worth the price for the features and support that you get.

Download, Install and set up SecuritySpy

SecuritySpy download page

Some of the features SecuritySpy provides:

– Live Video with FPS overlay
– Constant recording, or motion detection recording
– A robust interface for viewing recorded videos
– Web based interface for viewing on computer, phone, TV
– iOS client for live viewing on iPhone, iPad, AppleTV
– Automatic deletion of old video files (by age, or when the hard drive fills)
..and much more

Configure the Raspberry Pi camera to be a RTSP streaming server

Set up the Pi camera according to the camera setup guide. You need to run raspi-config and enable the camera module.

This technique uses the software raspivid and the VLC command line interface cvlc. raspivid should already be installed with your Raspbian install, but you will probably need to install VLC. We will also install screen which is needed for the auto-start:

sudo apt-get install vlc screen

Create a script to turn your Raspberry Pi into a RTSP streaming server. In the pi home directory /home/pi, create the file stream-rtsp.sh:

#!/bin/bash
raspivid -o - -t 0 -w 1920 -h 1080 -fps 30 -b 250000 | cvlc -vvv stream:///dev/stdin --sout '#rtp{access=udp,sdp=rtsp://:8554/stream}' :demux=h264

Tweak the settings to your liking. The -w width -h height -fps fps -b bitrate are good values to play with.

I sometimes run on a lower configuration to reduce network bandwidth:

#!/bin/bash
raspivid -o - -t 0 -w 1000 -h 576 -fps 20 -b 250000 | cvlc -vvv stream:///dev/stdin --sout '#rtp{access=udp,sdp=rtsp://:8554/stream}' :demux=h264

With this simple script, your Pi will be running as a RTSP server listening on both TCP and UDP. Remove access=udp to disable the UDP stream if you want. My suggestion is to leave both enabled, and see which one works best for you.

Make the script executable:

chmod +x stream-rtsp.sh

Test the script by running it manually:

./stream-rtsp.sh

Making the script run on startup

After you see it is working, set up the script to run automatically on startup. I have two examples of how to do this here. First is using a systemd startup script which is recommended. Second is inside of a screen session. You only need to choose one option.

Script startup Option 1 – systemd startup script

Create the file /etc/systemd/system/stream-rtsp.service

[Unit]
Description=auto start stream
After=multi-user.target

[Service]
Type=simple
ExecStart=/home/pi/stream-rtsp.sh
User=pi
WorkingDirectory=/home/pi
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then you can start, stop, or check on the service with:

sudo systemctl start stream-rtsp.service
sudo systemctl stop stream-rtsp.service
sudo systemctl status stream-rtsp.service

Script startup Option 2 – Using screen

Add this to the middle of your /etc/rc.local file (above exit 0):

# start streaming video
su - pi -c "/usr/bin/screen -dmS stream /home/pi/stream-rtsp.sh"

Configure SecuritySpy to connect to the camera

In SecuritySpy camera setup, add a new camera.

Enter the Raspberry Pi camera IP address. Select “Profile” “Manual configuration”, “Format” “RTSP TCP (video and audio)”, and down in “Request” enter “/stream”.

Apply Preferences, then the video should show up.

This technique also works for getting high resolution and high frame rate out of the new Raspberry Pi Zero W camera packs (infrared or standard)! At $45 they are a great way to add extra wireless cameras to your home security system.

27 Replies to “Achieving high frame rate with a Raspberry Pi camera system”

  1. This is great! I currently have MotionEye OS running on a Pi B in my garage, but I am baffled to why the FPS is terrible, even with Ethernet connectivity (as opposed to WiFi).

    I’ve actually seen that it might be possible to add a RTSP stream to Synology’s Surveillance Station as well, so I’m going to give that a go and see how that copes. I also own a PPC Mac Mini, and saw that SecuritySpy version 3.2.1 supports this, so I’ll give this a go too if the NAS doesn’t work as well.

    Looking forward to trying this out later!

      1. Hey Chris,

        I managed to get this working in Synology Surveillance Station 8.0.3-5159, but I needed to make a few tweaks.

        I started with Raspbian Lite (2017-04-10) and needed to install screen so that I could get the script to run on boot. Plus I needed to ensure I added the script in rc.local before the “exit 0” line (rather than at the end).

        Thanks for the guide! Pleased with the result.

        1. Use systemd to manage the service, not rc.local. this way you can ensure things start before or after other services (eg. network) and even make it auto restart if the service/script happens to die.. which is quite needed with security services.

  2. Dear Chris,
    thank you so much, it works on a PI 0 W.
    I’m playing the stream on a Windows PC using VLC… but there’s a huge lag (around 2 secs). Any idea to improve? Thank you!

    1. DaveT no I do not have audio set up yet. If we get cvlc to take audio input from the USB mic, it might be able to mix it in. I’ll give that a try. Try adding :input-slave=alsa://hw:0,0 to your cvlc

    1. DaveT I did play around with UV4L and like the website control panel it creates on the pi and the streaming to the browser is nice. I had trouble getting my setup working with UV4L but it does seem promising. It would probably have the benefit of running the Pi’s even cooler on the CPU. Basically I was trying to get a h264 RTSP stream out of it and off the top of my head I can’t remember what hurdle I kept hitting. If you figure anything out with regard to this, let me know!

  3. I am currently using Pikrellcam / nginx on the zero’s for the last year, it churns out mjpeg and can record the audio with the mjpeg… its super fast in browser but i cannot find the string for the stream to add to the windows server2012 running blueiris

    Hence landing here

    1. I did not go that route but that would be a fine solution. If you can move the motion detection off the pi you will get a much better FPS result on the video files. Also having the files being written on a faster drive would be a plus. The SD card on the Pi is not great with constant writes.

  4. Excellent work Chris,
    I am able to view the stream created using your method and script with my Samsung Tablet and only some stream viewing apps. For the benefit of anyone interested these include tinyCam Pro and Mango Player. This application of a Raspberry Pi and Camera should make for a cheap wildlife camera.

  5. This is awesome. Combined with VLC and a ZTE Mobley hotspot, I’m using this as a DIY carseat cam in my sedan. You just saved me at least $30,000 on a minivan, good sir!

  6. Why not simply run it from the crontab from user pi, with an entry like;

    @reboot /home/pi/stream_video.sh &

    Do a “crontab -e” and add the script to have it start at every reboot. You could also add a second script that checks every 1,2,3 minute(s) to see if the original script is still running and kick it back to life if it has failed for whatever reason.

    1. I have never seen that crontab trick. That looks very useful. Thanks for sharing it. I ended up going the systemd route which is handling the start/stop and restarting if it gets killed.

  7. Hi Chris, this worked brilliantly on my 2B, with both a 5mp and 8mp camera. Thanks! One small hiccup I’ve been trying to resolve… I get quite a lot of ‘noise’/’artefacts’ when there is significant motion. Upping the datarate seems to help, but the noise is often setting off my motion detection. Any thoughts on what this might be caused by? Thanks

    1. Maybe you can connect to the stream with VLC from a computer – connect to network – rtsp://10.10.10.10:8554/stream
      Then see if the same artifact/noise is happening with significant motion. That can rule in or out the video recording software as a culprit.
      If it is the Pi, then try tweaking more settings. Let me know if you figure out a better method.

      1. So, after a few hours, over a couple of days, of pissing around… I still can’t reproduce the problem I was originally having. In the process of trying to reproduce I stuff something and ended up re-imaging my RPi3! And I still can’t reproduce it… But, in case someone else reads this (I’d wanted to provide exact details) I was adjusting the time synchronisation settings within the VLC preferences and that appeared to resolve the problem. I’d been getting those ES_OUT_SET problems with the buffer appearing to run out – and the weird imaging would happen in the viewer after each resume.

  8. Also… Using this method, do you know if there is a way to force encoding in grayscale? That should help with overall bandwidth. Thanks again 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *