I'd been wanting to add a webcam to my OctoPrint setup for a little while now, but I'm a professional sysadmin (ie, really, really lazy), and having to build and install mjpg-streamer
manually just did not appeal. So I did a little reading and figured out how to set up a streaming mjpeg server using tools I already had installed on my Pi - ffmpeg.
This guide explains how I set up ffmpeg
as a drop-in replacement for mjpeg-streamer
. It expects a basic knowledge of Linux - how to create and edit text files, and how to run commands. If you've successfully installed OctoPrint following https://discourse.octoprint.org/t/setting-up-octoprint-on-a-raspberry-pi-running-raspbian/2337, then you'll be fine.
Notes about performance
This method will likely involve some transcoding, so I expect it to be more CPU-intensive than mjpg-streamer
. On my Raspberry Pi 3B+ running a USB webcam (Logitech C920), ffmpeg is consuming ~20% CPU, and pushes the load average up around 0.2-0.3. I've had no problems running this setup for a few prints around 1.5-2 hours each. But on older Pis this extra load may be a problem.
On the other hand, now that I know how easy this is to get running, my next step is to look in to replacing the mjpeg stream with a low bitrate h264 stream, to take advantage of the hardware encoder on the Pi.
Getting started
This setup requires two components. First, an ffserver
process is run that sets up the actual streaming server, which serves an mjpeg stream and static jpg images. Second, an ffmpeg
process is launched that pulls video from the webcam and feeds it to ffserver.
We're setting up ffserver to use the same port as the default mjpg-streamer
port. It's important to make sure mjpg-streamer is stopped before trying this.
Set up ffserver
The ffserver configuration file is located at /etc/ffserver.conf
. Create it with these contents
# ffserver configuration for an mjpeg stream
# Adapted from
# https://gist.github.com/peterhellberg/ebfc72147c2009ee720aafe57ce9c141
HTTPPort 8080
HTTPBindAddress 0.0.0.0
MaxHTTPConnections 200
MaxClients 100
MaxBandWidth 500000
CustomLog -
<Feed camera.ffm>
File /tmp/camera.ffm
FileMaxSize 5M
</Feed>
<Stream camera.mjpeg>
Feed camera.ffm
Format mpjpeg
# Make sure frame rate and size
# match those passed to ffmpeg
VideoFrameRate 5
VideoSize 640x480
VideoGopSize 12
VideoBitRate 4096
VideoBufferSize 4096
VideoQMin 5
VideoQMax 51
NoAudio
Strict -1
</Stream>
<Stream static-camera.jpg>
Feed camera.ffm
Format jpeg
VideoFrameRate 2
VideoIntraOnly
VideoSize 640x480
NoAudio
NoDefaults
Strict -1
</Stream>
Then run the server (as a background process so we can keep using this session) with:
ffserver &
Running ffmpeg
I'm running ffmpeg to get video from the first attached webcam with this command:
ffmpeg -input_format mjpeg -video_size 640x480 -framerate 5 -i /dev/video0 -c:v copy http://localhost:8090/camera.ffm
You can check everything's working by browsing to http://<Your Pi's IP>:8080/camera.mjpeg
to view the 5fps live stream.
Running automatically at startup
Again, if you've got mjpg-streamer
configured to run at boot, this is the part where you make sure that's been disabled before continuing.
I set up two systemd
services to automatically run ffserver and ffmpeg.
First, create /etc/systemd/system/ffserver.service
with these contents. Note that the User=
line specifies the user to run ffserver as. This will work fine for a default Pi install, but may need to be tuned for your setup.
[Unit]
Description=FFMPEG streaming server service
[Service]
User=pi
ExecStart=/usr/bin/ffserver
[Install]
WantedBy=multi-user.target
Second, create /etc/systemd/system/ffmpeg.service
with these contents. Again, the User=
line may need to be adjusted. This service adds some extra flags to ffmpeg so it won't spam the logs with all the debug info that was dumped to your console when testing it above.
[Unit]
Description=FFMPEG transcoder service
After=ffserver.service
[Service]
User=pi
# -video_size and -framerate should match the settings in ffserver.conf
ExecStart=/usr/bin/ffmpeg -input_format mjpeg -video_size 640x480 -framerate 5 -i /dev/video0 -c:v copy -nostats -loglevel panic http://localhost:8090/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:
/webcam/camera.mjpeg
- Snapshot URL:
/webcam/static-camera.jpg