什么是信令?
信令是指协调通信的过程。为了让 WebRTC 应用设置通话,其客户端需要交换以下信息:
- 用于打开或关闭通信的会话控制消息
- 错误消息
- 媒体元数据,例如编解码器、编解码器设置、带宽和媒体类型
- 用于建立安全连接的关键数据
- 网络数据,例如主机在外部世界中显示的 IP 地址和端口
此信令过程需要一种让客户端能够来回传递消息的方式。WebRTC API 未实现该机制。您需要自行构建。本文稍后将介绍如何构建信令服务。不过,首先您需要了解一些背景信息。
为什么 WebRTC 未定义信令?
为避免冗余并最大限度地提高与现有技术的兼容性,WebRTC 标准未规定信令方法和协议。JavaScript 会话建立协议 (JSEP) 概述了这种方法:
JSEP 的架构还避免了浏览器必须保存状态(即充当信令状态机)的情况。例如,如果每次重新加载网页时信号数据都会丢失,那么这将是一个问题。而是可以将信令状态保存在服务器上。

JSEP 需要对等方之间交换上述媒体元数据,即 offer 和 answer。出价和回答以会话描述协议 (SDP) 格式进行通信,如下所示:
v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…
想知道所有这些 SDP 乱码实际上意味着什么?不妨看看互联网工程任务组 (IETF) 示例。
请注意,WebRTC 的设计允许您在将 offer 或 answer 设置为本地或远程说明之前,通过修改 SDP 文本中的值来对其进行调整。例如,appr.tc 中的 preferAudioCodec()
函数可用于设置默认编解码器和比特率。使用 JavaScript 操作 SDP 有些麻烦,有人讨论过未来的 WebRTC 版本是否应改用 JSON,但坚持使用 SDP 也有一些优势。
RTCPeerConnection
API 和信令:Offer、Answer 和 Candidate
RTCPeerConnection
是 WebRTC 应用用来在对等设备之间创建连接并传输音频和视频的 API。
为了初始化此流程,RTCPeerConnection
需要执行两项任务:
- 确定本地媒体条件,例如分辨率和编解码器功能。这是用于 offer-and-answer 机制的元数据。
- 获取应用宿主的潜在网络地址,称为候选地址。
确定此本地数据后,必须通过信令机制与远程对等方交换该数据。
假设 Alice 试图呼叫 Eve。以下是完整的 offer/answer 机制,其中包含所有详细信息:
- Alice 创建了一个
RTCPeerConnection
对象。 - Alice 使用
RTCPeerConnection
createOffer()
方法创建 offer(一个 SDP 会话描述)。 - Alice 调用
setLocalDescription()
并提供她的出价。 - Alice 将 offer 序列化,并使用信令机制将其发送给 Eve。
- Eve 使用 Alice 的出价调用
setRemoteDescription()
,以便她的RTCPeerConnection
了解 Alice 的设置。 - Eve 调用
createAnswer()
,并为此调用传递一个本地会话描述(Eve 的回答)。 - Eve 通过调用
setLocalDescription()
将自己的回答设置为本地描述。 - 然后,Eve 使用信号机制将序列化后的答案发送给 Alice。
- Alice 使用
setRemoteDescription()
将 Eve 的回答设置为远程会话描述。
Alice 和 Eve 也需要交换网络信息。“寻找候选对象”这一表达式是指使用 ICE 框架查找网络接口和端口的过程。
- Alice 使用
onicecandidate
处理程序创建RTCPeerConnection
对象。 - 当候选网络变为可用时,系统会调用该处理程序。
- 在处理程序中,Alice 通过信令通道将字符串化的候选数据发送给 Eve。
- 当 Eve 从 Alice 收到候选消息时,她会调用
addIceCandidate()
将候选对象添加到远程对等设备描述中。
JSEP 支持 ICE Candidate Trickling,这允许主叫方在初始提议之后逐步向被叫方提供候选对象,并允许被叫方开始处理通话并建立连接,而无需等待所有候选对象到达。
为信令编写 WebRTC 代码
以下代码段是一个 W3C 代码示例,总结了完整的信令过程。该代码假定存在某种信号机制 SignalingChannel
。信令将在下文中详细讨论。
// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);
// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription(await pc.createOffer());
// send the offer to the other peer
signaling.send({desc: pc.localDescription});
} catch (err) {
console.error(err);
}
};
// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
// Don't set srcObject again if it is already set.
if (remoteView.srcObject) return;
remoteView.srcObject = event.streams[0];
};
// Call start() to initiate.
async function start() {
try {
// Get local stream, show it in self-view, and add it to be sent.
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
selfView.srcObject = stream;
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({desc, candidate}) => {
try {
if (desc) {
// If you get an offer, you need to reply with an answer.
if (desc.type === 'offer') {
await pc.setRemoteDescription(desc);
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
await pc.setLocalDescription(await pc.createAnswer());
signaling.send({desc: pc.localDescription});
} else if (desc.type === 'answer') {
await pc.setRemoteDescription(desc);
} else {
console.log('Unsupported SDP type.');
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
如需查看实际的 offer/answer 和候选交换流程,请参阅 simpl.info RTCPeerConnection,并查看单页视频聊天示例的控制台日志。如果您想了解更多信息,可以从 Google Chrome 中的 about://webrtc-internals 页面或 Opera 中的 opera://webrtc-internals 页面下载完整的 WebRTC 信令和统计信息转储。
对等发现
这是一种比较正式的问法,意思是“如何找到聊天对象?”
对于电话,您有电话号码和电话簿。对于在线视频聊天和即时通讯,您需要身份和状态管理系统,以及供用户发起会话的方式。WebRTC 应用需要一种方式,让客户端可以相互发出信号,表明它们想要发起或加入通话。
WebRTC 未定义对等方发现机制,因此我们不会在此处介绍相关选项。此流程非常简单,只需通过电子邮件或即时通讯应用发送网址即可。对于 Talky、tawk.to 和 Browser Meeting 等视频聊天应用,您可以通过分享自定义链接来邀请他人加入通话。开发者 Chris Ball 构建了一个有趣的无服务器 WebRTC 实验,让 WebRTC 通话参与者能够通过他们喜欢的任何消息传递服务(例如即时通讯、电子邮件或信鸽)交换元数据。
如何构建信令服务?
再次强调,WebRTC 标准未定义信令协议和机制。无论您选择哪种方式,都需要一个中间服务器来在客户端之间交换信令消息和应用数据。遗憾的是,Web 应用无法简单地向互联网喊出“帮我联系我的朋友!”
幸运的是,信令消息很小,并且大多在通话开始时交换。在测试中使用 appr.tc 进行视频聊天会话时,信令服务总共处理了大约 30-45 条消息,所有消息的总大小约为 10KB。
除了对带宽的要求相对较低之外,WebRTC 信令服务不会消耗太多处理资源或内存,因为它们只需要中继消息并保留少量会话状态数据,例如哪些客户端已连接。
从服务器向客户端推送消息
用于信令的消息服务需要是双向的:从客户端到服务器,以及从服务器到客户端。双向通信与 HTTP 客户端/服务器请求/响应模型相悖,但多年来,人们开发了各种变通方法(例如长轮询),以便将数据从在网络服务器上运行的服务推送到在浏览器中运行的网络应用。
最近,EventSource
API 已得到广泛应用。这会启用服务器发送的事件,即通过 HTTP 从 Web 服务器发送到浏览器客户端的数据。EventSource
专为单向消息传递而设计,但可以与 XHR 结合使用来构建用于交换信令消息的服务。信令服务通过 XHR 请求传递来自调用方的消息,方法是通过 EventSource
将消息推送给被调用方。
WebSocket 是一种更自然的解决方案,专为全双工客户端-服务器通信而设计,可同时双向传输消息。使用纯 WebSocket 或服务器发送事件 (EventSource
) 构建的信令服务的一个优势是,这些 API 的后端可以在各种 Web 框架上实现,这些框架对于 PHP、Python 和 Ruby 等语言的大多数 Web 托管软件包来说都很常见。
除了 Opera Mini 之外,所有新式浏览器都支持 WebSocket,更重要的是,所有支持 WebRTC 的浏览器(无论是在桌面设备上还是在移动设备上)也都支持 WebSocket。所有连接都应使用 TLS,以确保消息不会被截获(未加密),并减少代理遍历方面的问题。(如需详细了解 WebSocket 和代理穿越,请参阅 Ilya Grigorik 的高性能浏览器网络中的 WebRTC 章节。)
也可以通过让 WebRTC 客户端通过 Ajax 反复轮询消息传递服务器来处理信令,但这会导致大量冗余的网络请求,对于移动设备来说尤其成问题。即使会话已建立,对等互连方也需要轮询信令消息,以防其他对等互连方发生更改或终止会话。WebRTC Book 应用示例采用了此选项,并对轮询频率进行了一些优化。
规模信令
虽然信令服务每个客户端消耗的带宽和 CPU 相对较少,但热门应用的信令服务器可能必须以高并发级别处理来自不同位置的大量消息。流量很大的 WebRTC 应用需要能够处理相当大负载的信令服务器。您在此处未详细说明,但有多种选项可用于实现高容量、高性能的消息传递,包括:
可扩展消息传递和状态协议 (XMPP),最初称为 Jabber,是一种为即时通讯开发的协议,可用于信令(服务器实现包括 ejabberd 和 Openfire)。JavaScript 客户端(例如 Strophe.js)使用 BOSH 来模拟双向流式传输,但由于各种原因,BOSH 可能不如 WebSocket 效率高,并且出于相同的原因,可能无法很好地进行扩缩。)(顺便说一句,Jingle 是一种 XMPP 扩展,用于启用语音和视频功能。WebRTC 项目使用 libjingle 库(Jingle 的 C++ 实现)中的网络和传输组件。)
开源库,例如 ZeroMQ(TokBox 在其 Rumour 服务中使用)和 OpenMQ(NullMQ 使用 STOMP 协议通过 WebSocket 将 ZeroMQ 概念应用于 Web 平台)。
使用 WebSocket(不过可能会回退到长轮询)的商业云消息传递平台,例如 Pusher、Kaazing 和 PubNub(PubNub 还具有 WebRTC 的 API)。
商业 WebRTC 平台,例如 vLine
(开发者 Phil Leggetter 的实时 Web 技术指南提供了消息传递服务和库的完整列表。)
在 Node 上使用 Socket.io 构建信令服务
以下是一个简单 Web 应用的代码,该应用使用基于 Node 构建的 Socket.io 信令服务。Socket.io 的设计可让您轻松构建服务以交换消息,而且,由于它内置了“房间”概念,因此特别适合用于 WebRTC 信令。此示例并非旨在作为生产级信令服务进行扩展,但对于相对较少的用户来说,它很容易理解。
Socket.io 使用 WebSocket 并提供以下后备方案:AJAX 长轮询、AJAX 多部分流式传输、Forever Iframe 和 JSONP 轮询。它已移植到各种后端,但最广为人知的可能是本示例中使用的 Node 版本。
此示例中没有 WebRTC。它仅用于展示如何在 Web 应用中构建信令。查看控制台日志,了解当客户端加入房间并交换消息时会发生什么情况。此 WebRTC Codelab 提供了有关如何将此功能集成到完整的 WebRTC 视频聊天应用中的分步说明。
以下是客户 index.html
:
<!DOCTYPE html>
<html>
<head>
<title>WebRTC client</title>
</head>
<body>
<script src='/socket.io/socket.io.js'></script>
<script src='js/main.js'></script>
</body>
</html>
以下是客户端中引用的 JavaScript 文件 main.js
:
const isInitiator;
room = prompt('Enter room name:');
const socket = io.connect();
if (room !== '') {
console.log('Joining room ' + room);
socket.emit('create or join', room);
}
socket.on('full', (room) => {
console.log('Room ' + room + ' is full');
});
socket.on('empty', (room) => {
isInitiator = true;
console.log('Room ' + room + ' is empty');
});
socket.on('join', (room) => {
console.log('Making request to join room ' + room);
console.log('You are the initiator!');
});
socket.on('log', (array) => {
console.log.apply(console, array);
});
以下是完整的服务器应用:
const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2013);
const io = require('socket.io').listen(app);
io.sockets.on('connection', (socket) => {
// Convenience function to log server messages to the client
function log(){
const array = ['>>> Message from server: '];
for (const i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
socket.on('message', (message) => {
log('Got message:', message);
// For a real app, would be room only (not broadcast)
socket.broadcast.emit('message', message);
});
socket.on('create or join', (room) => {
const numClients = io.sockets.clients(room).length;
log('Room ' + room + ' has ' + numClients + ' client(s)');
log('Request to create or join room ' + room);
if (numClients === 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients === 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
socket.emit('emit(): client ' + socket.id +
' joined room ' + room);
socket.broadcast.emit('broadcast(): client ' + socket.id +
' joined room ' + room);
});
});
(您无需为此学习 node-static。只是恰好在此示例中使用了它。)
如需在本地主机上运行此应用,您需要安装 Node、Socket.IO 和 node-static。您可以从 Node.js 下载 Node(安装过程简单快捷)。如需安装 Socket.IO 和 node-static,请从应用目录中的终端运行 Node Package Manager:
npm install socket.io
npm install node-static
如需启动服务器,请在应用目录的终端中运行以下命令:
node server.js
在浏览器中,打开 localhost:2013
。在任意浏览器中打开新标签页或窗口,然后再次打开 localhost:2013
。如需查看发生了什么情况,请检查控制台。在 Chrome 和 Opera 中,您可以通过 Google Chrome 开发者工具使用 Ctrl+Shift+J
(或在 Mac 上使用 Command+Option+J
)访问控制台。
无论您选择哪种信号传递方法,您的后端和客户端应用至少需要提供与此示例类似的服务。
信令陷阱
- 在调用
setLocalDescription()
之前,RTCPeerConnection
不会开始收集候选对象。这是 JSEP IETF 草案中的强制要求。 - 利用 Trickle ICE。在候选对象到达后立即调用
addIceCandidate()
。
现成的信令服务器
如果您不想自行开发,可以使用多个 WebRTC 信令服务器,这些服务器使用 Socket.IO(如上例所示)并与 WebRTC 客户端 JavaScript 库集成:
- webRTC.io 是 WebRTC 的首批抽象库之一。
- Signalmaster 是一个信令服务器,专为与 SimpleWebRTC JavaScript 客户端库搭配使用而创建。
如果您不想编写任何代码,可以从 vLine、OpenTok 和 Asterisk 等公司获取完整的商业 WebRTC 平台。
值得一提的是,在 WebRTC 的早期,爱立信曾使用 Apache 上的 PHP 构建了一个信令服务器。虽然现在这种方法已经过时,但如果您考虑采用类似的方法,不妨看看相关代码。
信令安全性
“安全是一门让一切都无法发生的艺术。”
萨尔曼·拉什迪
对于所有 WebRTC 组件而言,加密是必需的。
不过,WebRTC 标准并未定义信令机制,因此您需要自行确保信令安全。如果攻击者设法劫持信令,他们就可以停止会话、重定向连接,以及记录、更改或注入内容。
确保信令安全的最重要因素是使用安全协议(例如 HTTPS 和 WSS [TLS]),以确保消息不会被截获(未加密)。此外,请注意不要以其他调用者可以使用相同信令服务器的方式广播信令消息。
发出信号后:使用 ICE 来应对 NAT 和防火墙
对于元数据信令,WebRTC 应用使用中间服务器,但对于实际的媒体和数据流式传输,一旦会话建立,RTCPeerConnection
会尝试直接或以对等方式连接客户端。
在简单的情况下,每个 WebRTC 端点都将具有一个唯一的地址,该地址可与其他对等方交换,以便直接通信。

实际上,大多数设备都位于一层或多层 NAT 后面,有些设备安装了会屏蔽特定端口和协议的杀毒软件,还有许多设备位于代理和公司防火墙后面。防火墙和 NAT 实际上可能由同一设备(例如家庭 Wi-Fi 路由器)实现。

WebRTC 应用可以使用 ICE 框架来克服实际网络中的复杂性。为了实现此目的,您的应用必须将 ICE 服务器网址传递给 RTCPeerConnection
,如本文中所述。
ICE 会尝试找到连接对等方的最佳路径。它会并行尝试所有可能性,并选择最有效的可行方案。ICE 首先尝试使用从设备的操作系统和网卡获取的主机地址建立连接。如果失败(对于位于 NAT 后面的设备,这种情况会发生),ICE 会使用 STUN 服务器获取外部地址,如果失败,流量会通过 TURN 中继服务器路由。
换句话说,STUN 服务器用于获取外部网络地址,而 TURN 服务器用于在直接(对等)连接失败时中继流量。
每个 TURN 服务器都支持 STUN。TURN 服务器是一种 STUN 服务器,具有额外的内置中继功能。ICE 还可以应对 NAT 设置的复杂性。实际上,NAT 穿孔可能需要的不只是公共 IP:端口地址。
STUN 和/或 TURN 服务器的网址由 WebRTC 应用在 RTCPeerConnection
构造函数的第一个实参(即 iceServers
配置对象)中指定(可选)。对于 appr.tc,该值如下所示:
{
'iceServers': [
{
'urls': 'stun:stun.l.google.com:19302'
},
{
'urls': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'urls': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
}
]
}
RTCPeerConnection
获得该信息后,ICE 魔法会自动发生。RTCPeerConnection
使用 ICE 框架来确定对等方之间的最佳路径,并根据需要与 STUN 和 TURN 服务器配合使用。
STUN
NAT 为设备提供可在专用本地网络中使用的 IP 地址,但此地址无法在外部使用。如果没有公共地址,WebRTC 对等互连就无法进行通信。为了解决此问题,WebRTC 使用 STUN。
STUN 服务器位于公共互联网上,其任务很简单,即检查来自 NAT 后运行的应用的传入请求的 IP:端口地址,并将该地址作为响应发送回去。换句话说,应用使用 STUN 服务器从公共角度发现其 IP:端口。此过程可让 WebRTC 对等方获取可公开访问的地址,然后通过信令机制将其传递给另一个对等方,以便建立直接链接。(实际上,不同的 NAT 以不同的方式工作,并且可能存在多个 NAT 层,但原理仍然相同。)
STUN 服务器无需执行太多操作或记住太多信息,因此配置相对较低的 STUN 服务器也能处理大量请求。
根据 Webrtcstats.com 的数据,大多数 WebRTC 通话都能使用 STUN 成功建立连接(成功率为 86%),但对于防火墙后和复杂 NAT 配置后的对等设备之间的通话,成功率可能会降低。

TURN
RTCPeerConnection
尝试通过 UDP 在对等方之间建立直接通信。如果失败,RTCPeerConnection
会改用 TCP。如果失败,则可以使用 TURN 服务器作为后备方案,在端点之间中继数据。
再次强调,TURN 用于在对等方之间中继音频、视频和数据流,而不是信令数据!
TURN 服务器具有公共地址,因此即使对等方位于防火墙或代理后面,也可以联系到 TURN 服务器。TURN 服务器的任务在概念上很简单,即中继数据流。不过,与 STUN 服务器不同的是,TURN 服务器本身会消耗大量带宽。换句话说,TURN 服务器需要更强大。

此图显示了 TURN 的实际运作情况。纯 STUN 未成功,因此每个对等方都改用 TURN 服务器。
部署 STUN 和 TURN 服务器
为了进行测试,Google 运行了一个公共 STUN 服务器 stun.l.google.com:19302,appr.tc 使用了该服务器。对于生产 STUN/TURN 服务,请使用 rfc5766-turn-server。GitHub 上提供了 STUN 和 TURN 服务器的源代码,您还可以在其中找到指向多个服务器安装信息来源的链接。此外,我们还提供 Amazon Web Services 的虚拟机映像。
另一种 TURN 服务器是 restund,它以源代码的形式提供,也可用于 AWS。以下说明介绍了如何在 Compute Engine 上设置 restund。
- 根据需要打开防火墙,以允许 tcp=443、udp/tcp=3478。
- 创建四个实例,每个实例对应一个公共 IP 地址,并使用标准 Ubuntu 12.06 映像。
- 设置本地防火墙配置(允许来自任何来源的任何流量)。
- 安装工具:
shell sudo apt-get install make sudo apt-get install gcc
- 从 creytiv.com/re.html 安装 libre。
- 从 creytiv.com/restund.html 获取 restund 并解压缩。
wget
hancke.name/restund-auth.patch 并使用patch -p1 < restund-auth.patch
应用。- 针对 libre 和 restund 运行
make
、sudo make install
。 - 根据您的需求调整
restund.conf
(替换 IP 地址并确保其中包含相同的共享密钥),然后将其复制到/etc
。 - 将
restund/etc/restund
复制到/etc/init.d/
。 - 配置 restund:
- 设置
LD_LIBRARY_PATH
。 - 将
restund.conf
复制到/etc/restund.conf
。 - 将
restund.conf
设置为使用正确的 10。IP 地址。
- 设置
- 运行 restund
- 使用远程计算机上的 stund 客户端进行测试:
./client IP:port
超越一对一:多方 WebRTC
您可能还想看看 Justin Uberti 针对 REST API(用于访问 TURN 服务)提出的 IETF 标准。
不难想象,媒体流式传输的应用场景远不止简单的一对一通话。例如,一群同事之间的视频会议,或者一位演讲者和数百万观众参与的公开活动。
WebRTC 应用可以使用多个 RTCPeerConnection,以便每个端点都以网状配置连接到其他每个端点。talky.io 等应用就采用了这种方法,并且在少量同伴的情况下效果非常好。除此之外,处理和带宽消耗也会过高,尤其是对于移动客户端。

或者,WebRTC 应用可以选择一个端点,以星形配置将视频流分发给所有其他端点。您还可以在服务器上运行 WebRTC 端点,并构建自己的重新分发机制(webrtc.org 提供了一个示例客户端应用)。
自 Chrome 31 和 Opera 18 起,一个 RTCPeerConnection
的 MediaStream
可用作另一个 RTCPeerConnection
的输入。这可以实现更灵活的架构,因为 Web 应用可以通过选择要连接到的其他对等方来处理通话路由。如需查看实际效果,请参阅 WebRTC 示例对等连接中继和 WebRTC 示例多个对等连接。
多点控制单元
对于大量端点,更好的选择是使用多点控制单元 (MCU)。这是一种充当桥梁的服务器,用于在大量参与者之间分发媒体。MCU 可以处理视频会议中的不同分辨率、编解码器和帧速率;处理转码;进行选择性视频流转发;以及混合或录制音频和视频。对于多人通话,需要考虑许多问题,尤其是如何显示多个视频输入源以及如何混合来自多个来源的音频。vLine 等云平台也会尝试优化流量路由。
您可以购买完整的 MCU 硬件软件包,也可以自行组装。

有多种开源 MCU 软件可供选择。例如,Licode(以前称为 Lynckia)为 WebRTC 生成了一个开源 MCU。OpenTok 具有 Mantis。
除了浏览器之外:VoIP、电话和即时通讯
WebRTC 的标准化特性使得在浏览器中运行的 WebRTC 应用与在其他通信平台(例如电话或视频会议系统)上运行的设备或平台之间建立通信成为可能。
SIP 是 VoIP 和视频会议系统使用的信令协议。为了在 WebRTC Web 应用与 SIP 客户端(例如视频会议系统)之间实现通信,WebRTC 需要一个代理服务器来中介信令。信令必须通过网关,但一旦建立通信,SRTP 流量(视频和音频)就可以直接在对等方之间流动。
公共交换电话网 (PSTN) 是所有“普通”模拟电话的电路交换网络。对于 WebRTC Web 应用与电话之间的通话,流量必须通过 PSTN 网关。同样,WebRTC Web 应用需要一个中间 XMPP 服务器才能与 Jingle 端点(例如即时通讯客户端)通信。Jingle 由 Google 开发,是 XMPP 的扩展,可为消息服务启用语音和视频功能。目前的 WebRTC 实现基于 C++ libjingle 库,这是最初为 Talk 开发的 Jingle 实现。
许多应用、库和平台都利用了 WebRTC 与外部世界通信的能力:
- sipML5:一个开源 JavaScript SIP 客户端
- jsSIP:JavaScript SIP 库
- Phono:作为插件构建的开源 JavaScript 电话 API
- Zingaya:可嵌入的电话微件
- Twilio:语音和消息传递
- Uberconference:会议
sipML5 开发者还构建了 webrtc2sip 网关。Tethr 和 Tropo 展示了一个“公文包中的灾难通信”框架,该框架使用 OpenBTS 基站,通过 WebRTC 实现功能手机和计算机之间的通信。这是一种无需运营商的电话通信方式!
了解详情
WebRTC Codelab 提供了有关如何使用在 Node 上运行的 Socket.io 信令服务构建视频和文字聊天应用的分步说明。
2013 年 Google I/O 大会上的 WebRTC 演示,由 WebRTC 技术主管 Justin Uberti 主讲
Chris Wilson 的 SFHTML5 演示文稿 - WebRTC 应用简介
这本 350 页的图书 WebRTC: APIs and RTCWEB Protocols of the HTML5 Real-Time Web 详细介绍了数据和信令路径,并包含许多详细的网络拓扑图。
WebRTC 和信令:两年来我们学到了什么 - TokBox 博文,介绍了为什么将信令排除在规范之外是个好主意
Ben Strong 的《A Practical Guide to Building WebRTC Apps》(WebRTC 应用构建实用指南)提供了有关 WebRTC 拓扑和基础架构的丰富信息。
Ilya Grigorik 的《高性能浏览器网络》一书中的 WebRTC 章节深入探讨了 WebRTC 架构、应用场景和性能。