(译)WebRTC实战: STUN, TURN, Signaling

http://xiaol.me/2014/08/24/webrtc-stun-turn-signaling/javascript

 

原文:WebRTC in the real world: STUN, TURN and signaling By Sam Duttonphp

WebRTC 实现了网页点对点交流。
可是…
WebRTC 仍然须要服务器来:css

  • 交换客户端元数据协调通信,即信令(Signaling)。
  • 应对NATs(Network Address Translators) 和防火墙。

本文将向你展现如何创建一个信令服务器,并使用STUN和TURN服务器来处理实际应用中出现的一些怪异的链接问题。也将解释WebRTC应用是如何处理多方通信并与相似VoIP、PSTN的服务互动的。html

若是你没有了解过WebRTC,我强烈建议你在看这篇文章以前先看看这篇文章 Getting Started With WebRTC
html5

什么是信令?

信令即协调通信的过程。WebRTC应用要发起一个对话,客户端就须要交换以下信息:java

  • 用于打开和关闭通信的会话信息;
  • 错误信息;
  • 媒体元数据如编解码器及其设置,带宽和媒体类型;
  • 秘钥数据,用于建立安全链接;
  • 网络数据,如外部能访问的主机IP和端口。

这个信令过程须要客户端之间能来回传递消息,可是WebRTC APIs并无提供这种机制的实现,你须要本身建立。下面将描述创建信令服务器的几种方式。无论怎么样,先来点上下文吧…node

为何WebRTC不提供信令实现?

为了不冗余,以及作到与现有技术的最大兼容,信令方法和协议都不禁WebRTC标准来指定。这些都由JSEP(JavaScript Session Establishment Protocol)来概述.python

WebRTC呼叫创建背后的想法已是彻底指定和控制媒体连接,可是尽可能托管和应用间的信令链接。
由是不一样的应用可能会喜欢用不一样的协议,好比已存在的SIP、Jungle信令协议,或者也许为了一些新奇的用例而作的特殊应用而自定义的协议。
这一节文字要传达的关键信息点是多媒体会话的描述,这个描述指定了必要的传输和创建媒体连接所必要的媒体配置信息。git

JSEP的架构也避免了让浏览器去保存状态,那就是,像一个信令状态机同样工做。这里也许会有一个问题,好比,当页面被刷新时,信令数据会丢失。不过,也能够把这些信令状态存在服务器。github

alt

JSEP architecture

JSEP须要offer和answer之间作出以前提到的媒体元数据的信息交换。offer和answer经过Session Description Protocol(SDP)格式来沟通,以下

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
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 examples.
请记住WebRTC被设计使得offer或answer能够在被拧在一块儿以前经过编辑SDP文原本设置好本地或远程描述。好比apprtc.appspot.com中的preferAudioCodec()方法就被用于设置默认的编解码器和比特率。SDP用JavaScript来操做是有点痛苦,因此如今有个讨论是关于WebRTC的将来版本是否能够用JSON格式来替代,不过这里提到了一些坚持使用SDP的好处

RTCPeerConnection + 信令: offer, answer and candidate

RTCPeerConnection接口被WebRTC应用用于建立各点之间的链接并交流视音频信息。
要开始这个过程RTCPeerConnection须要先作两个工做:

  • 肯定本地媒体状况,好比分辨率和编解码器的能力。这些元数据会用在offeranswer机制中。
  • 获取可能的应用主机网络地址,就死所谓的candidate。

当本地信息被确认后,就会经过信令系统与远程终端进行交换。
联想下alice is trying to call Eve这幅漫画,发起/响应机制在其中完整的展示出来:

  • Alice建立一个RTCPeerConnection对象。
  • Alice经过RTCPeerConnection的createOffer()方法建立一个offer(SDP会话描述)。
  • Alice经过这个offer调用setLocalDescription()。
  • Alice将offer字符串化并经过信令服务器发给Eve。
  • Eve经过调用setRemoteDescription()设置Alice的offer,来让本身的RTCPeerConnection知道Alice的设置。
  • Eve调用createAnswer()和成功回调函数来传递Eve的本地会话描述—answer。
  • Eve经过setLocalDescription()来将她的本地描述设置到她的answer中。
  • 而后Eve将她字符串化后的answer经过信令服务器发回给Alice。
  • Alice经过setRemoteDescription()将Eve的anwser设置为远程会话描述。

