Trick #12: Support two cameras in Printoid Pro & Premium (tutorial for Raspbian)

Printoid is the only app to brings you the support of not only one but two video streamings!

This feature is only available in Printoid PRO and PREMIUM.

This tutorial is for those who have installed Raspbian on a Raspberry Pi, then OctoPrint on it, following this tutorial:

Setting up OctoPrint on a Raspberry Pi running Raspbian

If you have installed OctoPi please follow this one.

1. INTRODUCTION

Having two camera feeds is a must have for those who are accustomed to leave their 3D printers printing alone, all day and all night long. That’s also a good way to make HD timelapses with a camera, and keep an access to the direct streaming in a lower resolution.

2. PREREQUISITES

This tutorial assumes that the following facts are gathered:

  • You have a sufficient knowledge in Linux scripts and commands
  • Your Raspberry Pi is at least a Raspberry Pi 3B (for the CPU consumption)
  • Your Raspberry Pi has a great network coverage and the available bandwidth is sufficient for a second camera stream
  • You have (eventually) an USB powered hub for the second camera, or at least a 2.5A power supply.

Important note 1: this tutorial is based on a manual installation and configuration of OctoPrint on a Raspbian installation on a Raspberry Pi. That means: not for OctoPi, not for OctoPrint on Windows, not for OctoPrint on Linux, not for OctoPrint on Mac.

Important note 2: this tutorial is based on the use of 2 USB webcams (Logitech C270). You can follow it if you have different USB webcams, or 1 USB webcam and the official Raspberry Pi Camera, but you may have to adjust the scripts by yourself.

3. PREPARATION

Before adding the second camera, please be sure you have followed first these tutorials:

If you don’t follow them, please note that some of the following instructions will break your actual configuration if you don’t adjust them ; or you will probably been a bit lost when I’ll ask you to edit the haproxy.cfg file or the webcam daemon scripts.

Shutdown your Raspberry Pi and plug the two cameras on. Then, start your Raspberry Pi and wait for the boot completion. If everything is working well (OctoPrint is accessible and the first camera is still accessible, so you can go to the next step. If not, please get a better power supply (at least 2.5A) or please plug the USB cameras on a USB powered hub).

You should also check in /dev/ if you properly see both of the video0 and video1 devices (when connected to the Raspberry Pi over SSH, using a terminal) :

ls -l /dev/ | grep video

You should see at least these two lines:

crw-rw----+ 1 root video 81, 0 Mar 4 00:17 video0
crw-rw----+ 1 root video 81, 1 Mar 4 00:17 video1

4. MJPEG-SREAMER CONFIGURATION

If you have followed the official OctoPrint’s tutorial to configure your first camera for OctoPrint (or if you have installed OctoPi), then you should be in the following configuration:

  • You have a script called ‘webcamDaemon‘ in /home/pi/scripts/ to start the mjpg streaming server
  • You have a script called ‘webcam‘ in /home/pi/scripts/ to start and stop the webcam daemon
  • You have installed and configured haproxy (/etc/haproxy/haproxy.cfg) to make your streaming accessible on the port 80 (OctoPrint as well) and accessible with the suffix /webcam/

I will use the same script names and location in the following instructions.

Please make a copy using the command ‘cp’ of the 3 files (webcamDaemon, webcam and haproxy.cfg). If ever something goes wrong, you’ll be able to restore your previous configuration easily:

cp ~/scripts/webcamDaemon ~/scripts/webcamDaemonSAVE
cp ~/scripts/webcam ~/scripts/webcamSAVE
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfgSAVE

Create another webcam daemon for the second camera

Make another copy of the webcamDaemon script and rename it to webcamDaemon2. Then rename the webcamDaemon script to webcamDaemon1.

Then, we will edit the file webcamDaemon2 as follow:

Edit the camera options to target the second camera (/dev/video1). It’s also the good time do adjust the resolution and the framerate, but it’s not mandatory.

camera_usb_options="-d /dev/video1 -r 640x480 -f 5"

Comment the octopi.txt section so it doesn’t pull the same settings as your first camera:

#if [ -e "/boot/octopi.txt" ]; then
#    source "/boot/octopi.txt"
#fi

Edit the mjpg_streamer command, providing the port 8081 (we want to let the first camera streaming on the port 8080, but the second one on the port 8081)

./mjpg_streamer -o "output_http.so -w ./www -p 8081" -i "$input"

Set the keep-alive to check /dev/video1 instead of /dev/video0:

# keep mjpg streamer running if some camera1 is attached
while true; do
    if [ -e "/dev/video1" ] && { [ "$camera1" = "auto" ] || [ "$camera1" = "usb" ] ; }; then

