Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Octoprint IP Camera

How to use Octoprint with an IP camera that has an RTSP stream available

Optional: For Wyze cam only

Install Dafang Hacks on the Wyze Cam.

Once running and all is functional, continue. Set video bitrate to 1500, VBR, 30fps.

Installation

If OctoPrint is running on a Raspberry Pi (3B minimum):

ssh pi@<raspberry_ip>
sudo apt update
sudo apt install vlc

VLC will be used to transcode the rtsp stream to a http stream which OctoPrint can use as streaming URL

nano http_stream.sh

paste the following line:

cvlc -I dummy rtsp://ip_of_yourcam --sout "#transcode{vcodec=mjpg,quality=3,fps=5,acodec=none,width=1280,height=720}:standard{access=http{mime=multipart/x-mixed-replace; boundary=7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:8888/videostream.cgi}" 2>/dev/null

Change the ip_of_yourcam to match the full rtsp url from your camera

CTRL+x to save

chmod +x http_stream.sh
./http_stream.sh

Now you should be able to open your browser:

http://<raspberryip>:8888/videostream.cgi

If it works, you can use this url in OctoPrint for the Stream URL

For the snapshot URL use the stills url from your camera

Change your user/pass and ip to match your setup Click advanced options and uncheck Validate SSL on snapshot URL (if applicable)

As this process is cpu intensive you will need to play around with the quality=x,fps=x (fps = frames per second) options in the cvlc command. These settings work for me, but as I wanted better quality I have this process running on a more powerful device.

@bakaneko59
Copy link

bakaneko59 commented Feb 12, 2021

Apparently this is a feature of the Dafang firmware. With the official Wyze RTSP firmware there is no ability to directly login to the camera since there is no web page. The only way to interface with it is through the Wyze app. I'll have to give Dafang a shot...

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 12, 2021

Okay, so this has pissed me off enough to the point where I made a fully working RTSP to HTML flask script in python:

try:
    try:
        from flask import Flask, render_template, Response
        import cv2
    except:
        os.system('pip3 install flask opencv-python')
        from flask import Flask, render_template, Response
        import cv2

    app = Flask(__name__)
    camera = cv2.VideoCapture("rtsp://IPCAM")

    def gen_frames():
        while True:
            success, frame = camera.read()
            if not success:
                break
            else:
                ret, buffer = cv2.imencode('.jpg', frame)
                frame = buffer.tobytes()
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
    @app.route('/')
    def index():
        return '''<img src="/video_feed" width="100%" height="100%">'''


    @app.route('/video_feed')
    def video_feed():
        return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

    if __name__ == "__main__":
        app.run(debug=True, host='0.0.0.0', port=8080)
except Exception as e:
    print('\n\n\n'+str(e)+'\n\n\n')

replace IPCAM with your RTSP cam URL and write it to a file called video.py

then run the script with python3 video.py

the video is available at raspberryipadress:8080

@bakman2
Copy link
Author

bakman2 commented Feb 12, 2021

Okay, so this has pissed me off enough to the point where I made a fully working RTSP to HTML flask script in python:

nice one! I like the use of opencv, which could make sense indeed.
script doesn't work for me however, it can't find the template.

/video_feed does show a frame, something is working, just not the index.html template.

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 13, 2021

Okay, so this has pissed me off enough to the point where I made a fully working RTSP to HTML flask script in python:

nice one! I like the use of opencv, which could make sense indeed.
script doesn't work for me however, it can't find the template.

/video_feed does show a frame, something is working, just not the index.html template.

Extremely sorry abt that, ima update the post and the new code here:

try:
    try:
        from flask import Flask, render_template, Response
        import cv2
    except:
        os.system('pip3 install flask opencv-python')
        from flask import Flask, render_template, Response
        import cv2

    app = Flask(__name__)
    camera = cv2.VideoCapture("rtsp://IPCAM")

    def gen_frames():
        while True:
            success, frame = camera.read()
            if not success:
                break
            else:
                ret, buffer = cv2.imencode('.jpg', frame)
                frame = buffer.tobytes()
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
    @app.route('/')
    def index():
        return '''<img src="/video_feed" width="100%" height="100%">'''


    @app.route('/video_feed')
    def video_feed():
        return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

    if __name__ == "__main__":
        app.run(debug=True, host='0.0.0.0', port=8080)