Alice和Eve还须要交换网络信息。’finding candidates’就是经过ICE框架找到网络连接和端口的过程。

  • Alice 经过onicecandidate事件处理器来建立RTCPeerConnection对象。
  • 这个事件处理器将在candidates可用时被调用。
  • 在这个处理器中,Alice经过信令服务器将candidate数据字符串化后发送给Eve。
  • 当Eve获得Alice的candidate信息,她将调用addIceCandidate()方法将这个candidate加入本身的远程终端描述中。
    JSEP支持ICE Candidate Trickling, 这个可使呼叫者在初始化offer以后增量的提供candidates给被呼叫者,被呼叫者在这个呼叫中直接开始设置连接而不用等待收到其余candidates。
编写WebRTC信令服务

下面是一个简略的信令过程W3C代码示例。这片代码假设已经存在一些信令机制,如SignalingChannel. 下面讨论信令的一些详细细节。

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 
var signalingChannel = new SignalingChannel(); var configuration = {  'iceServers': [{  'url': 'stun:stun.example.org'  }] }; var pc;  // call start() to initiate  function start() {  pc = new RTCPeerConnection(configuration);   // send any ice candidates to the other peer  pc.onicecandidate = function (evt) {  if (evt.candidate)  signalingChannel.send(JSON.stringify({  'candidate': evt.candidate  }));  };   // let the 'negotiationneeded' event trigger offer generation  pc.onnegotiationneeded = function () {  pc.createOffer(localDescCreated, logError);  }   // once remote stream arrives, show it in the remote video element  pc.onaddstream = function (evt) {  remoteView.src = URL.createObjectURL(evt.stream);  };   // get a local stream, show it in a self-view and add it to be sent  navigator.getUserMedia({  'audio': true,  'video': true  }, function (stream) {  selfView.src = URL.createObjectURL(stream);  pc.addStream(stream);  }, logError); }  function localDescCreated(desc) {  pc.setLocalDescription(desc, function () {  signalingChannel.send(JSON.stringify({  'sdp': pc.localDescription  }));  }, logError); }  signalingChannel.onmessage = function (evt) {  if (!pc)  start();   var message = JSON.parse(evt.data);  if (message.sdp)  pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {  // if we received an offer, we need to answer  if (pc.remoteDescription.type == 'offer')  pc.createAnswer(localDescCreated, logError);  }, logError);  else  pc.addIceCandidate(new RTCIceCandidate(message.candidate)); };  function logError(error) {  log(error.name + ': ' + error.message); } 

要知道这片代码中offer/answer和candidate交换过程是如何运做的,能够看看simpl.info/pc 中视频聊天示例的控制台记录。若是你须要跟多细节,能够下载完整的WebRTC信令转储,并经过Chrome的 chrome://webrtc-internals 或Opera的 opera://webrtc-internals 页面来统计。

终端的发现

要说清楚’我怎么才能找到某人来聊天’挺复杂的。
对于电话来讲,咱们有电话号码目录。对于在线视频聊天,咱们须要身份认证以及在线状态管理系统,即用户初始化会话。WebRTC应用须要一种方式来让客户端来互相标识他们是像建立一个聊天室仍是加入一个聊天。

WebRTC没有提供终端目录机制,因此咱们不会进入这一项。这个过程能够简单的经过邮件或信息分享一个URL,好比 talky.iotawk.com 和 browsermeeting.com这些视频聊天应用中,你邀请别人加入是经过跟他们分享你的自有连接。开发者Chris Ball建立了一个有趣的实验serverless-webrtc让WebRTC的参与者经过IM,email或者信鸽来交换元数据。

要如何创建一个信令服务器?

 

重申一下,信令协议及机制并不禁WebRTC标准定义。无论你选择什么,你都须要一个中介服务器来交换客户端之间的信令信息和应用数据。很惋惜,网页应用并不能简单的直接冲着英特网说’把我和个人朋友连起来!’.

还好信令信息很小,而且大多数只在一个呼叫的开始才须要交换.在对apprtc.appspot.comsamdutton-nodertc.jit.su测试中咱们发现,一个视频聊天会话中,信令服务器总共处理了30-45条消息,全部消息的总大小才10kb左右。

