从MJPEG流中提取JPEG,并在websocket上发布base64编码的图像

时间:2013-10-31 00:50:27

标签: node.js http header streaming mjpeg

我正在编写代理mjpeg视频流的应用程序。我认为从mjpeg服务器(我代理的服务器)推送的mjpeg中提取每个帧会很酷,base64对它进行编码并在websockets上发布框架以作为data-uri图像呈现前端。这样,不支持mjpeg的客户端就能够将实时视频视为一系列图像。

问题在于我无法弄清楚如何从MJPEG边界之间提取jpeg数据。这是边界(以及标题)的样子:

--------JPEG_FRAME_BOUNDARY
Content-Type: image/jpeg
Content-Length: 33377
X-Frame-Epoc-HiRes: 1383166748.031929
X-Frame-Timestamp: 2013-10-30T20:59:08.031929Z
X-Resource-Status: active

在这些边界和标题的两边是一堆乱码数据,我假设是一个原始的jpeg图像。

我正在使用一个http请求获取mjpeg,该请求以一系列块响应,直到流结束(大约一分钟后)。

var boundary = extractBoundary(response.headers['content-type'])
  , buffer   = [];

response.on('data', function(chunk) {
    buffer.push(chunk);

    var frames = getFrames(buffer, boundary);

    if(frames[0]) {
        camera.set('data', "data:image/jpeg;base64," + frames[0]);
    }
    if(frames[1]) {
        buffer = [new Buffer(frames[1])];
    }
});

response.on('end', function() {
    console.log('done');
});

现在我只需要弄清楚“getFrames”必须做什么来检查缓冲区是否包含完整的图像,然后将该图像作为base64编码的字符串以及缓冲区的剩余块(包含该块的位)返回下一个图像标题,开启。

1 个答案:

答案 0 :(得分:0)

所以不知怎的,我错过了Paparazzo.js - 这太棒了,节省了我很多时间。基本上,解析标题时需要了解两件重要的事情。

首先,你需要知道最后一个标题行是什么(我的是“X-Resource-Status:active”)。让我绊倒的是你需要使用\ s而不是\ r \ n作为标题的结尾。所以你应该匹配这样的东西:

var headerEnd = remaining.match(/X-Resource-Status: active\s+/);

您基本上循环遍历流中的块接收并找到最后一个头的结尾的索引。您从最后一个头的端点开始获取一个子字符串,然后等到再次调用该处理程序以找到下一个头的开头。

下一个棘手的问题是你必须使用缓冲区将图像转换为base64(或任何其他格式)。因此,不必采用刚刚解析出的框架并在其上调用.toString('base64'),而是必须执行新的Buffer(image).toString('base64')。

以下是Paparazzo资源的链接,以便您更好地了解我所说的内容:https://github.com/wilhelmbot/Paparazzo.js/blob/master/src/paparazzo.js