Skip to content

Instantly share code, notes, and snippets.

@nunofgs
Last active April 23, 2024 11:39
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • 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
@joltcan
Copy link

joltcan commented Jul 20, 2023

Awesome idea, thanks!

I skipped fetching the image from ffmpeg and used the snapshot URL from octopi/raspberry camera instead, but same result.

(https://gist.github.com/joltcan/bf31bd184b118ee8c983bc1a1fd642af)

Cheers!

@rizz360
Copy link

rizz360 commented Jul 29, 2023

Thanks for this! I adjusted it to use it with USB cameras without having to install octoprint

#!/bin/bash

# Set default values for environment variables
: "${HTTP_URL:=https://webcam.connect.prusa3d.com/c/snapshot}"
: "${CAMERA_DEVICE:=/dev/video0}"
: "${DELAY_SECONDS:=10}"
: "${LONG_DELAY_SECONDS:=60}"
: "${FINGERPRINT:=<fingerprint-from-prusa-connect>}"
: "${TOKEN:=<token-from-prusa-connect>}"

while true; do
    # Grab a frame from the USB webcam using FFmpeg
    ffmpeg \
        -loglevel quiet \
        -stats \
        -y \
        -f v4l2 \
        -i "$CAMERA_DEVICE" \
        -f image2 \
        -vframes 1 \
        -pix_fmt yuyv422 \
        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

@KaiBuesing
Copy link

Hi Nuno,

really a brilliant idea !

There are many people in our Prusa Facebook group who find this exciting, especially with the new MK4. But most of us are not real programmers and can only partially understand what exactly to do.
I count myself among them ;-)

Would you have time and desire to explain us step by step what exactly to do, if for example a Home Assistant with Portainer is available?

Would be really great.

Greetings Kai

@Essbante
Copy link

Essbante commented Sep 3, 2023

Hello! Thanks for the instructions and the script. I was struggling to find the fingerprint value 😅

@ajatoledo
Copy link

For those working on Firefox who are unfamiliar with how to obtain the "Fingerprint" and "Token" information the steps below illustrate how to gather the information. Note: the general process should be similar for other browers, but I haven't tested.

  1. Complete Steps 1 - 4 outlined above.
  2. After completing Step 4 from above, press F12 on your keyboard or access the browser inspector through the menu by selecting Tools > Browser Tools > Web Developer Tools.
  3. In the inspector, click on the Network tab and locate the entry labeled Snapshot in the File column.
  4. Right-click on Snapshot and choose "Copy Value," then select "Copy Request Headers."
  5. Paste the copied output into a text editor of your choice.
  6. From the pasted output, locate the values for the "Fingerprint" and "Token" fields.
  7. Input the retrieved "Fingerprint" and "Token" values into the compose file as required.

@wizzlebippi
Copy link

wizzlebippi commented Oct 19, 2023

I'll admit that I only know enough about docker to be dangerous, but I can't figure out how to get this to run. I keep getting "property prusa-camera is not allowed".

EDIT: Nevermind. I ended up building the container via the portainer GUI using the commands in the config.

@chrishilbert
Copy link

I'll admit that I only know enough about docker to be dangerous, but I can't figure out how to get this to run. I keep getting "property prusa-camera is not allowed".

EDIT: Nevermind. I ended up building the container via the portainer GUI using the commands in the config.

You need a "service:" line as the first line, then it works!

@chrishilbert
Copy link

Can be used in conjunction with the wyze-bridge docker container and point at its rtsp link.

@wbsp
Copy link

wbsp commented Oct 30, 2023

I have noticed that, when trying to use a webcam attached to my laptop, that the camera registration doesn't work. If you open the developer tools, you will see that it is in a loop, failing to get the token from the scanned QR. I can never get the screen to scan a QR.

what the js code wants to do is get the token from the scanned QR and call the function "setToken". so, you can get yourself unstuck by copying the token text into the copy/paste buffer, clicking the link to show the webcam, going into the developer tools->console, and executing **setToken("token-in-your-copy-paste-buffer")**, after that, you can open the developer tools->network and see the snapshot request and look at the headers to retrieve the Fingerprint header.

@Bald-Har
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.

@redalert11
Copy link

this is awesome!

fyi
you can skip finding the "Fingerprint" as it is a string generated by the camera(not specific to prusa connect). you can enter any 16 characters to skip this step.

API Documentation
image

@jtee3d
Copy link

jtee3d commented Dec 14, 2023

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 :-)

@s31teg
Copy link

s31teg commented Dec 20, 2023

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 :-)

AMAZING!!! Just what I was looking for. Works perfect with an rtsps unfi camera url.

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

@p123ad
Copy link

p123ad commented Jan 5, 2024

Hello together,
based on your nice work I made a tutorial for connecting a Raspberry Pi with a Raspi cam to Prusa Connect.

https://gist.github.com/p123ad/5b1482200715d834e9db736fa9e187d0

@KaiBuesing
Copy link

KaiBuesing commented Jan 6, 2024

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 :-)

Fantastic work! Works with my 4 ESP32 cams on Home Assistant as a Portainer stack. My wish would be support for MJPEG in addition to RTSP. I would buy several coffees for that ;-)

@jtee3d
Copy link

jtee3d commented Jan 6, 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.

@s31teg
Copy link

s31teg commented Jan 10, 2024

Thanks. I've reduced FRAME_CAPTURE_DELAY, CAMERA_CYCLE_DELAY to 2s and refresh is a little faster. Not an actual stream but tbh only need a snapshot anyway. TY

@chylld
Copy link

chylld commented Jan 21, 2024

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 :-)

I've gotten to the point where the container is running, and in the GUI log I can see your logo along with the correct RTSP url and token, but nothing happens after the "------" line.

The message does say "Detected use of RTSP_URLS environment variable. Use CAMERA_URLS instead." Is that an error?

Also CPU usage is pinned at 25% by the process for command "curl -X PUT https://webcam.connect....." There is another process "/bin/bash /upload.sh" using 0% CPU.

Do I still need to populate and put upload.sh somewhere if I'm using the docker image?

@chylld
Copy link

chylld commented Jan 26, 2024

Finally got this working using the method in the first post!! Thanks @nunofgs 🙏🏻

@s31teg
Copy link

s31teg commented Apr 2, 2024

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 :-)

I've gotten to the point where the container is running, and in the GUI log I can see your logo along with the correct RTSP url and token, but nothing happens after the "------" line.

The message does say "Detected use of RTSP_URLS environment variable. Use CAMERA_URLS instead." Is that an error?

Also CPU usage is pinned at 25% by the process for command "curl -X PUT https://webcam.connect....." There is another process "/bin/bash /upload.sh" using 0% CPU.

Do I still need to populate and put upload.sh somewhere if I'm using the docker image?

Every so often I get 'This image is more then x mins old'

A restart of the docker fixes it but any way to detect this or just restart the docker on a schedule?

@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!

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