How to simultaneously stream 3 streams from a raspberry pi camera

I am using a raspberry pi 4B with 4GB of ram.

I installed the latest version of Buster on my pi

I gave it a memory split of 128MB to GPU.

I followed this guide for installing Octoprint onto the pi:

I installed nginx as my reverse-proxy, I followed this guide to install nginx:
https://www.raspberrypi.org/documentation/remote-access/web-server/nginx.md

Here is my reverse-proxy file located in /etc/nginx/sites-enabled/3d-printer.conf, I deleted the default file located in /etc/nginx/sites-enabled:

server {

  # webcam port, optional.
  location /webcam {
    proxy_pass http://localhost:8080/;
  }

  location /rtspcam {
    proxy_pass http://localhost:8555/;
  }

  location /octoprint/ {
    proxy_pass http://localhost:5000/;
    proxy_set_header Host $http_host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Script-Name /octoprint;
    proxy_http_version 1.1;
    client_max_body_size 0;
  }

}

I did NOT install mjpg-streamer. The reason I did not was because the /dev/video0 device (my raspberry pi camera) once used by a process can not be accessed by another process.

I orignally installed mjpg-streamer and v4l2rtspserver. But these two would not play nice together so I had to find another solution to my camera.

I want my pi camera to stream mjpeg, snap-shots or jpeg and rtsp stream (so I can add it in my surveillance screen with the rest of my cameras)
So I needed three streams coming from one input source, my raspberry pi camera. How to do this?

My solution:
use ffserver to distribute the streams for me. This is how you get ffserver onto your raspberry pi 4B.

Download the ffmpeg 3.4.6 from here (ffserver comes with ffmpeg 3.4.6):
https://ffmpeg.org/download.html#release_3.4

Place the ffmpeg-3.4.6.tar.xz file into /usr/src

From now on, if you see a $ in front of a line it will mean you need to type the command in a command terminal window. Please do not type the '$' symbol with the command or the command will not work.

$cd /usr/src
$sudo tar -xvf ffmpeg-3.4.6.tar.xz
$cd /usr/src
$sudo git clone git://git.videolan.org/x264
$cd x264
$sudo ./configure --host=arm-unknown-linux-gnueabi --enable-static --disable-opencl
if you have a raspberry pi 3B or higher you can use the -j4 otherwise leave it off for raspberry pi 1 or 2
$sudo make -j4
on my raspberry pi 4B it took only 30 minutes to compile
$sudo make install
$cd /usr/src/ffmpeg-3.4.6

$sudo ./configure --arch=armel --target-os=linux --enable-gpl --enable-libx264 --enable-nonfree --enable-omx --enable-omx-rpi

$sudo make -j4
$sudo make install

NOTE we will use tmp2 as place to save our video, but it will NOT go on the SD card. The video will be save to MEMORY

$sudo mkdir /tmp2
$sudo nano /etc/fstab

add this to /etc/fstab:

tmpfs           /tmp2              tmpfs   defaults,noatime,mode=1777 0       0

mount tempfs in ram:
$sudo mount /tmp2

create a file with:
$sudo nano /etc/ffserver.conf
and paste this:

# ffserver configuration for an mjpeg stream and rtsp stream
# Adapted from
# https://gist.github.com/peterhellberg/ebfc72147c2009ee720aafe57ce9c141
#/etc/ffserver.conf
HTTPPort 8080
HTTPBindAddress 0.0.0.0
RTSPPort 8555
RTSPBindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 500000
CustomLog -
# Suppress that if you want to launch ffserver as a daemon.
#NoDaemon

<Feed camera.ffm>
   File /tmp2/camera.ffm
   FileMaxSize 5M
   ACL allow 127.0.0.1
   ACL allow 192.168.0.0 192.168.255.255
</Feed>

<Stream camera.sdp>
   Format rtp
   Feed camera.ffm
   VideoFrameRate 10
   Videosize 480x360
   noAudio
   ACL allow 127.0.0.1
   ACL allow 192.168.0.0 192.168.255.255
</Stream>

<Stream camera.mjpeg>
   Format mpjpeg
   Feed camera.ffm
   # Make sure frame rate and size
   # match those passed to ffmpeg
   VideoFrameRate 10
   Videosize 480x360
   VideoBitRate 4096
   VideoBufferSize 4096
   VideoQMin 5
   VideoQMax 51
   NoAudio
   Strict -1
   ACL allow 127.0.0.1
   ACL allow 192.168.0.0 192.168.255.255
</Stream>

<Stream static-camera.jpg>
   Format jpeg
   Feed camera.ffm
   VideoFrameRate 2
   VideoIntraOnly
   VideoSize 480x360
   NoAudio
   NoDefaults
   Strict -1
   ACL allow 127.0.0.1
   ACL allow 192.168.0.0 192.168.255.255