而且对带宽的要求也较低,WebRTC信令服务器并不消耗太多cpu或内存,由于它们只须要作消息中转,并保存少许的会话状态数据(例如,有哪些客户已经链接了)。

Tip!
信令机制能够用来交换会话元数据,也能够用来作应用数据通信。它就是一个消息服务器。

从服务器推送消息到客户端

信令的消息服务须要是双向的:客户端发到服务器且服务器发到客户端。双向通信违反了HTTP协议的客户/服务,请求/响应模型。不过一些hack,好比为了将数据从服务器推送到网页的长轮询)已经出现不少年了。

最近,EventSource API已被普遍的应用了,他使得服务器经过HTTP发送数据到浏览器成为可能。这里有个简单的demo。EventSource被设计成单向传递消息,可是它能够和XHR结合构建成交换信令消息的服务器:一个从呼叫者开始传递消息,用XHR请求传输,经过EventSource推送到被呼叫者那去。

WebSocket是一个更天然的解决方案,被设计成全双工的客户端/服务器通信(消息能够同时双向传输)。一个将信令服务器用纯WebSocket或服务器发送事件(EventSource)的型式构建的好处是后台接口能够由各类语言的通用框架公共托管包来实现,好比PHP,Python和Ruby。

大概四分之三的浏览器都支持WebSocket了,更重要的是,全部支持WebRTC的浏览器都支持WebSocket,无论是桌面端仍是移动端。全部链接都须要使用TLS,去保证不被截获到未加密的信息,而且减小proxy traveral引发的问题。(须要更多WebSocket和proxy traversal相关的信息,能够看看Ilya Grigorik的High Performance Browser Networking一书的WebRTC章节。Peter Lubber的WebSocket Cheat Sheet有更多关于WebSocket客户端和服务器端的信息)。

apprtc.appspot.comWebRTC视频聊天应用的信令是经过Google App Engine Channel API完成的,这个API用到了Comet)技术(长轮询)去实现信令推送信息(这里有一个App Engine为支持WebSocket存在好久的bug,快去关注这个bug,给它投票别让它沉了!)。这里有一份这个应用的详细代码。

WebRTC客户端经过ajax轮询获取服务器信息处理信令也是可行的,可是这致使太多冗余的网络请求,尤为对于移动端客户来讲更是一个问题。甚至在一个会话创建以后,终端仍须要轮询信令信息去查询是否会话有变化或者会话是否被对方终止了。这个示例使用了该方法,但作了一些轮询频率的优化。

扩展信令服务器规模

虽然信令服务器对于每一个客户来讲消耗的带宽和CPU都较少,可是应用流行起来的话依然要处理不一样地域的大量的数据,应对高并发。通讯量较高的WebRTC应用须要可以应对高负载。

这里咱们不会讨论细节,但仍有以下一些为高容量,高性能信息能够注意的点。

(开发者Phil Leggetter的Real-Time Web Technologies Guide提供了一个关于消息服务和代码库的总结性清单。)

在Node上用Socket.io创建信令服务器

如下的简单网页应用代码使用到了基于Node上的Socket.io而创建的信令服务器。Socket.io的设计使创建信息交换服务器变得简单,并且它尤为适用于WebRTC信令服务器,由于它内置了’房间’的概念。这个例子不是为产品级别的信令服务器设计的,可是它面向相对较小的用户群工做得很好。

Socket.io除了用WebSocket,还适配如下备用技术:Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe and JSONP polling. 它有多种后台实现,可是它的Node版本应该是最著名的,咱们下面的例子就用的这个版本。

例子中没有WebRTC,这里只是展现网页应用信令该如何设计。查看控制台能够看到客户是如何加入一个房间且交换信息的。咱们的WebRTC codelab有如何将这个例子集成进完整的WebRTC视频聊天应用的步骤。你能够在codelab repo第五步下载这些代码,也能够在samdutton-nodertc.jit.su在线试试效果。

index.html的代码以下:

1
2 3 4 5 6 7 8 9 10 
<!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> 