Save the changes. If you have properly understood:

  • webcamDaemon1 will start the stream for the first camera on the port 8080
  • webcamDaemon2 will start the stream for the second camera on the port 8081

Adjust the webcam script to start the first or the second camera

Replace the content of the /home/pi/scripts/webcam script with the following:

#!/bin/bash
# Start / stop streamer daemon

case "$1" in
    start)
        case "$2" in
            1)
                /home/pi/scripts/webcamDaemon1 $3 >/dev/null 2>&1 &
                ;;
            2)
                /home/pi/scripts/webcamDaemon2 $3 >/dev/null 2>&1 &
                ;;
            *)
                echo "Usage: $0 {start|stop} {1|2|all} {low|high}"
                ;;
        esac
        echo "$0: cam_$2 started with quality $3"
        ;;
    stop)
        case "$2" in
            1)
                pkill -x webcamDaemon1
                ;;
            2)
                pkill -x webcamDaemon2
                ;;
            all)
                pkill -x webcamDaemon1
                pkill -x webcamDaemon2
                pkill -x mjpg_streamer
                ;;
        esac
        echo "$0: cam $2 stopped"
        ;;
    *)
        echo "Usage: $0 {start|stop} {1|2|all} {low|high}" >&2
        ;;
esac

This script works like:

  • Start the first camera in a low definition: ./webcam start 1 low
  • Start the first camera in a high definition: ./webcam start 1 high
  • Start the second camera in a low definition: ./webcam start 2 low
  • Start the second camera in a high definition: ./webcam start 2 high
  • Stop the first camera: ./webcam stop 1
  • Stop the second camera: ./webcam stop 2
  • Stop the both cameras: ./webcam stop all

5. HAPROXY CONFIGURATION

You have now to onfigure haproxy to make the second camera reachable on the port 80 too. So you have to:

  • Give a suffix to the second camera streaming
  • Make it accessible on the port 80 too

If you have properly followed the tutorials exposed in the step 1, then you will easily understand the new haproxy configuration. Simply edit /etc/haproxy/haproxy.cfg to match with the following.

The changes are highlighted in green. please note that I have expressly renamed the suffix /webcam/ to /webcam1/ in order to stay consistent with the new path for the second camera. That means that you will be not able to access anymore to your streaming by using the link http://my_ip_address/webcam/?action=stream but rather by using the new link http://my_ip_address/webcam1/?action=stream

Also don’t forget to replace your basic authentication username and password (hightligthed in red) with your own values. I advise you to edit the file step by step with the changes instead of copy-past the whole script.

Important note: Please take care to the haproxy.cfg file indentation. Do not use tabulations, please use spaces instead.

global
        maxconn 4096
        user haproxy
        group haproxy
        daemon
        log 127.0.0.1 local0 debug

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        retries 3
        option redispatch
        option http-server-close
        option forwardfor
        maxconn 2000
        timeout connect 5s
        timeout client  15min
        timeout server  15min

frontend public
        bind *:80
        use_backend webcam1 if { path_beg /webcam1/ }
        use_backend webcam2 if { path_beg /webcam2/ }
        use_backend octoprint_socket if { path_beg /sockjs/ }
        default_backend octoprint

backend octoprint
        reqrep ^([^\ :]*)\ /(.*)     \1\ /\2
        server octoprint1 127.0.0.1:5000
        acl AuthOkay http_auth(L1)
        http-request auth realm octoprint if !AuthOkay

backend octoprint_socket
        reqrep ^([^\ :]*)\ /(.*)     \1\ /\2
        server octoprint1 127.0.0.1:5000

backend webcam1
        reqrep ^([^\ :]*)\ /webcam1/(.*)     \1\ /\2
        server webcam1  127.0.0.1:8080

backend webcam2
        reqrep ^([^\ :]*)\ /webcam2/(.*)     \1\ /\2
        server webcam2  127.0.0.1:8081

userlist L1
        group G1

        user YOUR_USERNAME insecure-password YOUR_PASSWORD groups G1

6. UPDATE THE IP-TABLE

Mjpegstreamer does not allow to bind to a specific interface to limit the accessibility to localhost only.

If you want your octoprint instance to be reachable from the internet you need to block access to port 8081 from all sources except localhost if you don’t want the whole world to see your webcam image.

To do this simply add iptables rules like this:

sudo /sbin/iptables -A INPUT -p tcp -i wlan0 ! -s 127.0.0.1 --dport 8081 -j DROP    # for ipv4
sudo /sbin/ip6tables -A INPUT -p tcp -i wlan0 ! -s ::1 --dport 8081 -j DROP         # for ipv6

Replace the interface with eth0, if you happen to use ethernet.

To make them persistent, they need to be saved. In order to be restored at boot time, the easiest way is to install iptables-persist:

sudo apt-get install iptables-persistent

