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.