html中引用的的javascript文件main.js代码以下:

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 
var isInitiator;  room = prompt('Enter room name:');  var socket = io.connect();  if (room !== '') {  console.log('Joining room ' + room);  socket.emit('create or join', room); }  socket.on('full', function (room){  console.log('Room ' + room + ' is full'); });  socket.on('empty', function (room){  isInitiator = true;  console.log('Room ' + room + ' is empty'); });  socket.on('join', function (room){  console.log('Making request to join room ' + room);  console.log('You are the initiator!'); });  socket.on('log', function (array){  console.log.apply(console, array); }); 

完整的服务端应用代码:

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 
var static = require('node-static'); var http = require('http'); var file = new(static.Server)(); var app = http.createServer(function (req, res) {  file.serve(req, res); }).listen(2013);  var io = require('socket.io').listen(app);  io.sockets.on('connection', function (socket){   // convenience function to log server messages to the client  function log(){  var array = ['>>> Message from server: '];  for (var i = 0; i < arguments.length; i++) {  array.push(arguments[i]);  }  socket.emit('log', array);  }   socket.on('message', function (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', function (room) {  var 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能够直接在官网下载(安装过程很简单)。要安装socket.io和node-static,在你的应用目录终端运行Node包管理器(NPM)就好了.

1
2 
npm install socket.io npm install node-static 

要运行应用,只须要在你应用目录里终端运行以下命令:

1
node server.js 

在你的浏览器中打开localhost:2013。在新的标签页或窗口将localhost:2013再打开一次。看看发生了什么,检查下Chrome或Opera的控制台,你能够用经过快捷键Command-Option-JCtrl-Shift-J来打开开发者工具DevTool。

无论你选择什么来实现你的信令,你的后台和客户端都至少至少须要提供一个和这个例子相似的服务。

在信令服务器中使用RTCDataChannel

信令服务器须要初始化一个WebRTC会话。

然而,当两个终端间的链接创建后,RTCDataChannel理论上能够看成信令通道。这个能够减小信令的延迟而且减小信令服务器带宽和cpu的消耗,由于这样的信息是直接交流的。这里咱们没有demo,不过你们仍需留意。

信令陷阱?
  • setLocalDescription()方法被调用前RTCPeerConnection都不会开始收集candidates,这是JSEP IRTF draft中要求的。
  • 利用Trickle ICE(见前文):收到candidates信息马上调用addIceCandidate()方法。
现成的信令服务器

若是你不想你本身来作信令服务器,这里有提供一些WebRTC信令服务器,用的也是以前提到的Socket.io,并都集成了WebRTC客户端JavaScript代码库。

…若是你压根任何代码都不想写,这里也有一些彻底商业化的WebRTC平台如vLine,OpenTok,Asterisk.

须要指出来,Ericsson在WebRTC早期就已经用PHP在Apache上搭了个信令服务器。可是这个如今多少已经废弃了,不过若是你在考虑作相似的事的话,这代码仍是值得一看的。

信令安全

Security is the art of makeing nothing happen.
Salman Rushdie

加密在WebRTC组件中是强制的。

然而,信令机制并不禁WebRTC标准所定义,因此让信令更安全就是你本身的事了。若是攻击者试图劫持信令, HTTPS和WSS(i.e TLS),能够保证他们不会拦截到未加密的信息。你也要注意不要在其余用同一个服务器的用户能访问到的地方广播信令信息。

要保护WebRTC应用,在信令中使用TLS是绝对必要的。

信令以外:使用ICE应付NAT和防火墙

对于信令元数据,WebRTC应用使用了中介服务器,可是对于会话创建后的真正媒体数据流,RTCPeerConnection试图让客户终端直连:点对点链接。
简单的状况下,每一个WebRTC终端都有一个惟一的地址,可使得各终端都能互相直接通信。
{}p2p

没有NAT和防火墙的状况

可是大多数设备都处于一层或多层NAT(网络地址转换器)以后,还有杀毒软件的阻挡了一些端口或协议,又或者使用了代理或者防火墙。防火墙和NAT事实上可能在同一设备上,好比家庭无线路由器。
nat

实际状况

WebRTC应用可使用ICE框架来克服实际应用中复杂的网络问题。要使用ICE的话,你的应用必须以下所述的在RTCPeerConnection中传递ICE服务器的URL。

ICE试图找到链接端点的最佳路径。它并行的查找全部可能性,而后选择最有效率的一项。ICE首先用从设备操做系统和网卡上获取的主机地址来尝试链接,若是失败了(好比设备处于NAT以后),ICE会使用从STUN 服务器获取到的外部地址,若是仍然失败,则交由TURN中继服务器来链接。

换句话说:

  • STUN服务器用于获取设备的外部网络地址
  • TURN服务器是在点对点失败后用于通讯中继。

每个TURN服务器都支持STUN,由于TURN就是在STUN服务器中内建了一个中继功能。ICE也能够应付NAT复杂的设定:实际上,NAR’打洞’会有不止一个公共 IP : port 地址。STUN或TURN服务器的URL由WebRTC中RTCPeerConnection的第一个参数iceServers配置对象可选指定。apprtc.appspot.com中的值是这样的:

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
{
 'iceServers': [  {  'url': 'stun:stun.l.google.com:19302'  },  {  'url': 'turn:192.158.29.39:3478?transport=udp',  'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',  'username': '28224511:1379330808'  },  {  'url': '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:port 地址,而且将这个地址响应回去。换句话说,NAT后的应用使用STUN服务器来找到他的IP:port 公网地址。这个过程使得WebRTC终端能够找到本身公共访问方法,并经过信令机制将之发送给其余终端,就能够建立一个直连连接。(在实践中,不一样的NAT工做方式不一样,并有可能有多层NAT,可是原理是同样的。)

STUN服务器并无作太多东西,也不用记住不少东西,因此一个相对低规格的的STUN服务器能够处理大量的请求。

根据webrtcstats.com的调查,大部分(86%)WebRTC请求均可以经过STUN成功的建立链接,虽然对处于防火墙或者配置复杂的NAT以后的终端要低一些。
stun

用STUN服务器获取公共IP:port 地址
TURN

RTCPeerConnection尝试用UDP协议创建终端间的直连。若是失败了,就尝试TCP协议,仍是失败的话,TURN 服务器就会用于作终端间的数据中继。

重申一下:TURN用于中继视频音频数据流,而不是信令数据!

TURN服务器有公共地址,因此他能够被终端联系到,哪怕终端处于防火墙或者代理以后。TURN服务器有一个概念上简单的工做—作数据流中继—可是,不像STUN服务器,它天生须要消耗大量带宽,也就是说,TURN服务器须要很强大。
turn

STUN,TURN和信令

这幅图展示了TURN的运做,纯STUN不能成功的话,各终端将使用TURN服务器。

部署STUN和TURN服务器

Google运行了一个公用的STUN服务器用做测试,stun.l.google.com:19302,apprtc.appspot.com用到了它。咱们建议使用rfc5766-turn-server看成产品用途的STUN/TURN服务,STUN/TURN服务器的源代码能够在code.google.com/p/rfc5766-turn-server 找到,这里也提供了一些服务器安装的相关信息连接。Amazon Web Services(AWS)也提供了WebRTC的虚拟机镜像

另外一个备选TURN服务器是restund,有源代码,也能够装到在AWS上。下面是介绍如何将restund装到Google Compute Engine上。

  1. 防火墙开放tcp=443,udp/tcp=3478
  2. 建立4个实例(?),各自的公用IP,使用标准Ubuntu 12.06镜像
  3. 配置本地防火墙(容许全部访问源)
  4. 安装工具:
    sudo apt-get install make
    sudo apt-get install gcc
  5. creytiv.com/re.html安装libre
  6. creytiv.com/restund.html获取restund并解包
  7. wget hancke.name/restund-auth.patch 并应用patch -p1 < restund-auth.patch
  8. 对libre和restund运行 make, sudo make install
  9. 按你本身的需求配置restund.conf(替换IP地址,确保正确的共享密钥)并复制到/etc目录
  10. 复制restund/etc/restund/etc/init.d/
  11. 配置restund:
    设置LD_LIBRARY_PATH
    复制restund.conf/etc/restund.conf
    设置restund.conf使用以前配的IP地址
  12. 运行restund
  13. 在远程机器运行stund client命令作测试: ./client IP:port

点对点以外:多方WebRTC通信

你也许会对Justin Uberti为REST API for access to TURN Services提出的IETF标准感兴趣。

很容易想到一个超越简单的点对点媒体流用例:好比,同事间的视频会议,或者一个有数百(万)用户的公共演讲。

WebRTC应用可使用多RTCPeerConnection,让各终端之间以网状配置链接。这就是如talky.io这类应用所使用的方法,而且在少许终端的状况下运行的很是良好。不过,CPU和带宽都消耗很是多,尤为是在移动终端上。
mesh

网状拓扑结构:全部终端都互相链接

此外,WebRTC应用能够按星状拓扑结构来选择一个终端分发数据流。在服务器运行一个WebRTC终端来做为从新分配机制也是可行的(webrtc.org提供了一个简单例子)。

从Chrome 31和Opera 18开始,RTCPeerConnection的MediaStream能够看成另外一个RTCPeerConnection的输入:这里有个简单演示simpl.info/rtcpeerconnection/multi, 这使得应用结构更灵活,由于它使网络应用经过选择其余终端的链接来处理路由成为可能。

Multipoint Control Unit

对于大量终端的更好选择是使用Multipoint Control Unit(MCU).这是一个服务器,像大量参与者之间的桥梁同样用于分发媒体信息。MCU能够在一个视频会议中使用多种分辨率,编解码器和帧率,处理转换编码,选择数据流径,调制或录制视频音频。对于多方通话,有一堆问题须要注意: 特别是,如何显示多视频输入和混调多源音频。云平台如vLine有尝试优化流量路径。

能够考虑买一个MCU的硬件,或者本身作一个。

mcu
Cisco MCU的背面

有很多能用的开源MCU软件供选择。好比,Licode(以前叫Lynckia)就为WebRTC作了一个开源MCU,OpenTok也有一个开源产品Mantis

浏览器以外: VoIP, 电话和短信

WebRTC的标准性质使得浏览器中运行的WebRTC应用能够和运行其余通讯平台的设备或者平台创建通信,好比电话或者视频会议系统。

SIP是VoIP和视频会议系统的信令协议。要使WebRTC网页应用能和其余如视频会议系统的SIP客户端通信,WebRTC须要一个代理服务器作中介信令。信令须要流过网关,可是一旦通讯已经创建起来,SRTP(视频和音频)就能够点对点传输。

PSTN(Public Switched Telephone Network),公用电话交换网络,是全部普通模拟电话的闭路交换网络。要用WebRTC网页应用打电话,流量必须通过PSTN网关。此外,WebRTC网页应用须要用中介XMPP服务器来与Jingle)终端如即时通讯客户端通信。
Jingle由Google开发来做为XMPP扩展用于支持视频和音频信息:如今WebRTC的实现基于libjingleC++库,这个Jingle的实现刚开始是为Google Talk开发的。

一些应用,代码库和平台利用WebRTC的能力来于外界通信,如:

  • sipML5:开源JavaScript SIP客户端
  • jsSIP:JavaScript SIP代码库
  • Phono:开源JavaScript电话接口,做为插件开发
  • Zingaya:嵌入式电话组件
  • Twilio:音频消息应用
  • Uberconference:会议系统

sipML5的开发们也开发了webrtc2sip网关。Tethr and Tropo在笔记本上演示过一个救灾通信框架, 使用OpenBTS cell让电脑能经过WebRTC与一个特别的电话通信。无需电信就能打电话啦!

更多

WebRTC codelab:一步一步介绍如何创建一个视频文字聊天应用,使用了在Node中运行的Socket.io信令服务器。

2013 Google I/O 大会上由WebRTC技术组长Justin Uberti作的WebRTC报告

Chris Wilson在SFHTML5上的报告:Introduction to WebRTC Apps

WebRTC Book提供了不少数据和信令路径的详细信息,包括了许多详细的网络拓扑图。

WebRTC and Signaling: What Two Years Has Taught Us:TokBox的一篇博文告诉咱们为何要把信令从WebRTC细则中单独拎出来。

Ben Strong的报告A Practical Guide to Building WebRTC Apps提供了不少WebRTC拓扑和基础。

Ilya GrigorikHigh Performance Browser Networking一书中的WebRTC章节深刻描述了WebRTC结构,用例和性能。

相关文章
相关标签/搜索