except Exception as e:
    print('\n\n\n'+str(e)+'\n\n\n')

this shouldn't require any other code to function

Before I forgot to add index.html to the code itself. And also, for reference, I am using a Wyze Cam 2 with this.

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 13, 2021

Anyways, with this solution, you can view live video at raspberryipadress:8080, and snapshots at raspberryipadress:8080/video_feed

@kdavid2
Copy link

kdavid2 commented Feb 17, 2021

Thank you for this extremely useful piece of code. What about the raspberry CPU consumption of this running?

And, last but not least, can you set somehow the FPS in order to reduce the CPU usage?

@kdavid2
Copy link

kdavid2 commented Feb 17, 2021

Anyways, with this solution, you can view live video at raspberryipadress:8080, and snapshots at raspberryipadress:8080/video_feed

Partial success. While I can view the stream and snapshot on my browser:

  1. If I am viewing the first stream on one browser tab and then I try to open a second tab to view for example the snapshot stream, the latter never opens and the program crashes (which means the first instance stops showing the stream and the second never opens). After some time the script crashes.
  2. The links don't work on octopi. In webcam preview mode there is no picture.

I guess this is due to big processing times. I guess one suggested solution is to run the script constantly and cache the jpg locally every 0.5 seconds. On HTTP GET request it should serve the saved jpg instead of doing real time processing. The way it is now it cannot work with octopi.

@bakaneko59
Copy link

bakaneko59 commented Feb 17, 2021

I'm obviously doing something wrong. When I run the code from @GitHubEmploy I get "SyntaxError: 'break' outside of loop". I'm including my code in hopes a second set of eyes can find my mistake...

Screenshot_20210217-100539_ConnectBot

@bakman2
Copy link
Author

bakman2 commented Feb 17, 2021

I'm obviously doing something wrong. When I run the code I get "SyntaxError: 'break' outside of loop". I'm including my code in hopes a second set of eyes can find my mistake...

With which version of python are you running this ?

I tried the script, it works, but it is extremely heavy on the cpu (ie. *5 compared to the solution i posted).
The problem with vlc is, is when the buffer breaks, the script breaks. The buffer can easily break with high resolution and high framerate settings.

@bakaneko59
Copy link

bakaneko59 commented Feb 17, 2021

Python 3.7.3

So are you saying I should go back to the vlc method instead of the Python script?

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 17, 2021

I'm obviously doing something wrong. When I run the code from @GitHubEmploy I get "SyntaxError: 'break' outside of loop". I'm including my code in hopes a second set of eyes can find my mistake...

Screenshot_20210217-100539_ConnectBot

Actually,
do you see this line in your code?

            if not success:
                break

That's whats causing the error
it's because when you copy-pasted it you didn't indent this. just index both of these lines and it will work, or you could just delete them, either works.

@bakaneko59
Copy link

bakaneko59 commented Feb 17, 2021

it's because when you copy-pasted it you didn't indent this. just index both of these lines and it will work, or you could just delete them, either works.

Okay, I deleted them. Now I get the error "name 'os' is not defined"

Sorry - I've managed to work in IT for over 35 years and still I know nothing about Python.

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 17, 2021

it's because when you copy-pasted it you didn't indent this. just index both of these lines and it will work, or you could just delete them, either works.

Okay, I deleted them. Now I get the error "name 'os' is not defined"

Sorry - I've managed to work in IT for over 35 years and still I know nothing about Python.

I may also have to apologize, I haven't worked very much on this script, so I decided to refine it.

try:
    from flask import Flask, render_template, Response
    import cv2
except:
    import os
    os.system('pip3 install flask opencv-python')
    from flask import Flask, render_template, Response
    import cv2

app = Flask(__name__)
camera = cv2.VideoCapture("rtsp://IPCAM")

def gen_frames():
    while True:
        success, frame = camera.read()
        if not success:
            break
        else:
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.route('/')
def index():
    return '''<img src="/video_feed" width="100%" height="100%">'''


@app.route('/video_feed')
def video_feed():
    return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8080)

@kdavid2
Copy link

kdavid2 commented Feb 17, 2021

