我正在编写代理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编码的字符串以及缓冲区的剩余块(包含该块的位)返回下一个图像标题,开启。
答案 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