The only thing left to do now, is save the rules you have added:

sudo /sbin/ip6tables-save > /etc/iptables/rules.v6
sudo /sbin/iptables-save > /etc/iptables/rules.v4

If these two last commands failed, then please send the command su before in order to get the privileges.

(source for this 6th point: OctoPrint GitHub)

7. CONFIGURE OCTOPRINT

OctoPrint is only able to display one camera feed. So, you need to take you choice now… would you make your first camera as default, or the second one? You choose! But in Printoid, no worries! You will be able to define and display the both camera feeds!

Edit the file ~/.octoprint/config.yaml as follows:

In the webcam section, please edit the fields snapshot and stream to match with your selected camera:

webcam:
  snapshot: http://127.0.0.1:8081/?action=snapshot
  stream: /webcam2/?action=stream

In the system/action section, you can add if you want the commands to start/stop the two cameras:

system:
  actions:
  - action: stream1onlow
    command: /home/pi/scripts/webcam start 1 low
    confirm: false
    name: Start camera 1 LQ
  - action: stream1onhigh
    command: /home/pi/scripts/webcam start 1 high
    confirm: false
    name: Start camera 1 HQ
  - action: stream1off
    command: /home/pi/scripts/webcam stop 1
    confirm: false
    name: Stop camera 1
  - action: stream2onlow
    command: /home/pi/scripts/webcam start 2 low
    confirm: false
    name: Start camera 2 LQ
  - action: stream2onhigh
    command: /home/pi/scripts/webcam start 2 high
    confirm: false
    name: Start camera 2 HQ
  - action: stream2off
    command: /home/pi/scripts/webcam stop 2
    confirm: false
    name: Stop camera 2
  - action: streamoff
    command: /home/pi/scripts/webcam stop all
    confirm: false
    name: Stop cameras
  - action: superlighton
    command: /home/pi/scripts/super_light_on
    confirm: false
    name: Switch super light ON

Take care about the file indent. A wrong indent and your OctoPrint server will failed to boot 😉

Save the changes, and restart your Raspberry Pi to take all the modifications into account.

8. CONFIGURE PRINTOID

Open the Printoid’s settings and go to the Video streaming settings. Scroll down until you find the parameters for the second camera:

You will be able to define the new streaming and snapshot URLs for your second camera, and to customize its rotation and flip options.

Don’t forget to edit the first camera URLs if you have renamed the /webcam/ suffix to /webcam1/ 😉

In the example of the screenshot above, I’ve defined the /webcam1/ path as my second camera for personal reasons 🙂

9. EXAMPLE IN PRINTOID

Here you are! Everything is configured and should work well right now 🙂 Here are some screenshots to present you how Printoid handles and displays the 2 camera feeds in its interface.

(The streaming panel in portrait mode)

(The streaming panel in landscape mode)

(The streaming by overlay (floating button) in portrait mode)

(The right panel in portrait mode, first camera selected)

(The right panel in portrait mode, second camera selected)

(The launcher widget in portrait mode, one widget per camera)

 

10. FILES

Here is a example of the configuration of one of my Raspberry Pi & OctoPrint installation, using 2 cameras.

  • This example uses 2 USB webcams (Logitech C270)
  • This example is based on an installation of Raspbian + OctoPrint (and not OctoPi – but it is still valable for OctoPi)

You have to put the files webcam, webcamDaemon1, webcamDaemon2 in ~/scripts/.

You have to edit the ~/.octoprint/config.yaml file to add the lines from the config.yaml file

You have to edit the /etc/haproxy/haproxy.cfg file according to the haproxy.cfg file.

https://nofile.io/f/xE0qGVZQkjb/OctoPrint+2cam.zip

11. OCTOPRINT PLUGIN

There are OctoPrint plugins to see both cameras at the same time.

Both plugins are working well with the solution of this tutorial.

 

12. SPECIAL THANKS

You can find the official tutorial on the Foosel’s Github here. Thanks to Gina for her amazing work!


7 thoughts on “Trick #12: Support two cameras in Printoid Pro & Premium (tutorial for Raspbian)

    1. Hello Jonas,
      This tutorial works fine, a lot of people have followed it with success.
      May you’ve to adjust the scripts if ever you have 1 pi cam + 1 USB cam. Otherwise may you’ve missed something. I can’t provide full scripts (mine are very specific to my own configuration) but the piece of scripts in this tutorial are sufficient to make it work 🙂
      Anthony

      Like

  1. Hi Anthony,
    I don’t see webcamDaemon (does not exist). I am currently use version 0.15 octopi, and 1.3.8 octoprint.

    Like

    1. Hello,
      May you can contact Gina on the OctoPrint’s github, to know where mjpeg streamer is configured and started. I don’t use Octopi

      Like

Leave a comment