Node.js 服务器上的实时视频流
Live Video Stream on a Node.js Server
我对此进行了很多研究,但感到沮丧,因为我觉得解决方案 应该 简单,尽管我知道不会。理想情况下,我只想使用 node 来托管服务器,webrtc getusermedia 在本地客户端上获取实时流,并使用 socket.io 之类的东西将流发送到服务器,然后服务器将流广播到远程客户端;就好像它是一个简单的消息聊天应用程序。
再想一想,这种简单的方法似乎是不可能的,因为实时视频需要连续发送大量数据,这不等同于在事件发生后发送单个消息甚至文件(按下发送按钮)。
但是,也许我错了,实时视频流应用程序可以遵循与 node/socket.io 信使应用程序相同的结构吗?您会发送从 getUserMedia 返回的媒体对象、blob、一些二进制数据吗(我已经尝试了所有这些但可能不正确)。
理想的目标是应用尽可能少地使用 extra fluff,尽可能少地安装 npm,尽可能少地额外 javascript 库,或者很少担心encoding/decoding 或任何 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
尽量做到清晰具体。
首先,您在这里没有使用 WebRTC。 getUserMedia() 是 navigator WebAPI 的一部分,您可以使用它从相机获取媒体流。
使用 WebRTC 意味着您使用 ICE 和 STUN/TURN 服务器来发送信号。您将使用您的 host 服务器(节点)来指定 ICE 配置,识别每个用户并提供一种相互调用的方式。
如果你想通过你的主机流式传输它,你可能应该分块流式传输它并设置你自己的信号基础设施。您可以将 Stream API 与 socket io 一起使用以块(数据包)的形式传输数据。看这里Stream API(socket.io)
此外,您可以在此处查看 WebRTC + Socket.io 的实时示例:Socket.io | WebRTC Video Chat
您可以在这里找到更多信息:sending a media stream to Host server
我认为主题是关于 Node Server 以支持 Live Streaming 或 Video Chat ,它比你想象的要复杂得多,让我来说明一下。 直播和视频聊天都可以使用WebRTC,但直播不需要使用WebRTC .两者都需要一些 Node Server 来支持信号和流。
如果您想将相机发布为直播,并转发给成千上万的玩家,这就是所谓的直播。延迟不是很关键,一般3~10s就可以了。
如果你想和对方聊天,用你的相机,也转发给其他用户,这叫做视频聊天。 latency/lagging非常敏感,必须<400ms
,一般~200ms
.
完全不同,我们分开讨论。
直播
直播的关键是跨平台(H5和移动),流畅无缓冲,快速启动切换流。溪拱如下图:
Publisher ---> Server/CDN ---> Player
让我们谈谈播放器,HLS(LLHLS) 是一个主要的交付协议,它被广泛使用并且在 H5(PC 和移动)和移动(iOS 和 Android)中表现良好.唯一的问题是延迟大约是5~10s,甚至更大。因为它是基于文件的协议。
另外一个低延迟(3~5s)的协议也可以,它是HTTP-FLV,hls.js, and mobile by ijkplayer所有的PC-H5都支持它,一些CDN也支持这个协议。唯一的问题就是对mobile-H5不友好
对于播放器,WebRTC也可以播放流,它在PC-H5上运行良好Chrome。问题出在移动设备上,运行 WebRTC 原生播放器很难。除了复杂之外,您还需要一个信令服务器,用于交换 SDP。
对于发布商来说,这很复杂,因为它取决于您的客户:
- 如果是H5 publisher,只有WebRTC可用,所以你需要一个服务器来将WebRTC转换成播放器的协议。推荐SRS
- 如果是Native mobile publisher,推荐FFmpeg,有很多库和绑定。任何RTMP服务器都可以,一些节点服务器也可以。
- 如果是电视设备,可能使用SRT,你还需要一个服务器来隐蔽。再次推荐SRS。
归根结底,直播经济是基于C/C++,FFmpeg/WebRTC/SRS是C/C++写的,不过也有一些服务器是nodejs的,你可以找到通过像 nodejs rtmp
.
这样的协议
视频聊天
延迟是视频聊天最重要的特性,因此您必须为客户端(发布者和播放器)使用 WebRTC。
有不同的视频聊天服务器:
- 一个房间服务器,作为信号为客户端交换SDP,管理房间和用户,启动某些用户,或使麦克风静音等
- 一个SFU服务器(或MCU),为所有客户端提供媒体流。还有一些 SFU,比如 SRS、Janus 或 mediasoup.
- CDN:很少有CDN支持WebRTC服务器,但是QUIC正在发展为WebRTC的传输和HTTP/3,所以未来可能会更好。现在,您可以搜索一些 WebRTC 云服务。
正如我所说,构建WebRTC系统非常复杂,所以请您反复思考您的场景:您是真的需要WebRTC系统,还是只需要通过WebRTC发布直播?
如果不确定,请先尝试直播解决方案,它简单且稳定。
我对此进行了很多研究,但感到沮丧,因为我觉得解决方案 应该 简单,尽管我知道不会。理想情况下,我只想使用 node 来托管服务器,webrtc getusermedia 在本地客户端上获取实时流,并使用 socket.io 之类的东西将流发送到服务器,然后服务器将流广播到远程客户端;就好像它是一个简单的消息聊天应用程序。
再想一想,这种简单的方法似乎是不可能的,因为实时视频需要连续发送大量数据,这不等同于在事件发生后发送单个消息甚至文件(按下发送按钮)。
但是,也许我错了,实时视频流应用程序可以遵循与 node/socket.io 信使应用程序相同的结构吗?您会发送从 getUserMedia 返回的媒体对象、blob、一些二进制数据吗(我已经尝试了所有这些但可能不正确)。
理想的目标是应用尽可能少地使用 extra fluff,尽可能少地安装 npm,尽可能少地额外 javascript 库,或者很少担心encoding/decoding 或任何 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
尽量做到清晰具体。 首先,您在这里没有使用 WebRTC。 getUserMedia() 是 navigator WebAPI 的一部分,您可以使用它从相机获取媒体流。
使用 WebRTC 意味着您使用 ICE 和 STUN/TURN 服务器来发送信号。您将使用您的 host 服务器(节点)来指定 ICE 配置,识别每个用户并提供一种相互调用的方式。
如果你想通过你的主机流式传输它,你可能应该分块流式传输它并设置你自己的信号基础设施。您可以将 Stream API 与 socket io 一起使用以块(数据包)的形式传输数据。看这里Stream API(socket.io)
此外,您可以在此处查看 WebRTC + Socket.io 的实时示例:Socket.io | WebRTC Video Chat
您可以在这里找到更多信息:sending a media stream to Host server
我认为主题是关于 Node Server 以支持 Live Streaming 或 Video Chat ,它比你想象的要复杂得多,让我来说明一下。 直播和视频聊天都可以使用WebRTC,但直播不需要使用WebRTC .两者都需要一些 Node Server 来支持信号和流。
如果您想将相机发布为直播,并转发给成千上万的玩家,这就是所谓的直播。延迟不是很关键,一般3~10s就可以了。
如果你想和对方聊天,用你的相机,也转发给其他用户,这叫做视频聊天。 latency/lagging非常敏感,必须<400ms
,一般~200ms
.
完全不同,我们分开讨论。
直播
直播的关键是跨平台(H5和移动),流畅无缓冲,快速启动切换流。溪拱如下图:
Publisher ---> Server/CDN ---> Player
让我们谈谈播放器,HLS(LLHLS) 是一个主要的交付协议,它被广泛使用并且在 H5(PC 和移动)和移动(iOS 和 Android)中表现良好.唯一的问题是延迟大约是5~10s,甚至更大。因为它是基于文件的协议。
另外一个低延迟(3~5s)的协议也可以,它是HTTP-FLV,hls.js, and mobile by ijkplayer所有的PC-H5都支持它,一些CDN也支持这个协议。唯一的问题就是对mobile-H5不友好
对于播放器,WebRTC也可以播放流,它在PC-H5上运行良好Chrome。问题出在移动设备上,运行 WebRTC 原生播放器很难。除了复杂之外,您还需要一个信令服务器,用于交换 SDP。
对于发布商来说,这很复杂,因为它取决于您的客户:
- 如果是H5 publisher,只有WebRTC可用,所以你需要一个服务器来将WebRTC转换成播放器的协议。推荐SRS
- 如果是Native mobile publisher,推荐FFmpeg,有很多库和绑定。任何RTMP服务器都可以,一些节点服务器也可以。
- 如果是电视设备,可能使用SRT,你还需要一个服务器来隐蔽。再次推荐SRS。
归根结底,直播经济是基于C/C++,FFmpeg/WebRTC/SRS是C/C++写的,不过也有一些服务器是nodejs的,你可以找到通过像 nodejs rtmp
.
视频聊天
延迟是视频聊天最重要的特性,因此您必须为客户端(发布者和播放器)使用 WebRTC。
有不同的视频聊天服务器:
- 一个房间服务器,作为信号为客户端交换SDP,管理房间和用户,启动某些用户,或使麦克风静音等
- 一个SFU服务器(或MCU),为所有客户端提供媒体流。还有一些 SFU,比如 SRS、Janus 或 mediasoup.
- CDN:很少有CDN支持WebRTC服务器,但是QUIC正在发展为WebRTC的传输和HTTP/3,所以未来可能会更好。现在,您可以搜索一些 WebRTC 云服务。
正如我所说,构建WebRTC系统非常复杂,所以请您反复思考您的场景:您是真的需要WebRTC系统,还是只需要通过WebRTC发布直播?
如果不确定,请先尝试直播解决方案,它简单且稳定。