This code consumes a lot of CPU resources and due to the delay octoprint cannot grab the jpg from the link. Is there any possibility to save the jpg locally and then octoprint to retrieve it asyncronously from one http address?

@Judas2016
Copy link

Judas2016 commented Feb 17, 2021

This code consumes a lot of CPU resources and due to the delay octoprint cannot grab the jpg from the link. Is there any possibility to save the jpg locally and then octoprint to retrieve it asyncronously from one http address?

You're getting the hit of Python loops and openCV stream conversion. The VLC command that started this thread can be run from terminal w/out the overhead of Python. The command creates a HTTP endpoint and the framerate is adjustable. I found on a RP3 FPS=1 is about max framerate before the video feed starts to lag.

I've been using this command to create the stream and it's worked flawless for months.
cvlc -R rtsp://user:pwd@IPADDRESS/live --sout-x264-preset fast --sout='#transcode{acodec=none,vcodec=MJPG,vb=100,fps=1}:standard{mux=mpjpeg,access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},dst=:8888/videostream.cgi}' --sout-keep

@kdavid2
Copy link

kdavid2 commented Feb 17, 2021

This code consumes a lot of CPU resources and due to the delay octoprint cannot grab the jpg from the link. Is there any possibility to save the jpg locally and then octoprint to retrieve it asyncronously from one http address?

You're getting the hit of Python loops and openCV stream conversion. The VLC command that started this thread can be run from terminal w/out the overhead of Python. The command creates a HTTP endpoint and the framerate is adjustable. I found on a RP3 FPS=1 is about max framerate before the video feed starts to lag.

I've been using this command to create the stream and it's worked flawless for months.
cvlc -R rtsp://user:pwd@IPADDRESS/live --sout-x264-preset fast --sout='#transcode{acodec=none,vcodec=MJPG,vb=100,fps=1}:standard{mux=mpjpeg,access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},dst=:8888/videostream.cgi}' --sout-keep

Good point, thanks for this, I will try it. But what about the snapshot url? I need this for octolapse and my rtsp camera doens't have a link of its own.

By the way, what is the CPU consumption on raspberry pi with your script?

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 17, 2021

This code consumes a lot of CPU resources and due to the delay octoprint cannot grab the jpg from the link. Is there any possibility to save the jpg locally and then octoprint to retrieve it asyncronously from one http address?

You're getting the hit of Python loops and openCV stream conversion. The VLC command that started this thread can be run from terminal w/out the overhead of Python. The command creates a HTTP endpoint and the framerate is adjustable. I found on a RP3 FPS=1 is about max framerate before the video feed starts to lag.
I've been using this command to create the stream and it's worked flawless for months.
cvlc -R rtsp://user:pwd@IPADDRESS/live --sout-x264-preset fast --sout='#transcode{acodec=none,vcodec=MJPG,vb=100,fps=1}:standard{mux=mpjpeg,access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},dst=:8888/videostream.cgi}' --sout-keep

Good point, thanks for this, I will try it. But what about the snapshot url? I need this for octolapse and my rtsp camera doens't have a link of its own.

By the way, what is the CPU consumption on raspberry pi with your script?

You can view live video at raspberryipadress:8080, and snapshots at raspberryipadress:8080/video_feed

The CPU consumption is around 12 - 14% estimation

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 17, 2021

This code consumes a lot of CPU resources and due to the delay octoprint cannot grab the jpg from the link. Is there any possibility to save the jpg locally and then octoprint to retrieve it asyncronously from one http address?

it's actually set to only display the picture when asked, so averaged for around 12 - 14% CPU consumption usage, otherwise, it runs in the backround at around 1.3% CPU usage

The only real problem is 24/h livestreams, those can really wear down on your CPU, so i dont suggets them, tho it still seems fine.

@kdavid2
Copy link

kdavid2 commented Feb 17, 2021

Anyways, with this solution, you can view live video at raspberryipadress:8080, and snapshots at raspberryipadress:8080/video_feed

Partial success. While I can view the stream and snapshot on my browser:

  1. If I am viewing the first stream on one browser tab and then I try to open a second tab to view for example the snapshot stream, the latter never opens and the program crashes (which means the first instance stops showing the stream and the second never opens). After some time the script crashes.
  2. The links don't work on octopi. In webcam preview mode there is no picture.

