在Node.js服务器上实时视频流传输

47

我已经做了很多研究,但感到沮丧,因为我觉得解决方案应该很简单,但我知道不是。理想情况下,我只想使用node来托管服务器,webrtc获取用户在本地客户端上的实时流,并使用类似socket.io的东西将流发送到服务器,然后服务器会将流广播到远程客户端;就像是一个简单的消息聊天应用程序。

再仔细考虑一下,这种简单的方法似乎是不可能的,因为直播视频需要连续发送大量的数据,这与发送单个消息甚至文件不相等(事件后发送按钮按下)。

也许我错了,直播视频流应用程序是否可以遵循与节点/ socket.io消息传递应用程序相同的结构?您会发送从getUserMedia返回的媒体对象,blob,某些二进制数据(我已经尝试了所有这些,但可能不正确)。

理想目标是使用最少的额外组件,npm安装尽可能少,尽可能少的额外JavaScript库,或者很少担心编码/解码或ICE或STUN到底是什么。这有可能吗,还是我要求太多了?

理想客户端

    var socket = io();
    var local = document.getElementById("local_video");
    var remote = document.getElementById("remote_video");

    // display local video
    navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(function(stream) {
      local.src = window.URL.createObjectURL(stream);
      socket.emit("stream", stream);
    }).catch(function(err){console.log(err);});

    // displays remote video
    socket.on("stream", function(stream){
      remote.src = window.URL.createObjectURL(stream);

    });

理想服务器

var app = require("express")();
var http = require("http").Server(app);
var fs = require("fs");
var io = require("socket.io")(http);

app.get('/', onRequest);
http.listen(process.env.PORT || 3000, function() {
    console.log('server started');
})

//404 response
function send404(response) {
    response.writeHead(404, {"Content-Type" : "text/plain"});
    response.write("Error 404: Page not found");
    response.end();
}

function onRequest(request, response) {
  if(request.method == 'GET' && request.url == '/') {
    response.writeHead(200, {"Content-Type" : "text/html"});
    fs.createReadStream("./index.html").pipe(response);
  } else {
    send404(response);
  }
}

io.on('connection', function(socket) {
  console.log("a user connected");
  socket.on('stream', function(stream) {
    socket.broadcast.emit("stream", stream);
  });
  socket.on('disconnect', function () {
    console.log("user disconnected");
  });
});

这是有问题的应用程序演示:https://nodejs-videochat.herokuapp.com/

这是在 Github 上的出问题代码:https://github.com/joshydotpoo/nodejs-videochat


1
请查看此链接:https://dev59.com/tFwY5IYBdhLWcg3wq5Ud#32349750 - Profstyle
@Profstyle,从您发布的Github链接中我所看到的是用于从视频中捕获单个帧并将其转换为视频?即使如此,它也使用了cpp文件,但可能仅是为了使其与本机相机配合使用,而不仅仅是使用webrtc的东西...我真的很想保持简单。 - joshy.poo
2个回答

22
尽量清晰明确。首先,这里不使用WebRTC。getUserMedia()导航器Web API的一部分,您正在使用它从相机获取媒体流。
使用WebRTC意味着您将使用ICE和STUN / TURN服务器进行信令传递。您将使用主机Server(Node)指定ICE配置、识别每个用户并提供彼此通话的方法。
如果您想通过主机进行流式传输,可能应该按块(streaming in chunks)流传输,并设置自己的信令基础设施。您可以使用Stream API及Socket IO来以数据块(数据包)方式流式传输数据。请参阅此处的Stream API(socket.io) 另外,您可以在此处检查WebRTC + Socket IO的实时示例: Socket.io | WebRTC Video Chat 您可以在此处找到更多信息:sending a media stream to Host server

