Create 2×2 RTSP Camera Layout to Display 4 RTSP Cameras in Screenly on Raspberry Pi 3

Overview

Recently, I came across a nice piece of software for the Raspberry Pi 3 called Screenly OSE (Open Source Edition). The software is pretty easy to install and setup if you have NOOBS installed on a micro SD card. There are currently 3 types of media Screenly supports out of the box:

  • Videos
  • Images
  • Web-pages

Now, you’re probably looking at that list and noticing there isn’t anything stating it supports RTSP, but you would be wrong. In fact, Screenly does support RTSP streams natively. It’s pretty easy to setup, just put in the RTSP address just like you would a normal web page address and it will display the stream on a single slide!

Screenly Will Not Display More Than 1 RTSP Stream Natively

Herein lies the problem I encountered. What if you have several cameras and want to see more than one on a single slide in Screenly? Well, I ended up solving this issue by setting up a few different things with FFMPEG and FFSERVER on Ubuntu 16.0.4 and the results are nothing short of impressive.

How I Displayed 4 RTSP Cameras in Screenly

2x2 RTSP Streams Screenly
2×2 RTSP Camera Streams – Screenly – Screenshot

Requirements

  1. Raspberry Pi 3 Running Screenly OSE
  2. Physical PC or Virtual PC Running Ubuntu Server 16.04

Once you have completed the requirement, you can move on to the next step. Please note, my suggestions for RAM and CPU are what I have found to work for my environment, you may need more or less depending on yours.

Setting Up The Server

Now that you have your Ubuntu server up and running, open up a terminal and SSH into the machine to complete the next steps on the server.

  1. Update the server
    sudo apt update
  2. Install FFMPEG
    sudo apt install ffmpeg

    or
    Install the latest version from:
    http://ubuntuhandbook.org/index.php/2017/10/ffmpeg-3-4-released-install-ubuntu-16-04/

  3. Reboot the server for good measure
    sudo reboot
  4. After the reboot, let’s SSH back in and check out the version of FFMPEG.
    ffmpeg -version

    It should look something like: ffmpeg version 3.4-1~16.04.york0 Copyright (c) 2000-2017

  5. Lets check that ffserver is working (It’s installed as part of FFMPEG).
    ffserver -version

    The result should look basically the same as in step 4

Create and Configure the Streams

Now that we have both FFMPEG and FFSERVER installed and working, lets create 4 streams to accept the RTSP camera streams.

  1. SSH into the server
  2. Edit the FFSERVER config
    sudo -e /etc/ffserver.conf
  3. You should now see the sample config file that comes pre-installed. There are a few examples of different types of streams but for this example we will create our own and comment out the example streams by putting a # symbol in front of them.Alternatively, you can download my working example and copy and paste into your ffserver .config
  4. Looking at the ffserver.conf file, you should notice it looks similar to xml or html tags. The important thing to note here is there are two things needed to make this all work. First you need a a “Feed” and secondly you need a “Stream” for the feed to display. In other words, each <Feed> must have a matching <Stream>.
  5. Below is an example feed and stream (not Field & Stream haha!)  which is also in my attached ffserver.config file:
    <Feed shop.ffm>
     File /tmp/shop.ffm
     FileMaxSize 1G
     ACL allow localhost
     ACL allow 10.168.0.0 10.168.255.255
    </Feed>
    
    <Stream shop.mjpg>
    Feed shop.ffm
    Format mpjpeg
    VideoCodec mjpeg
    VideoSize 960x540
    VideoFrameRate 15
    VideoBitRate 4096
    VideoBufferSize 4096
    NoAudio
    VideoIntraOnly
    Strict -1
    </Stream>

At this point, should have the basics needed to customize your streams. In my example config file, I have the VideoSize variable set to 960×540 (widescreen format) since it will be displayed on one quarter of my screenly screen which is 1920×1080. You could also use 1920×1080 or 1280×720 but that’s what I chose and it should be a good starting point. Obviously, if you camera is not HD, you will need to adjust the VideoSize to fit your camera resolution.

After your done with your changes, save the ffserver.conf file so you can get back to terminal.

Testing The Newly Created Streams

Open up a 2nd terminal window and connect to the server to use for testing ffserver

  1. Start ffserver in the new terminal window
    ffserver -d -f /etc/ffserver.conf

    The result should end with something like “FFServer Started”.

Now we can test we can test transcoding one your RTSP cameras in terminal using ffmpeg. Just type the following into terminal (being sure to replace with your RTSP camera ip address and credentials) and the appropriate “name.ffm” if you modified the feed and stream names.

ffmpeg -i rtsp://admin:admin@10.148.1.6:554/ http://10.148.1.11:8090/shop.ffm

You should see a bunch of information about your RTSP camera displayed and if it’s working, something like the screenshot below:

RTSP Stream FFMPEG

If that worked, great! If you see any errors such as “Buffer Underflow”, you may need to tweak the VideoBitRate and VideoBufferSize in your ffserver.conf.

While the stream is still active in terminal, open up a web browser and point it to your ffserver ip address to view the stats page and access the stream. In my case it’s: http://10.148.1.11:8090/stat.html

Alternatively, you could go directly to the stream: http://10.148.1.11:8090/shop.mjpg

You should be able to see your camera streaming nicely in the browser now. If it’s working then let’s stop ffserver by hitting “CTRL + C” on your keyboard.

