NodeJS – 如何pipe相同的videostream到多个客户端?

我们有一种情况试图为videostream服务。

由于HTML5video标签不支持udp组播,因此我们试图重新使用已经转换的ffmpegstream并将其发送给多个响应。 但是这不起作用。

第一个响应得到了正确的stream,但第二个响应没有。 似乎这个stream不能通过另一个响应pipe道,也不能被克隆。

有没有人做过? 有任何想法吗?

提前致谢!

代码如下:

var request = require('request'); var http = require('http'); var child_process = require("child_process"); var n = 1; var stdouts = {}; http.createServer(function (req, resp) { console.log("***** url ["+req.url+"], call "+n); if (req.url != "/favicon.ico" && req.url != "/") { var params = req.url.substring(1).split("/"); switch (params[0]) { case "VIEW": if (params[1] == "C2FLOOR1" || params[1] == "C2FLOOR2" || params[1] == "C2PORFUN" || params[1] == "C2TESTCAM") var camera = "rtsp://192.168.16.19:554/Inter/Cameras/Stream?Camera="+params[1]; else var camera = "http://192.168.16.19:8609/Inter/Cameras/GetStream?Camera="+params[1]; // Write header resp.writeHead(200, {'Content-Type': 'video/ogg', 'Connection': 'keep-alive'}); if (stdouts.hasOwnProperty(params[1])) { console.log("Getting stream already created for camera "+params[1]); var newStdout = Object.create(stdouts[params[1]]); newStdout.pipe(resp); } else { // Start ffmpeg var ffmpeg = child_process.spawn("ffmpeg",[ "-i",camera, "-vcodec","libtheora", "-qscale:v","7", // video quality "-f","ogg", // File format "-g","1", // GOP (Group Of Pictures) size "-" // Output to STDOUT ]); stdouts[params[1]] = ffmpeg.stdout; // Pipe the video output to the client response ffmpeg.stdout.pipe(resp); console.log("Initializing camera at "+camera); } // Kill the subprocesses when client disconnects /* resp.on("close",function(){ ffmpegs[params[1]].kill(); console.log("FIM!"); }); */ break; } } else { resp.writeHeader(200, {"Content-Type": "text/html"}); resp.write("WRONG CALL"); resp.end(); } n++; }).listen(8088); console.log('Server running at port 8088'); 

stream可以被认为是固定大小的队列 ,因为它们可以“缓冲”或存储某个预定义数量的数据,然后它们拒绝接受更多或者数据开始从stream的读取端落下; 它们可以被认为是按照“ 先进先出 ”( FIFO )顺序存储数据的队列。

写入stream使得数据可供所有stream的当前读取器(打开stream读取的实体)使用。

从stream中读取将从stream的一端删除固定数量的数据,释放另一端的空间以潜在地接受更多的数据。

一旦从数据stream中读取数据并且更多的数据被添加到数据stream以填充其缓冲器,那些已经被读取的数据就消失了。

Node.jsstream确实可以同时拥有多个读取器,每个读取器都有自己的指针指向stream的缓冲区,指示已经消耗了多less数据,但是如果在stream已经将数据刷新之后添加新的读取器其缓冲区,这些数据不再可用。

我相信,当后续请求尝试从stream中读取数据时,浏览器会超时,因为数据stream已用尽,并且从stream中读取的更多尝试正在等待,直到新数据可用。

从本质上看,你似乎正在尝试使用stream,就好像它们是长寿命的数据caching一样,事实并非如此。

您可以尝试增加stream的“高水位”,以便将整个videostream缓冲在内存中,这样后续读取器就可以从内存中读取整个数据stream而不会耗尽stream的缓冲区。 (请参阅节点的stream文档以了解如何增加stream的缓冲区大小。)

然而,我怀疑你会看到改善的反应,例如,增加操作系统的I / O缓冲区的大小或从内存或固态硬盘读取数据。

更新(每个评论)

如果您需要随着时间的推移向多个查看器提供一个或多个连续的(实时)video源,是否考虑以“stream动”模式创build和初始化video数据stream,并依靠它们发出的事件将数据传递给用户?

我想想

  • 在全局上下文中为每个实时馈送创build一个stream(以确保stream将在请求之间持续)以及“stream动”(或事件驱动)模式
  • 将新stream分配给唯一的feedName处的全局feeds
  • 设置一个Stream.end事件侦听器来重新初始化stream,如果Feed意外结束

然后在HTTP请求处理程序中

  • feedName feed中find请求的feed
  • 注册事件监听器
    1. Stream.readable – 确保有数据被读取
    2. Stream.data – 将数据传递给响应
    3. Stream.endhttp.ServerResponse.close – 正常注销前两个处理程序

我还设置了一个定时器来取消注册请求处理程序中设置的所有事件,并在数据不能在合理的时间内从stream中提供数据时向客户端发送适当的错误。

(“stream动”模式在node.js Stream文档中有描述。)