通过Node.js代理将MJPEG流传输管道化

8
在linux上使用Motion,每个网络摄像头都会作为一个单独的流在其自己的端口上提供。现在我想使用Node.js将这些流全部在同一个端口上提供。
  • 编辑:此解决方案现已可行。我需要从原始的MJPEG流中获取边界字符串(在我的Motion配置中是“BoundaryString”)

app.get('/motion', function(req, res) {
var boundary = "BoundaryString";
var options = { // 要转发到的主机 host: '192.168.1.2', // 要转发到的端口 port: 8302, // 要转发到的路径 path: '/', // 请求方法 method: 'GET', // 发送的标头 headers: req.headers };
var creq = http.request(options, function(cres) {
res.setHeader('Content-Type', 'multipart/x-mixed-replace;boundary="' + boundary + '"'); res.setHeader('Connection', 'close'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Cache-Control', 'no-cache, private'); res.setHeader('Expires', 0); res.setHeader('Max-Age', 0);
// 等待数据 cres.on('data', function(chunk){ res.write(chunk); });
cres.on('close', function(){ // 关闭,同时结束客户端请求 res.writeHead(cres.statusCode); res.end(); });
}).on('error', function(e) { // 出现错误,向客户端返回500错误并记录错误 console.log(e.message); res.writeHead(500); res.end(); });
creq.end();
});
我认为这样服务于192.168.1.2:8302的MJPEG流将被提供为/motion,但实际上并没有。也许是因为它永远不会结束,并且这个代理示例并不是一个真正的流示例?

你可以考虑使用nginx。 - david
2
它需要是一个节点解决方案。 - Jelle De Loecker
2个回答

2
通过HTTP进行流传输并不是问题。我经常使用Node进行这样的操作。我认为你遇到的问题是没有向客户端发送内容类型头。实际上,你直接写入数据而没有发送任何响应头。
确保在发送任何实际内容数据之前,向发出请求的客户端发送正确的内容类型头。
如果Node的HTTP客户端没有为您处理多部分响应,则可能需要处理{{link1:multipart responses}}。
此外,我建议使用Wireshark进行调试,以便您可以看到正在发送和接收的内容。这将帮助您快速缩小此类问题。
我还应该指出,一些客户端可能会遇到分块编码的问题。如果您没有指定内容长度(因为它是不确定的),Node 将发送分块编码。如果您需要禁用分块编码,请参见我的答案:https://dev59.com/cGgu5IYBdhLWcg3wGTSd#11589937 基本上,您只需禁用它:response.useChunkedEncodingByDefault = false;。但不要随意这样做!确保在头部中使用Connection: close

“chunk-thing” 对于 mjpeg 流确实是个问题。我发现正常的 jpeg 流总是作为一个整体部分提供的。因此,我应该等待整个帧并且只有在完整的帧可用时才将其发送给客户端。 - Jelle De Loecker
1
啊,找到了! 我需要在响应头中设置原始mjpeg流中使用的多部分边界(在动态中,它始终是相同的“ BoundrayString”)这样我就可以转发块而不必自己添加任何数据。 - Jelle De Loecker

0
你需要做的是在一个线程中请求MJPEG流,只有在必要时才进行响应,并向每个客户端提供MJPEG或JPEG(如果需要支持IE)。

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