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.
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:
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.
/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
/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:
- Snapshot URL: