Best approach to get RTSP streaming into web browser from IP Camera?
Here is a blog entry, or tutorial if you will, that achieves something very similar.
Their setup slightly different, but this is the summary:
use ffmpeg
to convert your input into mpeg1video:
ffmpeg -i rtsp://whatever -f mpeg1video -b 800k -r 30 http://localhost:8082/yourpassword/640/480/
Install node.js
with stream-server.js
script from jsmpeg and ws
ws WebSocket package.
To view the stream, use the stream-example.html
and jsmpg.js
from the jsmpeg. Change the WebSocket URL in stream-example.html
to localhost
and open it in your favorite browser.
Update an SO topic suggest two other working solutions, with <video> tag: with stream-m Java server or with ffserver
.
vlc solution:
cvlc -v rtsp://user:password@camera_ip_address --sout='#transcode{vcodec=theo,vb=800,acodec=vorb,ab=128,channels=2,samplerate=44100,scodedec=none}:http{dst=:8080/webcam.ogg}'
Then check
http://localhost:8080/webcam.ogg
Or integrate this url to whatever webservice you want to run
If you are interested in the python api of vlc, here is an example:
import vlc
class WebcamStreamer:
def __init__(self, config):
"""
Expected rtsp url format:
"rtsp://user:[email protected]"
"""
self.instance = vlc.Instance()
self.stream_name = "webcam".encode()
self.rtsp_url = config["rtsp_url"].encode()
def launch_webcam_stream_converter(self):
"""
Basically here is what is done:
cmd= ["cvlc", "-v", f"rtsp://user:[email protected]",
f"--sout='#transcode{{vcodec=theo,vb=800,acodec=vorb,ab=128,channels=2,samplerate=44100,scodedec=none}}:http{{dst=:8080/webcam.ogg}}'"]
subprocess.run(cmd)
"""
ret = vlc.libvlc_vlm_add_broadcast(
p_instance=self.instance,
psz_name=self.stream_name,
psz_input=self.rtsp_url,
psz_output=f"#transcode{{vcodec=theo,vb=800,acodec=vorb,ab=128,channels=2,samplerate=44100,scodedec=none}}:http{{dst=:8080/webcam.ogg}}".encode(),
i_options=0,
ppsz_options=[],
b_enabled=True,
b_loop=False
)
assert (ret == 0)
vlc.libvlc_vlm_play_media(self.instance, self.stream_name)
If you want to stream that to only a very few clients, then you could use a cgi (or in nodejs, a child_process) that directly run ffmpeg:
NodeJS example:
app.getExpressApp().get('/camera/feed', (req, res) => {
// Thanks to https://stackoverflow.com/q/28946904/1954789
const child_process = require('child_process');
res.header('content-type', 'video/webm');
const cmd = `ffmpeg -i rtsp://user:pwd@somewhere/videoSub -c:v copy -c:a copy -bsf:v h264_mp4toannexb -maxrate 500k -f matroska -`.split(' ');
var child = child_process.spawn(cmd[0], cmd.splice(1), {
stdio: ['ignore', 'pipe', process.stderr]
});
child.stdio[1].pipe(res);
res.on('close', () => {
// Kill ffmpeg if the flow is stopped by the browser
child.kill();
});
CGI should be even more easier.
In the browser, you could just
<video autoplay=1 poster="camera.png" ><source src="/camera/feed"></video>
(Use a poster because the video may take some seconds before showing up).
Caveat: This will launch a ffmpeg for each connection to your setup, so it does not scale at all. This should be used only for a very personal website, where connections are limited (ex: to yourself only).
PS: the ffmpeg command may need a bit of tweaking.