谢谢你的纠正。你说,ICE和Stun/Turn服务器是用于信令的,我还没有好好研究过它们,所以如果其他方法失败了,我会去看一下;但是Socket.io不能用于信令吗? - joshy.poo
跟进问题,您所说的分块流式传输是指一次发送一部分实时视频,就像录制视频的一部分并发送它,并在下一个“部分”被“录制”时显示它。抱歉我只是想了解基础知识。 - joshy.poo
1
@joshy.poo 是的,它可以用于信令目的,并且您可以使用它轻松制作简单的文本聊天应用程序。您可以在此处查看链接(https://github.com/muaz-khan/WebRTC-Experiment/tree/master/socketio-over-nodejs) - Gaurav Chaudhary
是的,我知道我自己做了一个,如果我这么说的话,它看起来相当不错,;) ,但我的意思是,我是否可以通过使用socket.io作为我的信令服务器来绕过使用ICE配置(等等),并且我实际发送什么数据(流对象,blob等)? - joshy.poo
@joshy.poo 我已经修改了我的回答。是的,chunk意味着数据包,Stream API提供了管道机制来执行相同的操作。我没有使用socket.io进行视频流传输,所以无法帮助您实现! - Gaurav Chaudhary
这是一个非常好的演示。https://github.com/chenxiaoqino/getusermedia-to-rtmp - persec10000

7
我认为这个话题是关于Node服务器支持直播或视频聊天,这比你想象的要复杂得多,让我来说明一下。 直播和视频聊天都可以使用WebRTC,但不需要使用WebRTC进行直播。 两者都需要一些Node服务器来支持信令和流媒体。
如果您想将摄像头发布为实时流,并转发到许多像千名玩家一样的用户,这被称为直播。延迟并不是非常关键,通常3〜10秒就可以。
如果您想互相交谈,使用您的摄像头,也转发给其他用户,则称为视频聊天。延迟/延迟非常敏感,必须小于<400ms,通常为〜200ms
它们完全不同,让我们分别讨论它们。

直播

直播的关键是跨平台(H5和移动设备),无缓冲的流畅性,快速启动以在流之间切换。 流媒体结构如下:

Publisher ---> Server/CDN ---> Player

让我们谈谈播放器,HLS(LLHLS)是一种首选的传输协议,被广泛应用于H5(包括PC和移动设备)和移动端(包括iOS和Android)。唯一的问题是延迟大约为5~10秒,甚至更长。因为它是基于文件的协议。
对于Chrome浏览器,也可以使用hls.js播放HLS,通过MSE
另一个低延迟(3~5秒)的协议是HTTP-FLV,它被所有PC-H5(通过hls.js)和移动端(通过ijkplayer)支持,一些CDN也支持这个协议。唯一的问题是对移动H5不太友好。
对于播放器,WebRTC也可以播放流,在PC-H5上像Chrome一样的浏览器上效果很好。问题在于移动设备上,运行原生WebRTC播放器非常困难。除了复杂性之外,您还需要一个信令服务器,用于交换SDP。
对于发布者而言,它是复杂的,因为它取决于您的客户端:
- 如果是H5发布者,则只有WebRTC可用,因此您需要一个服务器将WebRTC转换为播放器使用的协议。 推荐使用SRS。 - 如果是本机移动设备发布者,则建议使用FFmpeg,有许多库和绑定。 任何RTMP服务器都可以,也可以使用一些node服务器。 - 如果是电视设备,则可能使用SRT,您还需要一个服务器进行转换。再次推荐使用SRS。
最终,直播经济基于C/C++,FFmpeg / WebRTC / SRS都是用C/C++编写的,但是也有一些通过nodejs编写的服务器,您可以通过协议查找,例如“nodejs rtmp”。
视频聊天
延迟是视频聊天中最重要的特性,因此您必须使用WebRTC作为客户端,无论是发布者还是播放器。

视频聊天有不同的服务器:

  • 房间服务器,用于交换客户端的SDP信令、管理房间和用户、踢出某些用户或静音麦克风等。
  • SFU服务器(或MCU),为所有客户端传输媒体流。还有一些SFU,如SRSJanusmediasoup
  • CDN:少数CDN支持WebRTC服务器,但QUIC正在开发作为WebRTC和HTTP/3的传输协议,因此未来可能会更好。现在,您可以搜索一些WebRTC云服务。

正如我所说,构建WebRTC系统非常复杂,请反复考虑您的场景:您真的需要一个WebRTC系统,还是只需要通过WebRTC发布实时流?

如果不确定,请先尝试实时流解决方案,它更简单和稳定。


如何使用SRS实现视频聊天(会议)Web应用程序? 我已经检查了SRS网站,但它对于视频聊天说“……正在进行中”。 - persec10000

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