【问题标题】:How do I detect a disconnect from an MJPEG stream in javascript如何在 javascript 中检测与 MJPEG 流的断开连接
【发布时间】:2013-09-21 14:09:16
【问题描述】:

我正在网页上显示来自 IP 摄像机的 MJPEG 流。流使用图像元素显示,由 jQuery 设置:

view = $('<img>');

view.load(function() {
     console.log('loaded');
});
view.error(function() {
     console.log('error');
});

view.attr('src', 'http://camera_ip/videostream.mjpeg');

当它们各自的情况发生时,这两个事件都会巧妙地触发。直到我断开相机。图像冻结(当然)。我想检测这种断开连接,向用户显示错误消息。我想出了一个解决方案,将与图像相隔几秒钟的帧复制到画布上,然后比较内容。

有更简单的选择吗?

【问题讨论】:

    标签: javascript jquery image jquery-events mjpeg


    【解决方案1】:

    我能想到在前端执行此操作的唯一方法是在您设置图像的 src 属性时创建一个 AJAX 请求。 AJAX 请求应该在 mjpeg 流结束时调用“完成”回调。

    如果您对 node.js 和/或 websockets 感到满意,您也可以设置一个 mjpeg 代理后端来提供 mjpeg 流,并在流结束时通过 websocket 向该客户端发出“关闭”事件。所以它看起来像这样(请记住,我仍然没有弄清楚 bufferToJPEG 如何从流中解析出单个 jpeg 帧):

    http.get('http://camera_ip/videostream.mjpeg', function(response) {
        var buffer = "";
    
        response.on('data', function(chunk) {
            buffer += chunk;
            clientSocket.emit('imageFrame', bufferToJPEG(buffer));
        });
        response.on('end', function() {
            clientSocket.emit('imageEnd');
        });
    });
    

    这个问题(我现在正试图在我自己的项目中处理)是你必须将 websocket 与每个图像请求相关联,或者在 mjpeg 流进入时从 mjpeg 流中发出原始 jpeg通过 websockets(您可以在前端使用数据 uris 渲染这些图像)。

    希望对您有所帮助——很抱歉让您等了这么久才得到回复。

    编辑:https://github.com/wilhelmbot/Paparazzo.js 看起来像是按照我上面描述的方式代理该图像的好方法。

    【讨论】:

      【解决方案2】:

      这是我在阅读 zigzackattack 答案后得出的结论。为了简单起见,我使用“datauri”包,但为了更精细地控制最终图像,我还成功地测试了“node-canvas”包。

      var mjpeg2jpegs = require('mjpeg2jpegs')
      const Datauri = require('datauri')
      
      var camURL = '/videostream.cgi?user=admin&pwd=password'
      var camPort = 81
      var camTimeout = 10000
      var FPS_DIVIDER = 1
      
      var options = {
        hostname: '192.168.1.241',
        port: camPort,
        path: camURL,
        timeout: camTimeout
      }
      
      function startCamStream (camName, options) {
        var http = require('http')
        var req = http.request(options, mjpeg2jpegs(function (res) {
          var data
          var pos = 0
          var count = 0
          res.on('imageHeader', function (header) {
          // console.log('Image header: ', header)
            data = new Buffer(parseInt(header['content-length'], 10))
            pos = 0
          })
          res.on('imageData', function (chunk) {
          // console.log('Image data: ', data.length)
            chunk.copy(data, pos)
            pos += chunk.length
          })
          res.on('imageEnd', function () {
          // console.log('Image end')
            if (count++ % FPS_DIVIDER === 0) {
              const datauri = new Datauri()
              datauri.format('.jpeg', data)
              socket.emit(camName, datauri.content) // Send the image uri via websockets. 
            }
          })
        })).on('timeout', function () {
          console.log('timeout')
          startCamStream(camName, options)
        }).end()
      }
      
      startCamStream('ipcam1', options)
      

      使用 vue.js(可选)我只是将图像 uri 与 img 标签嵌入。

      <img :src="ipcam1"  alt="ipcam1" />
      

      增加 FPS_DIVIDER 变量将减少 fps 输出。如果您想在超时时更改图像,则可以在到达“超时”回调时发送“离线”图像。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-16
        • 1970-01-01
        • 2012-11-03
        • 1970-01-01
        • 2018-04-25
        • 1970-01-01
        • 1970-01-01
        • 2019-06-23
        相关资源
        最近更新 更多