Trick #12: Support two cameras in Printoid Premium

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 PREMIUM, since the version 7.07.

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.

This tutorial assumes that the following facts are gathered:

  • You have a sufficient knowledge in Linux scripts and commands
  • You have already configured one camera and it’s working well in OctoPrint AND in Printoid
  • The second camera to be used is an USB webcam (in this tutorial, the two cameras are USB webcams)
  • Your Raspberry Pi is at least a Raspberry Pi 2 (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.

1/ Preparation of the second camera

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.

2/ Configure the new webcam daemon for the second camera

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‘ 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 (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.

2.1/ 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"

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 " -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

2.2/ 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:

# Start / stop streamer daemon

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

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


3/ Configure haproxy to make the second camera reachable on the port 80 too

Now we should configure haproxy in order 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.

        maxconn 4096
        user haproxy
        group haproxy
        log local0 debug

        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
        acl AuthOkay http_auth(L1)
        http-request auth realm octoprint if !AuthOkay

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

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

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

userlist L1
        group G1

        user YOUR_USERNAME insecure-password YOUR_PASSWORD groups G1

4/ Edit the iptable

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 --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 fourth point: OctoPrint GitHub)

5/ Edit the OctoPrint settings to match with the new configuration

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:

  stream: /webcam2/?action=stream

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

  - 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.


6/ Configure Printoid to use the second camera

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 🙂


7/ How Printoid handles the two camera feeds

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)

8/ More informations and special thanks

You can find the official tutorial on the Foosel’s Github here.




One thought on “Trick #12: Support two cameras in Printoid Premium

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s