【问题标题】:Best approach to get RTSP streaming into web browser from IP Camera?从 IP 摄像机将 RTSP 流式传输到网络浏览器的最佳方法?
【发布时间】:2014-05-25 12:47:28
【问题描述】:

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

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

  1. 仅 Mac OS 和 Safari 支持 RTSP 实时流式传输。

  2. HTML 5 视频不支持 RTSP。

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

可以混合 ffmpeg 和 websocket 吗?

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

在客户端机器上:

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

问题:

  1. 这是正确的方法吗?
  2. 如何从 ffmpeg 获取解码后的图像到浏览器中?

我可能在不同的地方错了。请提供输入。

【问题讨论】:

    标签: ffmpeg websocket activex webbrowser-control rtsp


    【解决方案1】:

    scandir.php(由viewcamera.php中的JS使用)

    <?php
    
    $folder = $_GET['name'];
    
    $dir = "../cache/".$folder;
    
    // Sort in descending order
    $b = scandir($dir,1);
    
    $myJSON = json_encode($b);
    
    echo $myJSON;
    
    ?>
    

    streamcam.php(运行在crontab

    <?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 &");
    
    }
    

    viewcamera.php - $camera_name 变量来自 SQL while 循环,其中对数据库中的所有摄像机重复以下操作。 var cameraName 如果从下面的按钮数据属性...

    <button
      style="font-size: 24px"
      class="btn2 fa fa-camera"
      id="<?php echo $image_id;?>"
      href="#<?php echo $camera_name_stripped;?>"
      data-toggle="modal"
      data-backdrop="false"
      data-keyboard="false"
      data-image-id="<?php echo $image_id;?>"
      data-camera-ip="<?php echo $ip;?>"
      data-camera-name="<?php echo $camera_name;?>"
      data-camera-name-stripped="<?php echo $camera_name_stripped;?>"
    >
      <i style="font-size: 24px" title="Live View"></i>
    </button>
    
     
    <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>
    

    【讨论】:

      【解决方案2】:

      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)
      

      【讨论】:

        【解决方案3】:

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

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

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

        jsmpegws ws WebSocket 包中安装node.jsstream-server.js 脚本。

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

        更新 SO topic 提出了另外两个可行的解决方案,带有

        【讨论】:

        • 这个支持音频吗?
        • 理论上确实如此。我会推荐 &lt;video&gt; 标签 solution 更好。
        • 我的意思是它是否支持流式传输视频的音频,只需使用视频标签? :)
        • 是的,&lt;video&gt; 标签支持两者;但您有责任准备相关信息流。
        • 我找不到 stream-server.js 脚本,你能否进一步解释一下,目前我用 nodejs 设置了一个本地 httpserver 并安装了 jsmpeg,谢谢
        【解决方案4】:

        如果您只想将其流式传输到极少数客户端,那么您可以使用直接运行 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 命令可能需要一些调整。

        【讨论】:

        【解决方案5】:

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

        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 {} \;
        

        希望能帮上忙! :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-08-08
          • 1970-01-01
          • 2021-12-22
          • 2021-12-31
          • 2018-03-12
          • 2020-03-22
          • 2019-10-24
          • 1970-01-01
          相关资源
          最近更新 更多