I guess this is due to big processing times. I guess one suggested solution is to run the script constantly and cache the jpg locally every 0.5 seconds. On HTTP GET request it should serve the saved jpg instead of doing real time processing. The way it is now it cannot work with octopi.

Hi GitHubEmploy. Thanks for your reply. The script you suggested doesn't work for me at all inside Octoprint. Please see above. If there is any possibility to debug it let me know.

@kdavid2
Copy link

kdavid2 commented Feb 18, 2021

vlc

Unfortunately, I didn't have luck even with vlc. I receive the errors shown in the picture BUT the stream works flawlessly on a browser via the link "http://raspberrypiaddress:8888/videostream.cgi" but nothing appears in octoprint. The message "webcam stream loading" is blinking and that's all. I rest my case... I don't know what's wrong. I even tried octoprint's webcam iframe plugin, but no luck either... Any thoughts?

@GitHubEmploy
Copy link

GitHubEmploy commented Feb 18, 2021

Honestly, at this point I'm just streaming it to youtube and using the embed url along with iframe

@JoeDante
Copy link

JoeDante commented Jul 25, 2021

Yea,

I was able to get it to run. This is what I did:
Start by log in to your Raspberry Pi.
To create the http_stream.sh file write:

sudo nano http_stream.sh

Paste in this in your http_stream.sh:

cvlc -R rtsp://USERNAME:PASSWORD@IP_OF_WYZECAM/live --sout-x264-preset fast --sout='#transcode{acodec=none,vcodec=MJPG,vb=100,fps=0.5}:standard{mux=mpjpeg,access=http{mime=multipart/x-mixed-replace; boundary=--7b3cc56e5f51db803f790dad720ed50a},dst=:8888/videostream.cgi}' --sout-keep

Press CTRL + X to save the file
To get it to run every time I reboot the Pi this is what I did:
Created a service file in /etc/systemd/system/ called wyze.service by writing:

sudo nano /etc/systemd/system/wyze.service

Write this in the wyze.service file:

[Unit]
Description=Start Wyze stream
After=network.target

[Service]
ExecStart=/bin/sh /home/pi/http_stream.sh
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

Save the file by pressing CTRL + X
Write:

systemctl daemon-reload

Enable the service by writing:

systemctl enable wyze.service

Confirm that the service is running by writing:

systemctl --all | grep wyze.service

Start the service by writing:

systemctl start wyze.service

Now go to your browser and type in:
http://IP_OF_YOUR_PI:8888/videostream.cgi
and you should see the picture from your camera!

Yea, thanks, this was really helpful!

I was able to get it to run. This is what I did:

Start by log in to your Raspberry Pi.
To create the http_stream.sh file write:

sudo nano http_stream.sh

Paste in this in your http_stream.sh (make sure you change the USERNAME and PASSWORD and IP_OF_WYZECAM to whatever you have in the app under the RTSP settings) :

cvlc -R rtsp://USERNAME:PASSWORD@IP_OF_WYZECAM/live --sout-x264-preset fast --sout='#transcode{acodec=none,vcodec=MJPG,vb=100,fps=0.5}:standard{mux=mpjpeg,access=http{mime=multipart/x-mixed-replace; boundary=--7b3cc56e5f51db803f790dad720ed50a},dst=:8888/videostream.cgi}' --sout-keep

Press CTRL + X to save the file

To get it to run every time I reboot the Pi this is what I did:

Created a service file in /etc/systemd/system/ called wyze.service by writing:

sudo nano /etc/systemd/system/wyze.service

Write this in the wyze.service file:

[Unit]
Description=Start Wyze stream
After=network.target

[Service]
ExecStart=/bin/sh /home/pi/http_stream.sh
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

Save the file by pressing CTRL + X

Write:

systemctl daemon-reload

Enable the service by writing:

systemctl enable wyze.service

Confirm that the service is running by writing:

systemctl --all | grep wyze.service

Start the service by writing:

systemctl start wyze.service

Now go to your browser and type in:
http://IP_OF_YOUR_PI:8888/videostream.cgi
and you should see the picture from your camera!

