Skip to main content

Python

RTSP to MJPEG for OctoPrint

What ?

I recently decided to update my very old installation of OctoPrint on my Raspberry Pi and to migrate to a spare small NUC that I had lying around.

The main reason was that the existing setup was running two instances on the Pi and handling two printers simultaneously. It had been working fine for a year, and I never updated it because of the adage, "if it's not broken, don't fix it!"

Well, it broke today! In the middle of a print, the Pi computed its last and died, likely just the SD card, though. But I took this as an opportunity to rebuild my setup, hence the NUC. Instead of running two instances as services directly on the OS, I switched to using containers. Now, I run two containers of OctoPrint, one for each printer. I have one USB camera mounted on one of the printers. This setup is quite simple, since OctoPrint is automatically pre-configured to use a USB webcam, but only one.

Problem

As I mentioned, I have one USB webcam but two printers, and I would like to monitor both. Additionally, I have an old IP camera, the Anker Eufy Indoor Cam 2K Pan & Tilt (T8410)—not an advertisement, by the way, it's just what I had around. I remember buying it new for about 50 Euros, and it also has an RTSP stream, like most IP cameras. So, I connected this camera to the network, aimed it at the printers, and then... OctoPrint does not accept RTSP streams as camera sources! Now what do I do?

Solution

To cut a long story short, I created a converter that takes an RTSP stream and converts it into an MJPEG stream, which OctoPrint accepts. Essentially, it's a brute force approach using FFmpeg and Flask as a web service. It's not CPU-efficient at all, as it only uses the CPU without GPU acceleration due to the hardware limitations. Fortunately, I only need one stream to work, and it's not too demanding for the NUC I have, but I'm not sure if a Raspberry Pi could handle it.

On an Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz NUC watching one stream, it consumes about 25% of the CPU. I also have a version with OpenCV, which was single-threaded and consumed 60% of one thread... so I'm not sure which is better. 😄


Since I can't be the only one facing this issue, I decided to create a small UI and a Docker container for it. Perhaps this could help someone else, or maybe someone could come up with a more efficient way to handle it.

GitHub - VladoPortos/rtsp-to-mjpeg
Contribute to VladoPortos/rtsp-to-mjpeg development by creating an account on GitHub.

Above is link to repo and you only need to run:

docker compose up -d

inside the repo folder, it will build the container and expose it on port 5000.

You can visit the url and add your RTSP sources.

  • RTSP URL: Enter your streaming URL here. My camera uses the format rtsp://<user>:<pass>@<ip>/live0. Consult your camera's manual, as the format may vary.
  • Quality: Choose from 1 (the best) to 31 (the worst). This setting affects the intensity of the CPU usage and the picture quality you get. I usually set it between 15 and 20.
  • Resolution: What resolution do you want the output stream to be? I typically set it to the same as my camera.
  • FPS: What FPS (frames per second) do you want the output stream to be? I usually opt for 24.

As you can see, after adding the camera stream, you'll get a link to "Watch Stream." Go there, copy the link, and you can use it in OctoPrint. Consider getting the MultiCamera plugin if you want to use both the USB camera and this one simultaneously.

If you found this guide helpful and feel like buying me a drink to show your appreciation, feel free to hit the donation button. Cheers!