从MJPEG流中提取JPEG并通过WebSocket发布Base64编码的图像

4
我正在编写一个代理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编码字符串返回,同时返回缓冲区的剩余部分(包含下一个图像头)。

请参见http://stackoverflow.com/questions/4378909/how-to-save-a-mjpeg-stream-to-disk-c-net/24329113#24329113。 - Jay
1个回答

0

不知怎么的,我错过了Paparazzo.js——它很棒,为我节省了大量时间。基本上,在解析头部时有两个重要的事情需要知道。

首先,你需要知道最后一个头部行将是什么(我的是“X-Resource-Status: active”)。让我困惑的是,你需要使用\s而不是\r\n作为头部的结尾。所以你应该匹配类似这样的内容:

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

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

下一个棘手的部分是,您必须使用缓冲区将图像转换为base64(或任何其他格式)。因此,您不能只是获取刚刚解析出来的帧并调用.toString('base64')方法,而是必须使用new Buffer(image).toString('base64')方法。

以下是Paparazzo源代码的链接,以便更好地了解我正在谈论的内容:https://github.com/wilhelmbot/Paparazzo.js/blob/master/src/paparazzo.js


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接