1 STUN/TURN 服务器搭建
1.1 STUN/TURN 服务器选型
rfc5766-turn-servercoTurnResTurn
1.2 coTurn 服务器搭建与布署
下载 coTurn
https://github.com/coturn/coturn./configure --prefix=/usr/local/coturnmake -j 4sudo make install
1.3 coTurn 服务器配置

1.4 启动 coTurn 服务器
ps -ef | grep turn/usr/local/coturn/bin/turnserver -c /usr/local/coturn/etc/turnserver.conf.defaulthttps://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
2 RTCPeerConnection
2.1 基本格式
pc = new RTCPeerConnection([configuration]);
2.2 configuration 可选

2.2.1 bundlePolicy
Balanced: 音频与视频轨使用各自的传输通道
max-compat: 每个轨使用自己的传输通道
max-bundle: 都绑定到同一个传输通道
2.2.2 certificates
授权可以使用连接的一组证书
2.2.3 iceCandidatePoolSize
16位的整数值,用于指定预取的ICE候选者的个数。
如果该值发生变化,它会解发重新收集候选者
2.2.4 iceTransportPolicy
指定ICE传输策略
relay: 只使用中继候选者
all: 可以使用任何类型的候选者
2.2.5 iceServers
其由 RTCIceServer组成。
每个RTCIceServer都是一个ICE代理的服务

2.2.6 rtcpMuxPolicy
该选项在收集ICE候选者的使用

2.3 addIceCandidate
2.3.1 基本格式
aPromise=pc.addIceCandidate(candidate);
2.3.2 candidate

3 真正的音视频传输
3.1 客户端信令消息
join 加入房间leave 离开房间message 端到端消息
3.2 端到端信令消息
Offer 消息Answer 消息Candidate 消息
3.3 服务端信令消息
joined 已加入房间otherjoin 其它用户加入房间full 房间人数已满leaved 已离开房间bye 对方已离开房间
3.4 直播系统消息处理流程

4 信令服务器改造
'use strict'var http = require('http');
var https = require('https');
var fs = require('fs');var express = require('express');
var serveIndex = require('serve-index');var socketIo = require('socket.io');var USERCOUNT = 3;var log4js = require('log4js');
log4js.configure({appenders: {console: {type: 'console'},log: {type: 'file',filename: 'log.log',maxLogSize: 1024,backups: 3,compress: true}},categories: {default: {appenders: ['console', 'log'],level: 'debug'}}
})var logger = log4js.getLogger();var app = express();
app.use(serveIndex('./public'));
app.use(express.static('./public'))var http_sever = http.createServer(app);
http_sever.listen(80, '0.0.0.0');var options = {key: fs.readFileSync('./cert/key.pem'),cert: fs.readFileSync('./cert/cert.pem')
};var https_server = https.createServer(options, app);var io = socketIo.listen(https_server);io.sockets.on('connection', (socket)=> { console.log('connection');socket.on('message', (room, data)=> {socket.to(room).emit('message', room, data);});socket.on('join', (room)=> {socket.join(room);var my_room = io.sockets.adapter.rooms[room];var users = my_room ? Object.keys(my_room.sockets).length:0;logger.debug('the number of user in room is: ' + users);if (users < USERCOUNT){socket.emit('joined', room, socket.id);if (users > 1){socket.to(room).emit('othersjoin', room);} }else{socket.leave(room);socket.emit('full', room, socket.id);}// socket.emit('joined', room, socket.id);//socket.to(room).emit('joined', room, socket.id); // 除自己之外 所有 人// io.in(room).emit('joined', room, socket.