node.js - 从 MJPEG 流中提取 JPEG 并通过 websocket 发布 base64 编码图像

标签 node.js http header streaming mjpeg

我正在编写一个代理 mjpeg 视频流的应用程序。我认为从 mjpeg 服务器(我正在代理的服务器)推送的 mjpeg 中提取每一帧会很酷,对其进行 base64 编码并通过 websockets 发布帧以作为数据 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,该请求以一系列 block 响应,直到流结束(大约一分钟后)。

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 编码的字符串与缓冲区的剩余 block (包含下一个图像标题,打开)。

最佳答案

不知何故,我错过了 Paparazzo.js——它很棒,为我节省了大量时间。基本上,在解析 header 时需要了解两件重要的事情。

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

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

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

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

这是 Paparazzo 来源的链接,因此您可以更好地了解我在说什么:https://github.com/wilhelmbot/Paparazzo.js/blob/master/src/paparazzo.js

关于node.js - 从 MJPEG 流中提取 JPEG 并通过 websocket 发布 base64 编码图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19696549/

相关文章:

html - header 在 IE 7-8 中乱七八糟

scala - 使用 akka http,如何将请求 header 注入(inject)到服务器中的传入路由中?

javascript - Aerospike - 语法错误 : Unexpected token {

javascript - ElasticSearch - 按 : sorting and pagging 聚合/分组

node.js - 尽管变量位于同一个类中,TypeScript 仍无法找到 namespace

php - Http 文件上传 - 超过 25mb 的文件失败 - PHP 上传脚本

c++ - 从比特流中读取 uint16_t

javascript - 如何在socket.io中获取特定的cookie值

http - 让 Varnish 忽略带有 Cookie header 的请求

java - 请求头太大