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:
- Making OctoPrint accessible over the Internet (if you want to see your two camera feeds over the Internet)
- Creating commands to start the streaming with a low or a high quality (this is mandatory to adjust the Raspberry Pi CPU consumption if needed)
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.
11. OCTOPRINT PLUGIN |
There are OctoPrint plugins to see both cameras at the same time.
- MultiCam plugin from Michael Morris : This plugin allows you to show both streams in the “Control” tab. You have only one stream at the same time, but a button allows you to switch between your cameras.
- MultiCamView from Jneilliii : This plugin creates a new tab to see both streamings 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!
Something is wrong, the second camera is not initializing. Can you dispense your scripts?
LikeLike
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
LikeLike
Hi Anthony,
I don’t see webcamDaemon (does not exist). I am currently use version 0.15 octopi, and 1.3.8 octoprint.
LikeLike
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
LikeLike
Hi sir. I installed octoPrint from the link https://community.octoprint.org/t/setting-up-octoprint-on-a-raspberry-pi-running-raspbian-or-raspberry-pi-os/2337 compiled video , according to your instructions, the video does not start for me. Maybe I’m not running the script correctly. I’m already confused, please help me write the control script correctly.
LikeLike