Hopefully that worked, if not, try connecting to your camera with VLC to be sure you can connect.

If that did work, I suggest you test each camera the same way, just make sure ffserver stays running in the other terminal windows or the ffmpeg command will fail.

Set It and Forget It – Automating The Feeds

In this section, we will be setting up some automation to start ffserver and the camera feeds.

First lets make the script to start ffserver and the cameras. Be sure to replace the ip addresses and login credentials for the RTSP cameras as well ad the IP address/feed for your Ubuntu Server.

  1. Create the file to hold the script
    sudo nano /etc/init.d/cams
  2. Paste in the following code
    #!/bin/bash
    ### BEGIN INIT INFO
    # Provides: ffmpeg
    # Required-Start:
    # Required-Stop:
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description:
    # Displays camera feeds for monitoring
    # Description:
    ### END INIT INFO
    
    # Camera Feeds
    ff_server="screen -dmS ff_server sh -c 'ffserver -d -f /etc/ffserver.conf'";
    top_left="screen -dmS top_left sh -c 'ffmpeg -i rtsp://admin:admin@10.148.1.6:554/live0/h264/ http://10.148.1.11:8090/front-porch.ffm'";
    top_right="screen -dmS top_right sh -c 'ffmpeg -i rtsp://admin:admin@10.148.1.5:554/live0/h264/ http://10.148.1.11:8090/shop.ffm'";
    bottom_left="screen -dmS bottom_left sh -c 'ffmpeg -i rtsp://admin:admin@10.148.1.4:554/live0/h264/ http://10.148.1.11:8090/parking.ffm'";
    bottom_right="screen -dmS bottom_right sh -c 'ffmpeg -i rtsp://admin:admin@10.148.1.2:554/live0/h264/ http://10.148.1.11:8090/garage.ffm'";
    
    # Camera Feed Names
    #(variable names from above, separated by a space)
    camera_feeds=(top_left top_right bottom_left bottom_right)
    camera_service=(ff_server top_left top_right bottom_left bottom_right)
    #---- There should be no need to edit anything below this line ----
    
    # Start displaying camera feeds
    case "$1" in
    start)
    for i in "${camera_service[@]}"
    do
    eval eval '$'$i
    done
    echo "Camera Display Started"
    ;;
    
    # Stop displaying camera feeds
    stop)
    killall ffmpeg
    killall ffserver
    echo "Camera Display Ended"
    ;;
    
    # Restart all camera feeds
    repair)
    for i in "${camera_feeds[@]}"
    do
    eval eval '$'$i
    echo "$i is now running"
    done
    ;;
    
    *)
    echo "Usage: /etc/init.d/cams {start|stop|repair}"
    exit 1
    
    ;;
    esac
    
    
  3. Save the file and back in terminal lets make the file executable
    sudo chmod 755 /etc/init.d/cams
  4. Lets test out the sript. The script usage is as follows:
    start ffserver and the streams:

    sudo /etc/init.d/cams start

    restart the streams (not ffserver):

    sudo /etc/init.d/cams repair

    stop ffserver and streams:

    sudo /etc/init.d/cams stop
  5. Now, lets setup a cron job to start ffserver and streams at startup
    sudo crontab -e

    paste the following at the end

    @reboot /etc/init.d/cams start
  6. Still in crontab, lets add a step to restart the streams every five minutes since they can get hosed up after running for a while. Add the following after your last line:
    */5 * * * * /etc/init.d/cams repair
  7. And one last thing to add after that to reboot the server every day at 5am
    0 5 * * * sudo reboot

That should do it for the the startup and repair script. Go ahead and reboot and after its up and running, visit the stats page at http://yourserverIP:8090/stat.html

Then click on each of the streams to verify they are all working. Next we move on to the part that puts this all together.

Display The Feeds 2×2 For Screenly Consumption

This next part is pretty simple and it’s all done on your normal PC or Mac. We are creating a single index.html file to house all 4 camera streams. Now, for this part, you are going to need a web server to make the file we create accessible to your Screenly device. If you don’t have a web server, here’s a tutorial to setup a web server on Ubuntu.

Using Notepad or another text editor, create a new file and paste the following code in it and save it to your desktop as index.html or whatever.html. Be sure to modify the img src urls to match the camera streams from your ffserver stat.html page:

<style type="text/css">
body {
padding:0;
margin:0;
}

@media only screen and (min-width:1600px){

.flexcontainer {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}

img {
max-width: 100%;
max-height: 100%;
}

}

.smallitem {
-webkit-flex: 1 0 0;
flex: 1 0 0;
}

img {
width: 100%;
max-height: 100%;
}
</style>
<html>
<body>
<div class="flexcontainer">
<div class="smallitem"><img src="http://10.148.1.11:8090/frontporch.mjpg"></div>
<div class="smallitem"><img src="http://10.148.1.11:8090/parking.mjpg"></div>
</div>
<div class="flexcontainer">
<div class="smallitem"><img src="http://10.148.1.11:8090/garage.mjpg"></div>
<div class="smallitem"><img src="http://10.148.1.11:8090/shop.mjpg"></div>
</div>
</body>
</html>

That’s pretty much it, just put that file on a web server that’s accessible to your Screenly device and you should be able to view 4 RTSP cameras in a nice 2×2 widescreen layout.

Leave a Comment