Ffmpeg 从IP摄像头将RTSP流媒体传输到web浏览器的最佳方法?

Ffmpeg 从IP摄像头将RTSP流媒体传输到web浏览器的最佳方法?,ffmpeg,websocket,activex,webbrowser-control,rtsp,Ffmpeg,Websocket,Activex,Webbrowser Control,Rtsp,是否可以将RTSP流式传输数据导入web浏览器 以下是我的一些发现。如果我错了,请纠正我。 只有Mac OS和Safari支持RTSP实时流媒体 HTML 5视频不支持RTSP 我可以使用VLC插件,但我不想使用它 混合ffmpeg和websocket的可能性? 假设我的IP摄像头与以太网连接 在客户端计算机中: 我运行ffmpeg从服务器获取数据(即:IP) 客户端计算机运行websocket 一旦ffmpeg从RTSP服务器获取数据,它将解码并生成任何格式的原始图像(例如:yuv) 现在,我

是否可以将RTSP流式传输数据导入web浏览器

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

  • 只有Mac OS和Safari支持RTSP实时流媒体

  • HTML 5视频不支持RTSP

  • 我可以使用VLC插件,但我不想使用它

  • 混合ffmpeg和websocket的可能性?

    假设我的IP摄像头与以太网连接

    在客户端计算机中:

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

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

    是一篇博客文章,如果你愿意的话,也可以是一篇教程,它实现了一些非常相似的功能

    它们的设置略有不同,但总结如下:

    使用
    ffmpeg
    将输入转换为MPEG1视频:

    ffmpeg  -i rtsp://whatever -f mpeg1video -b 800k -r 30 http://localhost:8082/yourpassword/640/480/
    
    使用和
    ws
    ws-WebSocket包中的
    stream server.js
    脚本安装
    node.js

    要查看流,请使用中的
    stream example.html
    jsmpg.js
    。将
    stream example.html
    中的WebSocket URL更改为
    localhost
    ,并在您喜爱的浏览器中打开它


    更新建议另外两种工作解决方案,带有标签:使用Java server或使用
    ffserver
    我需要在不同的平台和浏览器中显示流媒体。为了在不使用任何插件的情况下实现这一点(不确定它是否能在智能手机和平板电脑上工作),我们使用了与您非常类似的方法。ffmpeg crontab任务每秒创建3个图像,并存储到目录中。使用Jquery,对php的ajax调用读取目录并获取文件名,每330ms更改一次图像(仅更改
    的'src'属性)。为了解决存储问题,使用了其他crontab任务,在1分钟以上的时间内删除文件。它不是真正的流媒体,而是跨浏览器的,很好地解决了这个问题

    ffmpeg任务

    示例ajax调用

    存储控制任务

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

    希望能有所帮助!:)

    如果您只想将其流式传输到少数客户端,那么您可以使用直接运行ffmpeg的cgi(或在nodejs中,一个child_进程):

    NodeJS示例:

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

    在浏览器中,您可以

    find /var/www/path/to/dir -mmin +1 -exec rm -f {} \;
    
    
    
    (使用海报,因为视频可能需要几秒钟才能显示)

    警告: 这将为您的设置的每个连接启动ffmpeg,因此它根本不会扩展。这应该只用于非常私人的网站,在那里连接是有限的(例如:仅限于您自己)。

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

    vlc解决方案:

    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();
        });
    
    然后检查

    http://localhost:8080/webcam.ogg

    或者将此url集成到您想要运行的任何Web服务

    如果您对vlc的python api感兴趣,下面是一个示例:

    <video autoplay=1 poster="camera.png" ><source src="/camera/feed"></video>
    
    scandir.php(由JS在viewcamera.php中使用)

    
    
    streamcam.php(在crontab中运行)


    这支持音频吗?理论上是这样的。我建议使用
    标签更好。我的意思是,它是否仅通过使用视频标签就支持视频音频流?:)是,
    标记同时支持这两种功能;但是准备相关的流是你的责任。我找不到stream-server.js脚本,你能进一步解释一下吗,目前我用nodejs设置了一个本地httpserver并安装了jsmpeg,谢谢。我相信这些天来,最好的方法是。我感到惊讶的是,6年前的这个问题仍然相关。我曾与他一起工作过,并且非常高兴。
    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}'
    
    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)
    
    <?php
    
    $folder = $_GET['name'];
    
    $dir = "../cache/".$folder;
    
    // Sort in descending order
    $b = scandir($dir,1);
    
    $myJSON = json_encode($b);
    
    echo $myJSON;
    
    ?>
    
    <?php
    
    function live_view ($cameraip, $cameraname){
    
        echo shell_exec("/usr/bin/ffmpeg -rtsp_transport tcp -i rtsp://root:pass@".$cameraip."/ufirststream -s 1920x1080 -f image2 -vf fps=fps=5 /var/www/html/occupancy/cache/".$cameraname."/frame%04d.jpg >/dev/null 2>/dev/null &");
    
    }
    
    <img width="100%" height="auto" id="img_cam<?php echo $camera_name_stripped;?>" src="">
    
    
    
    <script>
    
     var cameraName = $(e.relatedTarget).data('camera-name-stripped');
    
     window.livetimer<?php echo $camera_name;?> = setInterval(function() {
    
              <?php echo $camera_name_stripped;?> = $.ajax({
                  url: 'scandir.php?name='+cameraName,
                  type: "POST",
                  dataType: 'json' 
              }).done(function(result)  {
                  $("#img_cam<?php echo $camera_name_stripped;?>").attr('src',"../cache/" + cameraName + "/" + result[0]);
              });
    
              }, 55);    
    
    });
    
    </script>