Skip to content

Instantly share code, notes, and snippets.

@nunofgs
Last active May 6, 2025 02:35
Show Gist options
  • Save nunofgs/84861ee453254823be6b069ebbce9ad2 to your computer and use it in GitHub Desktop.
Save nunofgs/84861ee453254823be6b069ebbce9ad2 to your computer and use it in GitHub Desktop.
Use any RTSP camera with Prusa Connect

I use a cheap Tapo C100 webcam to monitor my 3D prints. It supports RTSP.

Screenshot 2023-07-17 at 23 26 34

Instructions

  1. Go to the Cameras section at https://connect.prusa3d.com
  2. Add a new camera.
  3. Click the QR code link
  4. Click "Start Camera"
  5. Open your browser's inspector window and look for the "/snapshot" request.
  6. Copy the "Fingerprint" and "Token" headers into the docker-compose below.

The end result!

Screenshot 2023-07-17 at 23 13 10

prusa-camera:
image: linuxserver/ffmpeg
restart: always
entrypoint: /bin/bash
command: /upload.sh
environment:
RTSP_URL: "rtsp://<username>:<password>@<camera.ip.address>/stream1"
FINGERPRINT: "<fingerprint-from-prusa-connect>"
TOKEN: "<token-from-prusa-connect-link>"
volumes:
- ./upload.sh:/upload.sh
#!/bin/bash
# Set default values for environment variables
: "${HTTP_URL:=https://webcam.connect.prusa3d.com/c/snapshot}"
: "${DELAY_SECONDS:=10}"
: "${LONG_DELAY_SECONDS:=60}"
while true; do
# Grab a frame from the RTSP stream using FFmpeg (timeout at 5s)
ffmpeg \
-timeout 5000000 \
-loglevel quiet \
-stats \
-y \
-rtsp_transport tcp \
-i "$RTSP_URL" \
-f image2 \
-vframes 1 \
-pix_fmt yuvj420p \
output.jpg
# If no error, upload it.
if [ $? -eq 0 ]; then
# POST the image to the HTTP URL using curl
curl -X PUT "$HTTP_URL" \
-H "accept: */*" \
-H "content-type: image/jpg" \
-H "fingerprint: $FINGERPRINT" \
-H "token: $TOKEN" \
--data-binary "@output.jpg" \
--no-progress-meter \
--compressed
# Reset delay to the normal value
DELAY=$DELAY_SECONDS
else
echo "FFmpeg returned an error. Retrying after ${LONG_DELAY_SECONDS}s..."
# Set delay to the longer value
DELAY=$LONG_DELAY_SECONDS
fi
sleep "$DELAY"
done
@ChiefPoints
Copy link

Hi all, I've turned this in to a standalone Docker image where multiple cameras can be specified using environment variables in the docker-compose file or docker command: https://hub.docker.com/r/jtee3d/prusa_connect_rtsp

Like so (docker-compose.yml):

version: '3.8'
services:
  prusa_connect_rtsp:
    image: jtee3d/prusa_connect_rtsp:latest
    restart: always
    environment:
      RTSP_URLS: >
        rtsp://username:password@192.168.1.11/live0,
        rtsp://username:password@192.168.1.12/live0,
        rtsp://username:password@192.168.1.13/live0
      TOKENS: >
        5dvoIByhfG7AeODTiNNk,
        MdVaUadfw93MBdlZSlqM,
        fejnJhrhCGncXsDU0R8S

Let me know your thoughts :-)

Thanks for setting this up. Got it running on my Synology NAS in Container Manager. Gave me errors at first, which I put up on your github, but then it just started working. Thanks so much!

@calexandre
Copy link

calexandre commented May 13, 2024

If anyone is interested to make this work on octoprint, I've forked the gist and modified the script to get image snapshot from the rpi camera api.

@TheChiefSmeg
Copy link

Is there perhaps a video somewhere on how I can install the Tapo C100 in Prusa Cennect? I have tried the above, but I can't figure it out myself. The camera itself works and I can access it via RTSP. I'm a total novice and I have no idea how to install this.

Did you ever find out how to do this? I have no idea what to do with the docker stuff once I’ve added the info to it (total novice)

@s31teg
Copy link

s31teg commented Jul 16, 2024

[ChiefPoints] above has done all the work and a guide.

@ChiefPoints
Copy link

Is there perhaps a video somewhere on how I can install the Tapo C100 in Prusa Cennect? I have tried the above, but I can't figure it out myself. The camera itself works and I can access it via RTSP. I'm a total novice and I have no idea how to install this.

Did you ever find out how to do this? I have no idea what to do with the docker stuff once I’ve added the info to it (total novice)

jtee3d set up a docker for it, and it does work: https://gist.github.com/nunofgs/84861ee453254823be6b069ebbce9ad2?permalink_comment_id=4793596#gistcomment-4793596

@DK-1989
Copy link

DK-1989 commented Nov 11, 2024

Could you add the x2 delays as variables also to play with this?

I have added the following optional environment variables: FRAME_CAPTURE_DELAY, CAMERA_CYCLE_DELAY and CONNECTION_TIMEOUT_DELAY

My wish would be support for MJPEG in addition to RTSP.

I have added MJPEG stream support.

Where can I put the delay lines? in the docker compose.yml or do I need to make another file? I have everything working but want the snapshots faster than the standard 10 sec?

@xssociety
Copy link

Ich bekomme ständig die Fehlermeldung "Invalid Fingerprint" ist das Problem bekannt, was mache ich falsch?

@nikscha
Copy link

nikscha commented Mar 5, 2025

Modified the script to work with camera streams from ESPHome:

#!/bin/sh

# Set default values for environment variables
: "${HTTP_URL:=https://webcam.connect.prusa3d.com/c/snapshot}"
: "${DELAY_SECONDS:=10}"
: "${LONG_DELAY_SECONDS:=60}"

while true; do
    # Use curl instead of wget to avoid method issues
    curl -s -o output.jpg "$SNAPSHOT_URL"

    # Check if the download was successful
    if [ $? -eq 0 ] && [ -s output.jpg ]; then
        # Upload image to Prusa Connect
        curl -X PUT "$HTTP_URL" \
            -H "accept: */*" \
            -H "content-type: image/jpg" \
            -H "fingerprint: $FINGERPRINT" \
            -H "token: $TOKEN" \
            --data-binary "@output.jpg" \
            --no-progress-meter \
            --compressed

        # Reset delay to the normal value
        DELAY=$DELAY_SECONDS
    else
        echo "Failed to download snapshot. Retrying after ${LONG_DELAY_SECONDS}s..."
        DELAY=$LONG_DELAY_SECONDS
    fi

    sleep "$DELAY"
done

@spkane
Copy link

spkane commented Mar 29, 2025

If it is useful to folks, I have a version of this as a GitHub repo here: https://github.com/spkane/rtsp2prusa .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment