一、搭建 Web 服务器
- 前面我们已经实现过,但是没有详细说HTTPS服务
- 首先需要引入了
express
库,它的功能非常强大,用它来实现 Web 服务器非常方便 - 同时还需要引入
HTTPS
服务,并让 Web 服务运行于 HTTPS 之上即可
var https = require('https');
var express = require('express');
var serveIndex = require('serve-index');
var app = express();
app.use(serveIndex('./public'));
app.use(express.static('./public'));
var options = {
key : fs.readFileSync('./cert/www.autofelix.cn.key'),
cert: fs.readFileSync('./cert/www.autofelix.cn.pem')
}
var https_server = https.createServer(options, app);
var io = socketIo.listen(https_server);
https_server.listen(443, '0.0.0.0');
二、实现信令系统
- 信令系统超级重要,直播系统中,由谁来发起呼叫、什么时间发 SDP 等各种操作都是由信令控制的
- 客户端命令︰
join
用户加入房间、leave
用户离开房间、message
端到端命令 - 服务端命令︰
joined
用户已加入、leaved
用户已离开、other_joined
其他用户已加入、bye其他用户已离开、full
房间已满 - 在初始时,客户端处于
init/leaved
状态,在该状态下用户只能发送 join 消息 - 服务端收到 join 消息后,会返回 joined 消息,此时客户端为 joined 状态
- 如果用户离开房间,那客户端又回到了初始状态
- 如果客户端收到
second user join
消息,则切换到 joined_conn
状态,该状态下可以进行通话 - 如果客户端收到
second user leave
消息,则切换到 joined_unbind
状态,该状态与 joined 状态基本一致

三、搭建 TURN 服务器
- 其中最重要的 TURN 服务。它有两个作用,一是提供 STUN 服务,客户端可以通过 STUN 服务获取自己的外网地址;二是提供数据中继服务
- 目前最著名的 TURN 服务器是由 Google 发起的开源项目
coturn
︰https://github.com/coturn/coturn - coturn 的编译安装与部署步骤如下︰
git clone https:
./configure --prefix=/usr/local/coturn
make && make install
listening-port=3478
external-ip=147.104.34.27
user=username:password
realm=stun.xxx.cn
四、视频直播之音视频数据的采集
- 第一步通过 getUserMedia 就可以获取到音视频数据
- 以前是在浏览器显示页面时就开始采集,而现在则是在用户点击
Connect Sig Server
按钮时才开始采集音视频数据 - 信令系统建立好后,后面的逻辑都是围绕着信令系统建立起来的,
RTCPeerConnection
对象也不例外 - 在客户端,用户要想与远端通话,首先要发送 join 消息,也就是要先进入房间,如果服务器判定用户是合法的,则会给客户端回 joined 消息
- 客户端收到 joined 消息后,就要创建 RTCPeerConnection 对象了,也就是要建立一条与远端通话的音视频数据传输通道
- 我们需要设置 TURN 服务器地址、用户名和密码,这样当 RTCPeerConnection 通过 P2P 建立连接失败时,就会使用 TURN 服务器进行数据中继
RTCPeerConnection
对象创建好后,我们要将前面获取的音视频数据与它绑定到一起,这样才能通过 RTCPeerConnection
对象将音视频数据传输出去
var pcConfig = {
'iceServers': [{
'urls': 'turn:stun.al.learningrtc.cn:3478',
'credential': "passwd",
'username': "username"
}]
};
function createPeerConnection(){
if(!pc){
pc = new RTCPeerConnection(pcConfig);
pc.ontrack = getRemoteStream;
}else {
console.log('the pc have be created!');
}
return;
}
function bindTracks(){
localStream.getTracks().forEach((track)=>{
pc.addTrack(track, localStream);
});
}
五、视频直播之音视频的渲染与播放
- 按照上面的步骤,音视频数据就可以被采集到了,
RTCPeerConnection
对象也创建好了,通过信令服务器也可以将各端的 Candidate
交换完成了 - 此时在 WebRTC 的底层就会进行连通性检测,它首先判断通信的双方是否在同一个局域网内
- 如果在同一个局域网内,则让双方直接进行连接
- 如果不在同一局域网内,则尝试用P2P 连接
- 如果仍然不成功,则使用 TURN 服务进行数据中继
- 一旦数据连通后,数据就从一端源源不断地传到了远端,此时远端只需要将数据与播放器对接,就可以看到对端的视频、听到对方的声音了
- 当数据流过来的时候会触发
RTCPeerConnection
对象的 ontrack
事件 - 只要我们侦听该事件,并在回调函数中将收到的
track
与 <video>
标签绑定到一起即可
var remoteVideo = document.querySelector('video#remotevideo');
pc = new RTCPeerConnection(pcConfig);
pc.ontrack = getRemoteStrea
function getRemoteStream(e){
remoteStream = e.streams[0];
remoteVideo.srcObject = e.streams[0];
}