</Stream>

<Stream stat.html>
   Format status
   ACL allow localhost
   ACL allow 192.168.0.0 192.168.255.255
</Stream>

<Redirect index.html>
   URL http://www.ffmpeg.org/
</Redirect>

now let's test to see if ffserver will work:
$ffserver -d -f /etc/ffserver.conf

now open another terminal window:

$ffmpeg -input_format mjpeg -video_size 480x360 -framerate 10 -input_format h264 -i /dev/video0 -c:v copy http://localhost:8080/camera.ffm

now goto Chromium and put these two addresses in the address bar:
http://localhost:8080/camera.mjpeg
new Chromium tab:
http://localhost:8080/static-camera.jpg

if you see the camera output then everything is running nicely.
So let's set it up to start automatically:
$sudo nano /etc/systemd/system/ffserver.service
paste this in:

[Unit]
Description=FFMPEG streaming server (ffserver) service

[Service]
User=pi
ExecStart=/usr/local/bin/ffserver -f /etc/ffserver.conf

[Install]
WantedBy=multi-user.target

$sudo nano /etc/systemd/system/ffmpeg.service
paste this in:

[Unit]
Description=FFMPEG transcoder service
After=ffserver.service

[Service]
User=pi
# -video_size and -framerate should match the settings in ffserver.conf
ExecStart=/usr/local/bin/ffmpeg -input_format mjpeg -video_size 480x360 -framerate 10 -input_format h264 -i /dev/video0 -c:v copy -nostats -loglevel panic http://localhost:8080/camera.ffm

[Install]
WantedBy=multi-user.target

Then reload systemd and start our new services to ensure they start up properly:

$sudo systemctl --system daemon-reload
$sudo systemctl start ffserver.service
$sudo systemctl start ffmpeg.service

If that goes well, then we can finally configure systemd to run them at startup:

$sudo systemctl enable ffserver.service
$sudo systemctl enable ffmpeg.service

Updating OctoPrint configuration:
Navigate to the OctoPrint settings dialog. In the Webcam & Timelapse section you want these settings:

Stream URL: http://localhost/webcam/camera.mjpeg
Snapshot URL: http://localhost/webcam/static-camera.jpg
RTSP URL: rtsp://localhost:8555/camera.sdp

If you would like to control all the stream through Octoprint:
$cd /home/pi/scripts
$nano webcamStreams
past this in:

#!/bin/bash
# Start / stop webcam streamer daemons

case "$1" in
    start)
        sudo service ffserver start >/dev/null 2>&1 &
        sudo service ffmpeg start >/dev/null 2>&1 &
        echo "$0: started"
        ;;
    stop)
        sudo service ffmpeg stop >/dev/null 2>&1 &
        sudo service ffserver stop >/dev/null 2>&1 &
        echo "$0: stopped"
        ;;
    *)
        echo "Usage: $0 {start|stop}" >&2
        ;;
esac

$cd /home/pi/.octoprint
$nano config.yaml
paste this in:

system:
  actions:
  - action: streamon
    command: /home/pi/scripts/webcamStreams start
    confirm: false
    name: Start video streams
  - action: streamoff
    command: sudo /home/pi/scripts/webcamStreams stop
    confirm: false
    name: Stop video streams

$sudo reboot

when the system reboots you will have the following:
on http://localhost, you will find the octoprint UI
on http://localhost/webcam/camera.mjpeg , you will find the Stream URL
on http://localhost/webcam/static-camera.jpg , you will find the Snapshot URL
on rtsp://localhost:8555/camera.sdp, you will find the RTSP URL
In Octorprint if you go to the top menu under the Power button, you will see two entries "Turn off the video streams" and "Turn on the video streams". These selection will give you control over all three streams. So they are all on or they are all off. On boot of your system, all three streams will be ON.

I noticed I am only using 19% CPU and my tempurature on my pi is at 44 degree C (I have a heat sink and active fan on the pi 4B)

I hope this helps someone. If anyone notices errors please point them out. But my setup is working at this time.

Happy and safe 3d printing!

1 Like

Since you've added nginx I don't know if it's necessary to visit the haproxy configuration on there to adjust anything but perhaps not. As long as they're not fighting over ports, it's probably alright.

1 Like

Great write up. I wonder why @guysoft doesn't use ffmpegserver in lieu of mjpgstreamer in octopi. My best guess would be because of some issue with camera support maybe?

Which codebase is that?
Welcome to contribute info to this issue:

@guysoft, looks like it's compiled on Buster.

yes, ffmpeg is compiled on the raspberry pi but BUSTER OS is installed from the raspberry pi website

1 Like

yes, FFMPEG was compiled on BUSTER

Can someone give me a straightforward guide how to add this to OctoPi?