从IP Camera获取RTSP流媒体到网络浏览器的最佳方法?

时间:2014-04-11 11:25:44

标签: ffmpeg websocket activex webbrowser-control rtsp

是否可以将RTSP Streaming数据导入Web浏览器?

以下是我的一些发现。如果我错了,请纠正我?

  1. 只有Mac OS和Safari支持RTSP直播。

  2. HTML 5视频不支持RTSP。

  3. 我可以使用VLC插件,但我不想使用它。

  4. 混合ffmpeg和websocket的可能性

    假设我的IP摄像机已连接以太网。

    在客户端计算机中:

    1. 我运行ffmpeg从服务器获取数据(即:IP)
    2. 客户端计算机运行websocket。
    3. 一旦ffmpeg从RTSP服务器获取数据,它就会解码并生成任何格式的原始图像(例如:yuv)。
    4. 现在,我必须通过websocket将此图像发送到浏览器。
    5. 问题:

      1. 这是正确的方法吗?
      2. 如何将ffmpeg中的解码图像输入浏览器?
      3. 在不同的地方我可能错了。请提供意见。

4 个答案:

答案 0 :(得分:18)

Here是一个博客条目,或者如果您愿意,可以获得非常相似的教程。

他们的设置略有不同,但这是摘要:

使用ffmeg将您的输入转换为mpeg1video:

ffmpeg  -i rtsp://whatever -f mpeg1video -b 800k -r 30 http://localhost:8082/yourpassword/640/480/

使用jsmpegnode.js ws WebSocket包中的stream-server.js脚本安装ws

要查看信息流,请使用jsmpeg中的stream-example.htmljsmpg.js。将stream-example.html中的WebSocket网址更改为localhost,然后在您喜欢的浏览器中将其打开。

更新 SO topic建议另外两个有效的解决方案,< video> tag:使用stream-m Java服务器或使用ffserver

答案 1 :(得分:1)

如果您只想将其流式传输给很少的客户端,则可以使用直接运行ffmpeg的cgi(或在nodejs中为child_process):

NodeJS示例:

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应该更容易。

在浏览器中,您可以

<video autoplay=1 poster="camera.png" ><source src="/camera/feed"></video>

(使用海报是因为视频可能需要几秒钟才能显示出来)。

注意事项: 这将为与您的设置的每个连接启动一个ffmpeg,因此它根本无法扩展。这仅应用于连接受限的非常个人化的网站(例如:仅针对您自己)。

PS:ffmpeg命令可能需要一些调整。

答案 2 :(得分:0)

我需要在不同的平台和浏览器中显示流式传输。为了在不使用任何插件的情况下做到这一点(不确定它是否适用于智能手机和平板电脑),使用了与您非常相似的方法。 ffmpeg crontab任务每秒创建3个图像,并存储到目录中。使用Jquery,对php的ajax调用读取目录并获取文件的名称,每隔330ms更改一次图像(仅更改<img>的'src'属性)。要解决存储问题,请使用其他crontab任务删除超过1分钟的文件。这不是真正的流媒体,而是跨浏览器,并且很好地解决了这个问题。

ffmpeg任务

ffmpeg -i "rtsp://path/to/cam" -s 320x240 -f image2 -vf fps=fps=3 cache/%04d.jpg

示例ajax调用

$.ajax({
        url: '_read_dir.php',
        type: 'POST',
        dataType: 'json'
    })
    .done(function(result) {        
        $("#img_cam").prop('src',"cache/" + result.img);            
    });

存储控制任务

find /var/www/path/to/dir -mmin +1 -exec rm -f {} \;
希望可以帮到你! :)

答案 3 :(得分:0)

vlc 解决方案:

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}'

然后检查

http://localhost:8080/webcam.ogg

或者将此网址集成到您要运行的任何网络服务

如果你对vlc的python api感兴趣,这里有一个例子:

import vlc

class WebcamStreamer:
    def __init__(self, config):
        """
        Expected rtsp url format:
        "rtsp://user:password@192.168.0.1"
        """
        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:password@192.168.0.16",
            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)