I did that, and it worked fine so far. BUT: my videofeed is incredible slow. Like one frame every 10 seconds, so one minute of realtime takes up 10 minutes of video. CPU soesn't seem to be the problem, I got a Pi 4 and it shows about 33% CPU activity. Does anyone know what could cause the Problenm? BTW, I got a Yi cam with Yi Hack firmware that supports RTSP streams.

@GitHubEmploy
Copy link

GitHubEmploy commented Jul 26, 2021

Okay, so update on this issue, I have no clue how to stream RTSP to octoprint anymore. So far, iv been using the RTSP to be converted locally using TinyCam on a 10 dollar tablet, then restreamed locally. But that's not the ideal solution, and I need to come up with a new one. IF anyone has any ideas that would be great.

@JoeDante
Copy link

JoeDante commented Jul 27, 2021

We definititely need a plugin for that....

@GitHubEmploy
Copy link

GitHubEmploy commented Oct 29, 2021

UPDATE: Half a year later, a solution was made. https://github.com/aler9/rtsp-simple-server is what I'm currently using, and it works great, no problems yet.

@bakman2
Copy link
Author

bakman2 commented Oct 29, 2021

UPDATE: Half a year later, a solution was made. https://github.com/aler9/rtsp-simple-server is what I'm currently using, and it works great, no problems yet.

Can you share your settings for this server ?

@Cjkeenan
Copy link

Cjkeenan commented Dec 18, 2021

@GitHubEmploy I also would appreciate if you could share your settings. I have it outputting my RTSP stream on my Reolink E1 Pro to my RPi, but I would like to stream that out to my network as a mp4 or something readable by OctoPrint.

@RonaldCoutinho
Copy link

RonaldCoutinho commented Feb 25, 2022

Hi, guys!

I solved my problem in a simple way, after a lot of research, I entered this post with this smart solution and very easy to execute! Before running the .BAT it is necessary to have VLC installed on your computer, then just replace your rtsp:// link inside the BAT and that's it!

:: The following line is neccessary if you need an ability to restart the streams with this batch file
:: Kill all existing streams (the command actually suspends ALL the vlc processes):
taskkill /f /im "vlc.exe"

:: Run two instances of VLC. These would transcode MP4 rtsp-stream to Motion JPEG http-stream:
start vlc -vvv -Idummy rtsp://login:password@192.168.0.2/streaming/channels/2/preview --sout #transcode{vcodec=MJPG,venc=ffmpeg{strict=1},fps=10,width=640,height=360}:standard{access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:9911/}
start vlc -vvv -Idummy rtsp://login:password@192.168.0.3/streaming/channels/2/preview --sout #transcode{vcodec=MJPG,venc=ffmpeg{strict=1},fps=10,width=640,height=360}:standard{access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:9912/}

:: In order to execute VLC with `vlc` as in exapmle above, you have to add corresponding value to the PATH variable.
:: Otherwise you have to use full path e.g `"C:\Program Files\VLC\vlc.exe"`.

:: Such rtsp-stream uri as rtsp://login:password@127.0.0.1/streaming/channels/2/preview is specific for Hikvision cameras.

:: Access the http-streams like that:
:: For the first camera: http://127.0.0.1:9911 
:: For the the second camera: http://127.0.0.1:9912 
:: For external access change `127.0.0.1` to the address of the server (or PC) you are running VLC on.
:: Your server's Ports you are using for streaming (9911 and 9912 from current example) must be open for external access.

by @JonesTwink/cctv-startup.bat

@bastel-123
Copy link

bastel-123 commented Mar 9, 2022

UPDATE: Half a year later, a solution was made. https://github.com/aler9/rtsp-simple-server is what I'm currently using, and it works great, no problems yet.

Hi,

can you please give us some hints how you integrated this with octorprint.

That you be very fine
Frank

@JDIacobbo
Copy link

JDIacobbo commented Apr 28, 2022

UPDATE: Half a year later, a solution was made. https://github.com/aler9/rtsp-simple-server is what I'm currently using, and it works great, no problems yet.

Hi,

can you please give us some hints how you integrated this with octorprint.

That you be very fine Frank

I am also interested in how @bastel-123 was able to get this working with Octoprint.

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