WebRTC in the real world: STUN, TURN and signaling

http://www.cnblogs.com/bktmkd/p/5100082.html


 

!WebRTC中文社區原創,轉載請註明出處,謝謝,水平有限,部分意思可能不到位,建議參考英文原帖!
WebRTC 可以p2p視頻通話
但是...
WebRTC 仍然需要幾個服務:
  • 信令服務: 使客戶端之間交換數據用來協調建立通話
  • NAT穿透服務:應付NATs和防火牆
這篇文章會教你怎麼搭建信令服務,和用STUN/TURN服務去做nat穿透。另外,我們會解釋WebRTC是怎麼做到多端通話的。以及如何和VoIP/PSTN(電話)建立通話。
如果你對WebRTC還沒有基礎,我們強烈建議你先看下Getting Started With WebRTC


一.什麼是信令服務(Signaling)?

信令是一個協調溝通的過程,爲了讓一個WebRTC應用發起一個“通話”,客戶端間需要交換以下信令信息:
1.發起和關閉一個通話的控制信息;
2.錯誤信息;
3.媒體元數據,比如編碼解碼設置,帶寬和媒體類型;
4.Key數據,用於確保安全通訊;
5.網絡數據,比如主機在外網下的IP地址和端口。


客戶端的信令處理需要一種來回傳遞信息的方法,這種機制沒有被WebRTC定義,你需要自己去創建它。下面我們將描繪幾種構建信令服務的方法。在此之前,先講幾個概念……

爲什麼WebRTC沒有定義信令?
爲了避免冗餘和最大化兼容已經確立的技術,WebRTC沒有指定信令的方法和協議。
-------------------------------

(WebRTC設計思想是完全指定和控制媒體層,但是讓signaling層儘量脫離應用,原因是不同的應用可能會使用不同的協議,比如已經存在的SIP或者Jingle呼叫協議等。這份協議中,需要交換的關鍵信息是多媒體會議的描述信息,包括在媒體層確定必要的傳輸方式和 媒體配置信息)
------------------------------------------------
JSEP的結構同樣避免了讓瀏覽器保存狀態信息,如果讓瀏覽器成爲一個保存信令狀態的機器,會出現一個問題,就是每次當頁面重載的時候,信令會丟失。所以更好的方案是用服務器保存信令狀態。






JSEP協議要求端對端之間需要發起(offer)和迴應(answer)上面提到的數據。
offer和answer用SDP(Session Description Protocol format信令描述協議格式)交流,像這樣


如果想知道所有的SDP代表的意思,可以看下這個鏈接:IEFT examples

記住,WebRTC這樣設計是爲了讓offer端和answer端能夠在tweaked之前通過SDP文檔設置好參數。

舉個例子: apprtc.appspot.com 裏的preferAudioCodec()方法用來設置默認的編解碼方式和比特率,SDP用JavaScript比較難操作,未來的版本可能會用JSON代替,但是SDP還是有一些優勢的。


二.RTCPeerConnection + 信令: offer,answer和candidate

RTCPeerConnection 是WebRTC客戶端在兩端建立音視頻通訊的API。

初始化RTCPeerConnection進程需要兩個步驟:
1.確定當期的媒體條件,例如分辨率,編解碼能力。這些是給offer和answer的原始數據。
2.獲得應用主機的網絡地址(也就是candidate)


一旦這些本地數據被確定好了,就必須通過信令機制在不同端交換。


假設A想呼叫B,下面是整個offer/answer機制的細節:

1.A創建一個RTCPeerConnection對象。
2.A用RTCPeerConnection的createOffer()方法創建一個offer(用SDP協議描述)。
3.A用他的offer設置本地描述setLocalDescription()。
4.A序列化offer,並且用信令機制發送給B.
5.B用A的offer調用setRemoteDescription()設置對方的描述,B的RTCPeerConnection就知道了A的配置了。
6.B調用createAnswer(),如果成功會返回一個本地的session描述,既B的answer。
7.B用她的answer設置爲本地的描述,通過調用setLocalDescription().設置本地描述
8.B用信令機制發送序列化後的answer給A。
9.A設置B的answer爲對方session描述,通過調用setRemoteDescription()設置對方的描述.


(至此,A和B都設置了本地和對方的描述)


A和B還需要交換網絡信息。'finding candidates' 指的是用ICE framework.去發現網絡接口和端口。
1.A用一個onIceCandidate handler創建一個RTCPeerConnection對象。
2.當網絡candidates有效時這個handler會被調用。
3.在這個handler裏,A發送序列化的candidates數據給B,通過信令通道。
4.當B從A獲得一個candidate信息,她調用addIceCandidate()去給對方描述添加candidate。

JSEP支持ICE Candidate Trickling技術(允許呼叫者在首次初始化offer後,逐次發送candidates給被呼叫者,這是爲了讓被呼叫者開始設置連接而不用等到全部的candidates到達)



WebRTC 的信令編碼
下面是W3C code exampleW3C代碼樣例,概況了完整的signaling過程。

樣例假設已經有了信令機制:SignalingChannel。Signaling 會在下面探討比較多的細節。

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


查看“單頁面”視頻聊天的例子simpl.info/pc.可以在 控制檯的lgo看到offer/answer 和candidate 的交換過程。
如果你想了解更多,可以在Chrome瀏覽器打開 chrome://webrtc-internals 或在opera打開 opera://webrtc-internals下載完整的代碼。


三.成員發現機制(Peer discovery)這裏有個問題: 我怎麼發現誰可以通話?

對於電話,我們有電話號碼和目錄。對於在線視頻聊天,我們需要身份和業務管理系統和一種讓用戶開始會話的手段。
WebRTC apps需要一種 讓客戶端標示自己以便可以開始和加入會話的方法。

成員發現機制Peer discovery mechanisms沒有被WebRTC定義,在這裏我們不用做選擇。
這個過程可以像發送一個URL地址這麼簡單,對於視頻聊天應用,比如 talky.io, tawk.com and browsermeeting.com,你通過分享一個通用鏈接邀請別人進入一個會話。
開發者Chris Ball開發了一個有趣的實驗:serverless-webrtc,可以讓WebRTC呼叫參與者分享元數據,通過任何信息服務,比如IM,email或者信鴿。


四.怎麼創建一個signling服務?
再說一遍:信令機制沒有被WebRTC標準定義,無論你選擇哪種 ,你需要一箇中間服務器去交換信令信息和不同客戶端間的應用數據。


慶幸的是,信令信息很小,大部分交換都是在通話開始的時候。


在測試 apprtc.appspot.com 和 samdutton-nodertc.jit.su 時,我們發現一個 視頻會話,總共有大概30-45的信息被信令服務器處理,信息大小大概是10kB。


除了相對要求不高的帶寬,WebRTC 信令服務器不用花費過多的內存和進程,因爲只需要轉發信息和保持很少的會議狀態數據(比如那個客戶端被連接了)

小貼士 :
信令機制不僅可以用來交換會話元數據,也能用來傳達應用數據。它就是個信息服務。


五.從服務端推信息給客戶端

一個信令服務器需要是雙向的:客戶端到服務器和服務器到客戶端。
雙向通訊違反了HTTP 客戶端/服務端 請求/回覆的模式,但是有一些發展多年的技術,例如long polling(長時間輪詢) 被用來從服務端發送數據給一個運行中的web應用。

最近,EventSource API 被廣泛的應用,它允許“服務端發送事件”:數據通過HTTP從服務端發送給瀏覽器。
這裏有個簡單的demo:simpl.info/es
EventSource被設計爲一種消息傳送方式,但是它可以跟XHR 結合做成一個交換signaling的服務:從一個呼叫者傳遞信息,由XHR 請求傳遞,推送給被呼叫者。

WebSocket 是一種更自然的解放方案,它是爲了全雙工 客戶端-服務端通訊設計的(信息可以在同一時間在兩個端傳遞)。
用純WebSocket或者Server-Sent Events (EventSource) 做爲signaling服務的優點是後端調用這些APIs可以用多種Web框架實現,在使用PHP,Python和Ruby的情況下。


大約有四分之三的瀏覽器支持WebSocket ,更重要的是,所有支持WebRTC的桌面瀏覽器和移動瀏覽器都支持WebSocket。


TLS(安全傳輸層協議)應該用於所有的鏈接,已確保信息不會被截斷。
同時用proxy traversal減少問題(更多關於WebSocket 和proxy traversal的資料可以看WebRTC chapter 和WebSocket Cheat Sheet


apprtc.appspot.com 的信令是通過Google App Engine Channel API完成的,Google App Engine Channel API是使用了Comet技術(長時間輪詢)讓APP後端和web客戶端 實現推送通訊功能。這裏有個代碼預演


另外一種方案,可以通過Ajax去輪詢服務端獲取signaling,但會導致一堆多餘的網絡請求,特別是在移動客戶端。
在一個會話被確定後,用戶仍然需要去輪詢signaling信息,因爲會話可能會被其他用戶改變或者終止。
WebRTC》這本書就用了這種經過優化輪詢頻率的方法。


信令壓縮
雖然一個信令服務器在每一個客戶端中花費相當小的帶寬和CPU,但是一個普遍使用的應用可能需要從不同的地點處理很多信息,並且有很多高的併發數。一個大流量的WebRTC 應用需要心理服務端去處理相當大的負荷。


這裏我們不講細節,下面有一些 處理高數據量,高性能的信息通訊設置:
1.XMPP,最初被稱爲Jabber:一種被開發用來即時通訊的協議,可以用來做signaling。服務端可以用 ejabberd andOpenfire實現。JavaScript客戶端,例如 Strophe.js 使用BOSH去模仿雙向通訊流,但因爲各種原因BOSH可能不像WebSocket那麼有效率。(Jingle 是一種支持視頻和語音的XMPP擴展,WebRTC從libjingle庫(Jingle的C++實現庫)裏使用了網絡和傳輸組件 
2.像 ZeroMQ(據說TokBox服務端使用了)、OpenMQ的開源庫。
3.使用支持WebSocket商業的雲服務平臺。
4.商業的WebRTC 平臺,比如vLine.


開發者Phil Leggetter提供了一系列信息服務器和第三方庫列表在Real-Time Web Technologies Guide



用Node開發基於Sockket.io的信令服務

下面有個例子,Socket.io可以輕易創建一個用於交換信息的服務。
Socket.io非常適合WebRTC 的信令,因爲它就是以“rooms”的概念設計的。
這個demo不是一個產品級別的服務,但是能夠應付小數量的用戶。


Socket.io通過下面的回調使用WebSocket: Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe and JSONP polling。
Socket.io也被移植到後端版本,但是最廣爲人知的是Node版本。
這個demo沒有WebRTC,它只是展示怎麼創建一個webapp的signaling。
用控制檯查看log,去看下客戶端加入一個房間和交換數據發生了什麼變化。
WebRTC codelab會一步一步教你怎麼整合這個demo變成一個完整的WEbRTC視頻聊天應用。
你可以從step 5 of the codelab repo下載源碼或者在samdutton-nodertc.jit.su運行(用兩個瀏覽器打開這個鏈接 )

這是客戶端的index.htl:



還有JavaScript文件main.js:





完整的服務端:

  1. var static = require('node-static');
  2. var http = require('http');
  3. var file = new(static.Server)();
  4. var app = http.createServer(function (req, res) {
  5.   file.serve(req, res);
  6. }).listen(2013);
  7. var io = require('socket.io').listen(app);
  8. io.sockets.on('connection', function (socket){
  9.   // convenience function to log server messages to the client
  10.   function log(){
  11.     var array = ['>>> Message from server: '];
  12.     for (var i = 0; i < arguments.length; i++) {
  13.       array.push(arguments[i]);
  14.     }
  15.       socket.emit('log', array);
  16.   }
  17.   socket.on('message', function (message) {
  18.     log('Got message:', message);
  19.     // for a real app, would be room only (not broadcast)
  20.     socket.broadcast.emit('message', message);
  21.   });
  22.   socket.on('create or join', function (room) {
  23.     var numClients = io.sockets.clients(room).length;
  24.     log('Room ' + room + ' has ' + numClients + ' client(s)');
  25.     log('Request to create or join room ' + room);
  26.     if (numClients === 0){
  27.       socket.join(room);
  28.       socket.emit('created', room);
  29.     } else if (numClients === 1) {
  30.       io.sockets.in(room).emit('join', room);
  31.       socket.join(room);
  32.       socket.emit('joined', room);
  33.     } else { // max two clients
  34.       socket.emit('full', room);
  35.     }
  36.     socket.emit('emit(): client ' + socket.id + ' joined room ' + room);
  37.     socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room);
  38.   });
  39. });
複製代碼



要運行這個app,你需要安裝Node, socket.io and node-static。可以在 nodejs.org下載Node,再安裝 socket.io 和node-static,在終端運行Node Package Manager:
npm install socket.ionpm install node-static
啓動服務,運行下面命令
node server.js
在瀏覽器打開 localhost:2013.用新的瀏覽器打開localhost:2013 ,用控制檯看下發生了什麼


使用 RTCDataChannel交換信息
初始化一個WebRTC會話,必須有一個信令 服務器。
然而,一旦兩端確定了 一個通話,理論上,RTCDataChannel可以接替信令通道,這可以減少信號的延遲。
一旦信息直接在兩端通訊,RTCDataChannel會幫忙減少帶寬使用和進程開銷。沒有例子,但可以看下面:
信令性能和擴展性
1.RTCPeerConnection 不會蒐集candidates,直到setLocalDescription() 被調用。這個被JSEP IETF draft.強制要求了。
2.利用Trickle ICE(看上面解釋):接收到candidates後立即調用addIceCandidate(),

現成的信令服務 
這裏有一些可以用的WebRTC signaling服務端:

如果你一點都不想編碼,你可以用完整的商業WebRTC平臺,像vLineOpenTok and Asterisk



愛立信創建了一個 signaling server using PHP on Apache,在WebRTC早期的時候,現在這個已經被棄用了,但是如果你考慮到相似的情況,這個代碼還是值得一看的。


六.Signaling安全 

Security is the art of making nothing happen.


所有WebRTC 組件都被強制加密。
但是信令機制沒有被WebRTC標準定義,所有確保信令安全取決於你,如果一個攻擊者想去劫持信令,他們會導致會話中止,重定向鏈接和記錄,改變或者注入內容。
 
一個牢固的信令最重要的功能是使用加密協議,HTTPS 和WSS (i.e TLS)可以確保信息不會非加密攔截。
同時,小心不要廣播信令信息,不然攻擊者可以使用相同的信令服務鏈接其他來電用戶。


使用 TLS.去確保WebRTC應用的安全。


信令交互完之後,使用ICE去處理NATs和防火牆
對於元數據的信令,WebRTC應用可以使用中間服務,但實際的媒體和數據流在一個會話確立後,RTCPeerConnection 嘗試去直連客戶端:P2P


在一個簡單的世界裏,每一個WebRTC端都有一個唯一的地址,這樣他可以與其他端交換數據,以便直接 通訊。







實際情況下,大多數設備都在一個或多個NAT層後面,有些有防毒軟件阻礙確定的端口和協議,還有很多在代理和公司的防火牆後面。
防火牆和NAT實際上可能由一些類似家庭wifi路由器產生的。







WebRTC 可以使用ICE框架去克服真實世界的複雜網絡。
爲了實現這個功能,你的應用必須傳ICE服務地址給RTCPeerConnection,如下所述。


ICE 試着尋找最佳路線去連接對方,它會並行的尋找所有可能性,然後選擇最有效的可行方式。 
ICE首先會嘗試用設備系統或網卡獲取到的主機地址去建立連接;如果這個失敗了(設備在NATs後面就會)ICE從STUN服務器獲得外部的地址,如果這個也失敗了,就用TURN中轉服務器做通訊。


也就是說:
STUN服務器用來獲取外部網絡地址。
如果P2P失敗的話,[size=14.4444446563721px]TURN服務器用來中繼通訊。


每一個TURN服務器都支持STUN:一個TURN服務器是由一個STUN服務器加上中繼功能。ICE也可以用來應付複雜的NAT設置:
事實上,NAT的”打洞“可能需要除了公共IP之外的端口地址。


WebRTC應用在iceServers配置對象(RTCPeerConnection constructor)裏設置STUN and/or TURN服務器地址。
apprtc.appspot.com裏這個值像這樣:
  1. {
  2.   'iceServers': [
  3.     {
  4.       'url': 'stun:stun.l.google.com:19302'
  5.     },
  6.     {
  7.       'url': 'turn:192.158.29.39:3478?transport=udp',
  8.       'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
  9.       'username': '28224511:1379330808'
  10.     },
  11.     {
  12.       'url': 'turn:192.158.29.39:3478?transport=tcp',
  13.       'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
  14.       'username': '28224511:1379330808'
  15.     }
  16.   ]
  17. }
複製代碼
 
一旦RTCPeerConnection 有了這些信息,ICE會自動啓動:RTCPeerConnection 使用ICE框架計算出兩端間最佳路線,需要STUN和TURN服務器。
 

STUNNATs會給它的設備提供一個內部網絡IP地址,但這個地址不能在外網使用,因爲沒有外網的地址,所有WebRTC沒辦法做連接,爲解決這個問題,WebRTC使用了STUN。

STUN服務架設在外網,它有一個簡單的任務:獲取一個發送請求的設備(運行在NAT後邊的應用)的IP和端口,然後返回這個地址。換句話說,應用使用STUN服務器發現它的外網IP和端口,這個過程確保了一個WebRTC端獲得它自己的公共地址,然後通過signaling機制發送這個信息給另一端,這樣就可以建立起一個直接連接。(在實際中,不同的NATs有不同的工作方式,可能有多個NAT層,但是原理是一樣的)


STUN服務器不需要做太多工作和存儲太多東西,所以簡單的STUN服務器可以應付大量的請求。


根據 webrtcstats.com的統計,使用STUN方式建立WebRTC通話的成功率有86%的。





TURN
RTCPeerConnection 會試着用UDP在兩端建立一個直連,如果失敗了,RTCPeerConnection 會改用TCP,如果這個再失敗了,TURN服務器會被作爲後備方案使用,在兩端間中繼數據。



重述:TURN是在兩端間中轉視頻/語音/數據 流,而不是發送數據。

 

TURN 有個公共地址,所以每個端即使在防火牆或者代理後面,也能訪問到。
TURN有個簡單的任務,中轉數據流,但不像STUN,TURN會花費大量帶寬。所有,TURN需要夠強壯。

 

圖表表示TURN的作用:單純的STUN不起作用,客戶端就會轉向使用TURN。



部署 STUN 和 TURN 服務器
作爲測試,谷歌公佈了一個公共的STUN服務,stun.l.google.com:19302, apprtc.appspot.com用的就是這個。
作爲一個產品級別的 STUN/TURN服務器,我們建議使用 rfc5766-turn-server,STUN 和TURN的源碼可以從code.google.com/p/rfc5766-turn-server獲取,這個鏈接也包括了部署的資料。VM image for Amazon Web Services is also available.

本社區也發佈了部署教程:部署教程

一個可代替的TURN服務器是restrund,可以在source code 下載到,下面介紹在谷歌Compute Engine部署resrund的步驟:

  • Open firewall as necessary, for tcp=443, udp/tcp=3478
  • Create four instances, one for each public IP, Standard Ubuntu 12.06 image
  • Set up local firewall config (allow ANY from ANY)
  • Install tools:
    sudo apt-get install make
    sudo apt-get install gcc
  • Install libre from creytiv.com/re.html
  • Fetch restund from creytiv.com/restund.html and unpack
  • wget hancke.name/restund-auth.patch and apply with patch -p1 < restund-auth.patch
  • Run make, sudo make install for libre and restund
  • Adapt restund.conf to your needs (replace IP addresses and make sure it contains the same shared secret) and copy to /etc
  • Copy restund/etc/restund to /etc/init.d/
  • Configure restund:
    Set LD_LIBRARY_PATH
    Copy restund.conf to /etc/restund.conf
    Set restund.conf to use the right 10. IP address
  • Run restund
  • Test using stund client from remote machine: ./client IP:port




七.突破p2p:多人會議WebRTC

你可以需要看下Justin Uberti提議的IETF標識:請求TURN服務的API

很容易想象到一些場景不只是一對一的視頻通話,舉個例子,公司小組需要一個視頻會議,或者一個公開的演講,一個演講者面對數百(或者數千)的觀看者。

一個WebRTC應用可以使用多個RTCPeerConnections,這樣每一個端可以連接其他端形成一個網絡。
talky.io就是使用這種方法實現,對於少數的用戶,可以很好的工作。但是進程和帶寬開銷會非常大,特別是移動客戶端。




在一個星型結構裏,一個WebRTC客戶端可以選擇一個端去分佈數據流給所有的用戶,你可以自己設計重新分配機制的服務和構造區實現這種方式(werrtc.org提供了一個樣例sample client application

從Chrome31和Opera18 開始,從一個RTCPeerConnection 獲取的媒體流,可以作爲對方的輸入:這裏有個demosimpl.info/multi。這樣可以確保更靈活的結構,因爲它可以允許web應用通過選擇哪個用戶可以連接去控制一個通話 路由。


多點控制部件MCU(Multipoint Control Unit)

大量用戶通話的更好解決方案是使用Multipoint Control Unit(MCU)。這是一個在大量參與者間分佈媒體的橋接服務器。MCUs可以在一個視頻 會議裏處理不同的分辨率,編解碼,和幀速率。對於多端會議,有很多因素要考慮:最重要的是,從多個源裏,怎麼顯示多個視頻和混合音頻。像 vLine 的雲平臺也在致力於優化傳輸路由。
 
你可以去買一個MCU硬件或者自己搭一個。




Cisco MCU背部
有幾個開源的MCU硬件款可以選,例如 Licode(以前稱爲Lynckia) 生產的開源 MCU for WebRTC; OpenTok 平臺的Mantis.



突破瀏覽器: VoIP, telephones 和 messaging
WebRTC 的標準讓瀏覽器和不同設備不同平臺,例如手機或者一個視頻會議系統,進行通話稱爲可能。

SIP是一種信令協議,用來做VoIP和視頻系統。爲了讓WebRTC和SIP端通訊,WebRTC需要一個代理服務器去調解信令。信令一定會經過網關,但是一旦會話建立,視頻和語音就能在兩端傳輸。


PSTN,公共電話交換網絡,是舊式模擬電話的交換網絡。爲了WebRTC和電話進行通話,必須通過一個PSTN網關。
同理,要讓WebRTC跟Jingle端(像IM客戶端)通訊,需要一箇中間XMPP服務器。
Jingle作爲XMPP的擴展,用來實現視頻和語音能夠作爲信息服務:現在的WebRTC就是基於C++實現libjingle 庫發展來的,Jingle最初是Google Talk的技術。


一堆應用庫,平臺讓WebRTC能在實際中通訊:




sipML5 的開發者也開發了webrtc2sip的網關
Tethr and Tropo have demonstrated a framework for disaster communications 'in a briefcase', using an OpenBTS cell to enable communications between feature phones and computers via WebRTC. Telephone communication without a carrier! 



發現更多

WebRTC codelab: 一步一步教你怎麼打造一個視頻和文本聊天應用,使用Socket.io Signaling服務。在Node上面跑。


2013 Google I/O WebRTC presentation WebRTC領頭人Justin Uberti.

Chris Wilson 關於WebRTC的介紹:Introduction to WebRTC Apps.
WebRTC Book 這本書有很多關於數據、signaling、網絡拓撲結構的細節。
WebRTC and Signaling: What Two Years Has Taught Us:介紹爲什麼把signaling脫離出標準是個好主意
A Practical Guide to Building WebRTC Apps:提供很多WebRTC的技術和基礎建設信息。
WebRTC chapter 深入研究WebRTC的結構,使用案例和性能。

!WebRTC中文社區原創,轉載請註明出處,謝謝,水平有限,部分意思可能不到位,建議參考英文原帖!
WebRTC 可以p2p視頻通話
但是...
WebRTC 仍然需要幾個服務:
  • 信令服務: 使客戶端之間交換數據用來協調建立通話
  • NAT穿透服務:應付NATs和防火牆
這篇文章會教你怎麼搭建信令服務,和用STUN/TURN服務去做nat穿透。另外,我們會解釋WebRTC是怎麼做到多端通話的。以及如何和VoIP/PSTN(電話)建立通話。
如果你對WebRTC還沒有基礎,我們強烈建議你先看下Getting Started With WebRTC

一.什麼是信令服務(Signaling)?

信令是一個協調溝通的過程,爲了讓一個WebRTC應用發起一個“通話”,客戶端間需要交換以下信令信息:
1.發起和關閉一個通話的控制信息;
2.錯誤信息;
3.媒體元數據,比如編碼解碼設置,帶寬和媒體類型;
4.Key數據,用於確保安全通訊;
5.網絡數據,比如主機在外網下的IP地址和端口。


客戶端的信令處理需要一種來回傳遞信息的方法,這種機制沒有被WebRTC定義,你需要自己去創建它。下面我們將描繪幾種構建信令服務的方法。在此之前,先講幾個概念……

爲什麼WebRTC沒有定義信令?
爲了避免冗餘和最大化兼容已經確立的技術,WebRTC沒有指定信令的方法和協議。
-------------------------------

(WebRTC設計思想是完全指定和控制媒體層,但是讓signaling層儘量脫離應用,原因是不同的應用可能會使用不同的協議,比如已經存在的SIP或者Jingle呼叫協議等。這份協議中,需要交換的關鍵信息是多媒體會議的描述信息,包括在媒體層確定必要的傳輸方式和 媒體配置信息)
------------------------------------------------
JSEP的結構同樣避免了讓瀏覽器保存狀態信息,如果讓瀏覽器成爲一個保存信令狀態的機器,會出現一個問題,就是每次當頁面重載的時候,信令會丟失。所以更好的方案是用服務器保存信令狀態。






JSEP協議要求端對端之間需要發起(offer)和迴應(answer)上面提到的數據。
offer和answer用SDP(Session Description Protocol format信令描述協議格式)交流,像這樣


如果想知道所有的SDP代表的意思,可以看下這個鏈接:IEFT examples

記住,WebRTC這樣設計是爲了讓offer端和answer端能夠在tweaked之前通過SDP文檔設置好參數。

舉個例子: apprtc.appspot.com 裏的preferAudioCodec()方法用來設置默認的編解碼方式和比特率,SDP用JavaScript比較難操作,未來的版本可能會用JSON代替,但是SDP還是有一些優勢的。


二.RTCPeerConnection + 信令: offer,answer和candidate

RTCPeerConnection 是WebRTC客戶端在兩端建立音視頻通訊的API。

初始化RTCPeerConnection進程需要兩個步驟:
1.確定當期的媒體條件,例如分辨率,編解碼能力。這些是給offer和answer的原始數據。
2.獲得應用主機的網絡地址(也就是candidate)


一旦這些本地數據被確定好了,就必須通過信令機制在不同端交換。


假設A想呼叫B,下面是整個offer/answer機制的細節:

1.A創建一個RTCPeerConnection對象。
2.A用RTCPeerConnection的createOffer()方法創建一個offer(用SDP協議描述)。
3.A用他的offer設置本地描述setLocalDescription()。
4.A序列化offer,並且用信令機制發送給B.
5.B用A的offer調用setRemoteDescription()設置對方的描述,B的RTCPeerConnection就知道了A的配置了。
6.B調用createAnswer(),如果成功會返回一個本地的session描述,既B的answer。
7.B用她的answer設置爲本地的描述,通過調用setLocalDescription().設置本地描述
8.B用信令機制發送序列化後的answer給A。
9.A設置B的answer爲對方session描述,通過調用setRemoteDescription()設置對方的描述.


(至此,A和B都設置了本地和對方的描述)


A和B還需要交換網絡信息。'finding candidates' 指的是用ICE framework.去發現網絡接口和端口。
1.A用一個onIceCandidate handler創建一個RTCPeerConnection對象。
2.當網絡candidates有效時這個handler會被調用。
3.在這個handler裏,A發送序列化的candidates數據給B,通過信令通道。
4.當B從A獲得一個candidate信息,她調用addIceCandidate()去給對方描述添加candidate。

JSEP支持ICE Candidate Trickling技術(允許呼叫者在首次初始化offer後,逐次發送candidates給被呼叫者,這是爲了讓被呼叫者開始設置連接而不用等到全部的candidates到達)



WebRTC 的信令編碼
下面是W3C code exampleW3C代碼樣例,概況了完整的signaling過程。

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

查看“單頁面”視頻聊天的例子simpl.info/pc.可以在 控制檯的lgo看到offer/answer 和candidate 的交換過程。
如果你想了解更多,可以在Chrome瀏覽器打開 chrome://webrtc-internals 或在opera打開 opera://webrtc-internals下載完整的代碼。


三.成員發現機制(Peer discovery)這裏有個問題: 我怎麼發現誰可以通話?

對於電話,我們有電話號碼和目錄。對於在線視頻聊天,我們需要身份和業務管理系統和一種讓用戶開始會話的手段。
WebRTC apps需要一種 讓客戶端標示自己以便可以開始和加入會話的方法。

成員發現機制Peer discovery mechanisms沒有被WebRTC定義,在這裏我們不用做選擇。
這個過程可以像發送一個URL地址這麼簡單,對於視頻聊天應用,比如 talky.io, tawk.com and browsermeeting.com,你通過分享一個通用鏈接邀請別人進入一個會話。
開發者Chris Ball開發了一個有趣的實驗:serverless-webrtc,可以讓WebRTC呼叫參與者分享元數據,通過任何信息服務,比如IM,email或者信鴿。


四.怎麼創建一個signling服務?
再說一遍:信令機制沒有被WebRTC標準定義,無論你選擇哪種 ,你需要一箇中間服務器去交換信令信息和不同客戶端間的應用數據。


慶幸的是,信令信息很小,大部分交換都是在通話開始的時候。


在測試 apprtc.appspot.com 和 samdutton-nodertc.jit.su 時,我們發現一個 視頻會話,總共有大概30-45的信息被信令服務器處理,信息大小大概是10kB。


除了相對要求不高的帶寬,WebRTC 信令服務器不用花費過多的內存和進程,因爲只需要轉發信息和保持很少的會議狀態數據(比如那個客戶端被連接了)

小貼士 :
信令機制不僅可以用來交換會話元數據,也能用來傳達應用數據。它就是個信息服務。


五.從服務端推信息給客戶端

一個信令服務器需要是雙向的:客戶端到服務器和服務器到客戶端。
雙向通訊違反了HTTP 客戶端/服務端 請求/回覆的模式,但是有一些發展多年的技術,例如long polling(長時間輪詢) 被用來從服務端發送數據給一個運行中的web應用。

最近,EventSource API 被廣泛的應用,它允許“服務端發送事件”:數據通過HTTP從服務端發送給瀏覽器。
這裏有個簡單的demo:simpl.info/es
EventSource被設計爲一種消息傳送方式,但是它可以跟XHR 結合做成一個交換signaling的服務:從一個呼叫者傳遞信息,由XHR 請求傳遞,推送給被呼叫者。

WebSocket 是一種更自然的解放方案,它是爲了全雙工 客戶端-服務端通訊設計的(信息可以在同一時間在兩個端傳遞)。
用純WebSocket或者Server-Sent Events (EventSource) 做爲signaling服務的優點是後端調用這些APIs可以用多種Web框架實現,在使用PHP,Python和Ruby的情況下。


大約有四分之三的瀏覽器支持WebSocket ,更重要的是,所有支持WebRTC的桌面瀏覽器和移動瀏覽器都支持WebSocket。


TLS(安全傳輸層協議)應該用於所有的鏈接,已確保信息不會被截斷。
同時用proxy traversal減少問題(更多關於WebSocket 和proxy traversal的資料可以看WebRTC chapter 和WebSocket Cheat Sheet


apprtc.appspot.com 的信令是通過Google App Engine Channel API完成的,Google App Engine Channel API是使用了Comet技術(長時間輪詢)讓APP後端和web客戶端 實現推送通訊功能。這裏有個代碼預演


另外一種方案,可以通過Ajax去輪詢服務端獲取signaling,但會導致一堆多餘的網絡請求,特別是在移動客戶端。
在一個會話被確定後,用戶仍然需要去輪詢signaling信息,因爲會話可能會被其他用戶改變或者終止。
WebRTC》這本書就用了這種經過優化輪詢頻率的方法。


信令壓縮
雖然一個信令服務器在每一個客戶端中花費相當小的帶寬和CPU,但是一個普遍使用的應用可能需要從不同的地點處理很多信息,並且有很多高的併發數。一個大流量的WebRTC 應用需要心理服務端去處理相當大的負荷。


這裏我們不講細節,下面有一些 處理高數據量,高性能的信息通訊設置:
1.XMPP,最初被稱爲Jabber:一種被開發用來即時通訊的協議,可以用來做signaling。服務端可以用 ejabberd andOpenfire實現。JavaScript客戶端,例如 Strophe.js 使用BOSH去模仿雙向通訊流,但因爲各種原因BOSH可能不像WebSocket那麼有效率。(Jingle 是一種支持視頻和語音的XMPP擴展,WebRTC從libjingle庫(Jingle的C++實現庫)裏使用了網絡和傳輸組件 
2.像 ZeroMQ(據說TokBox服務端使用了)、OpenMQ的開源庫。
3.使用支持WebSocket商業的雲服務平臺。
4.商業的WebRTC 平臺,比如vLine.


開發者Phil Leggetter提供了一系列信息服務器和第三方庫列表在Real-Time Web Technologies Guide



用Node開發基於Sockket.io的信令服務

下面有個例子,Socket.io可以輕易創建一個用於交換信息的服務。
Socket.io非常適合WebRTC 的信令,因爲它就是以“rooms”的概念設計的。
這個demo不是一個產品級別的服務,但是能夠應付小數量的用戶。


Socket.io通過下面的回調使用WebSocket: Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe and JSONP polling。
Socket.io也被移植到後端版本,但是最廣爲人知的是Node版本。
這個demo沒有WebRTC,它只是展示怎麼創建一個webapp的signaling。
用控制檯查看log,去看下客戶端加入一個房間和交換數據發生了什麼變化。
WebRTC codelab會一步一步教你怎麼整合這個demo變成一個完整的WEbRTC視頻聊天應用。
你可以從step 5 of the codelab repo下載源碼或者在samdutton-nodertc.jit.su運行(用兩個瀏覽器打開這個鏈接 )

這是客戶端的index.htl:



還有JavaScript文件main.js:





完整的服務端:
  1. var static = require('node-static');
  2. var http = require('http');
  3. var file = new(static.Server)();
  4. var app = http.createServer(function (req, res) {
  5.   file.serve(req, res);
  6. }).listen(2013);
  7. var io = require('socket.io').listen(app);
  8. io.sockets.on('connection', function (socket){
  9.   // convenience function to log server messages to the client
  10.   function log(){
  11.     var array = ['>>> Message from server: '];
  12.     for (var i = 0; i < arguments.length; i++) {
  13.       array.push(arguments[i]);
  14.     }
  15.       socket.emit('log', array);
  16.   }
  17.   socket.on('message', function (message) {
  18.     log('Got message:', message);
  19.     // for a real app, would be room only (not broadcast)
  20.     socket.broadcast.emit('message', message);
  21.   });
  22.   socket.on('create or join', function (room) {
  23.     var numClients = io.sockets.clients(room).length;
  24.     log('Room ' + room + ' has ' + numClients + ' client(s)');
  25.     log('Request to create or join room ' + room);
  26.     if (numClients === 0){
  27.       socket.join(room);
  28.       socket.emit('created', room);
  29.     } else if (numClients === 1) {
  30.       io.sockets.in(room).emit('join', room);
  31.       socket.join(room);
  32.       socket.emit('joined', room);
  33.     } else { // max two clients
  34.       socket.emit('full', room);
  35.     }
  36.     socket.emit('emit(): client ' + socket.id + ' joined room ' + room);
  37.     socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room);
  38.   });
  39. });
複製代碼


要運行這個app,你需要安裝Node, socket.io and node-static。可以在 nodejs.org下載Node,再安裝 socket.io 和node-static,在終端運行Node Package Manager:
npm install socket.ionpm install node-static
啓動服務,運行下面命令
node server.js
在瀏覽器打開 localhost:2013.用新的瀏覽器打開localhost:2013 ,用控制檯看下發生了什麼


使用 RTCDataChannel交換信息
初始化一個WebRTC會話,必須有一個信令 服務器。
然而,一旦兩端確定了 一個通話,理論上,RTCDataChannel可以接替信令通道,這可以減少信號的延遲。
一旦信息直接在兩端通訊,RTCDataChannel會幫忙減少帶寬使用和進程開銷。沒有例子,但可以看下面:
信令性能和擴展性
1.RTCPeerConnection 不會蒐集candidates,直到setLocalDescription() 被調用。這個被JSEP IETF draft.強制要求了。
2.利用Trickle ICE(看上面解釋):接收到candidates後立即調用addIceCandidate(),

現成的信令服務 
這裏有一些可以用的WebRTC signaling服務端:

如果你一點都不想編碼,你可以用完整的商業WebRTC平臺,像vLineOpenTok and Asterisk



愛立信創建了一個 signaling server using PHP on Apache,在WebRTC早期的時候,現在這個已經被棄用了,但是如果你考慮到相似的情況,這個代碼還是值得一看的。


六.Signaling安全 
Security is the art of making nothing happen.

所有WebRTC 組件都被強制加密。
但是信令機制沒有被WebRTC標準定義,所有確保信令安全取決於你,如果一個攻擊者想去劫持信令,他們會導致會話中止,重定向鏈接和記錄,改變或者注入內容。
 
一個牢固的信令最重要的功能是使用加密協議,HTTPS 和WSS (i.e TLS)可以確保信息不會非加密攔截。
同時,小心不要廣播信令信息,不然攻擊者可以使用相同的信令服務鏈接其他來電用戶。

使用 TLS.去確保WebRTC應用的安全。

信令交互完之後,使用ICE去處理NATs和防火牆
對於元數據的信令,WebRTC應用可以使用中間服務,但實際的媒體和數據流在一個會話確立後,RTCPeerConnection 嘗試去直連客戶端:P2P


在一個簡單的世界裏,每一個WebRTC端都有一個唯一的地址,這樣他可以與其他端交換數據,以便直接 通訊。







實際情況下,大多數設備都在一個或多個NAT層後面,有些有防毒軟件阻礙確定的端口和協議,還有很多在代理和公司的防火牆後面。
防火牆和NAT實際上可能由一些類似家庭wifi路由器產生的。







WebRTC 可以使用ICE框架去克服真實世界的複雜網絡。
爲了實現這個功能,你的應用必須傳ICE服務地址給RTCPeerConnection,如下所述。


ICE 試着尋找最佳路線去連接對方,它會並行的尋找所有可能性,然後選擇最有效的可行方式。 
ICE首先會嘗試用設備系統或網卡獲取到的主機地址去建立連接;如果這個失敗了(設備在NATs後面就會)ICE從STUN服務器獲得外部的地址,如果這個也失敗了,就用TURN中轉服務器做通訊。


也就是說:
STUN服務器用來獲取外部網絡地址。
如果P2P失敗的話,[size=14.4444446563721px]TURN服務器用來中繼通訊。

每一個TURN服務器都支持STUN:一個TURN服務器是由一個STUN服務器加上中繼功能。ICE也可以用來應付複雜的NAT設置:
事實上,NAT的”打洞“可能需要除了公共IP之外的端口地址。

WebRTC應用在iceServers配置對象(RTCPeerConnection constructor)裏設置STUN and/or TURN服務器地址。
apprtc.appspot.com裏這個值像這樣:
  1. {
  2.   'iceServers': [
  3.     {
  4.       'url': 'stun:stun.l.google.com:19302'
  5.     },
  6.     {
  7.       'url': 'turn:192.158.29.39:3478?transport=udp',
  8.       'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
  9.       'username': '28224511:1379330808'
  10.     },
  11.     {
  12.       'url': 'turn:192.158.29.39:3478?transport=tcp',
  13.       'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
  14.       'username': '28224511:1379330808'
  15.     }
  16.   ]
  17. }
複製代碼
 
一旦RTCPeerConnection 有了這些信息,ICE會自動啓動:RTCPeerConnection 使用ICE框架計算出兩端間最佳路線,需要STUN和TURN服務器。
 
STUNNATs會給它的設備提供一個內部網絡IP地址,但這個地址不能在外網使用,因爲沒有外網的地址,所有WebRTC沒辦法做連接,爲解決這個問題,WebRTC使用了STUN。

STUN服務架設在外網,它有一個簡單的任務:獲取一個發送請求的設備(運行在NAT後邊的應用)的IP和端口,然後返回這個地址。換句話說,應用使用STUN服務器發現它的外網IP和端口,這個過程確保了一個WebRTC端獲得它自己的公共地址,然後通過signaling機制發送這個信息給另一端,這樣就可以建立起一個直接連接。(在實際中,不同的NATs有不同的工作方式,可能有多個NAT層,但是原理是一樣的)


STUN服務器不需要做太多工作和存儲太多東西,所以簡單的STUN服務器可以應付大量的請求。


根據 webrtcstats.com的統計,使用STUN方式建立WebRTC通話的成功率有86%的。





TURN
RTCPeerConnection 會試着用UDP在兩端建立一個直連,如果失敗了,RTCPeerConnection 會改用TCP,如果這個再失敗了,TURN服務器會被作爲後備方案使用,在兩端間中繼數據。




重述:TURN是在兩端間中轉視頻/語音/數據 流,而不是發送數據。

TURN 有個公共地址,所以每個端即使在防火牆或者代理後面,也能訪問到。
TURN有個簡單的任務,中轉數據流,但不像STUN,TURN會花費大量帶寬。所有,TURN需要夠強壯。

圖表表示TURN的作用:單純的STUN不起作用,客戶端就會轉向使用TURN。


部署 STUN 和 TURN 服務器
作爲測試,谷歌公佈了一個公共的STUN服務,stun.l.google.com:19302, apprtc.appspot.com用的就是這個。
作爲一個產品級別的 STUN/TURN服務器,我們建議使用 rfc5766-turn-server,STUN 和TURN的源碼可以從code.google.com/p/rfc5766-turn-server獲取,這個鏈接也包括了部署的資料。VM image for Amazon Web Services is also available.

本社區也發佈了部署教程:部署教程

一個可代替的TURN服務器是restrund,可以在source code 下載到,下面介紹在谷歌Compute Engine部署resrund的步驟:
  • Open firewall as necessary, for tcp=443, udp/tcp=3478
  • Create four instances, one for each public IP, Standard Ubuntu 12.06 image
  • Set up local firewall config (allow ANY from ANY)
  • Install tools:
    sudo apt-get install make
    sudo apt-get install gcc
  • Install libre from creytiv.com/re.html
  • Fetch restund from creytiv.com/restund.html and unpack
  • wget hancke.name/restund-auth.patch and apply with patch -p1 < restund-auth.patch
  • Run make, sudo make install for libre and restund
  • Adapt restund.conf to your needs (replace IP addresses and make sure it contains the same shared secret) and copy to /etc
  • Copy restund/etc/restund to /etc/init.d/
  • Configure restund:
    Set LD_LIBRARY_PATH
    Copy restund.conf to /etc/restund.conf
    Set restund.conf to use the right 10. IP address
  • Run restund
  • Test using stund client from remote machine: ./client IP:port



七.突破p2p:多人會議WebRTC

你可以需要看下Justin Uberti提議的IETF標識:請求TURN服務的API

很容易想象到一些場景不只是一對一的視頻通話,舉個例子,公司小組需要一個視頻會議,或者一個公開的演講,一個演講者面對數百(或者數千)的觀看者。

一個WebRTC應用可以使用多個RTCPeerConnections,這樣每一個端可以連接其他端形成一個網絡。
talky.io就是使用這種方法實現,對於少數的用戶,可以很好的工作。但是進程和帶寬開銷會非常大,特別是移動客戶端。




在一個星型結構裏,一個WebRTC客戶端可以選擇一個端去分佈數據流給所有的用戶,你可以自己設計重新分配機制的服務和構造區實現這種方式(werrtc.org提供了一個樣例sample client application

從Chrome31和Opera18 開始,從一個RTCPeerConnection 獲取的媒體流,可以作爲對方的輸入:這裏有個demosimpl.info/multi。這樣可以確保更靈活的結構,因爲它可以允許web應用通過選擇哪個用戶可以連接去控制一個通話 路由。


多點控制部件MCU(Multipoint Control Unit)
大量用戶通話的更好解決方案是使用Multipoint Control Unit(MCU)。這是一個在大量參與者間分佈媒體的橋接服務器。MCUs可以在一個視頻 會議裏處理不同的分辨率,編解碼,和幀速率。對於多端會議,有很多因素要考慮:最重要的是,從多個源裏,怎麼顯示多個視頻和混合音頻。像 vLine 的雲平臺也在致力於優化傳輸路由。
 
你可以去買一個MCU硬件或者自己搭一個。



Cisco MCU背部
有幾個開源的MCU硬件款可以選,例如 Licode(以前稱爲Lynckia) 生產的開源 MCU for WebRTC; OpenTok 平臺的Mantis.



突破瀏覽器: VoIP, telephones 和 messaging
WebRTC 的標準讓瀏覽器和不同設備不同平臺,例如手機或者一個視頻會議系統,進行通話稱爲可能。

SIP是一種信令協議,用來做VoIP和視頻系統。爲了讓WebRTC和SIP端通訊,WebRTC需要一個代理服務器去調解信令。信令一定會經過網關,但是一旦會話建立,視頻和語音就能在兩端傳輸。


PSTN,公共電話交換網絡,是舊式模擬電話的交換網絡。爲了WebRTC和電話進行通話,必須通過一個PSTN網關。
同理,要讓WebRTC跟Jingle端(像IM客戶端)通訊,需要一箇中間XMPP服務器。
Jingle作爲XMPP的擴展,用來實現視頻和語音能夠作爲信息服務:現在的WebRTC就是基於C++實現libjingle 庫發展來的,Jingle最初是Google Talk的技術。


一堆應用庫,平臺讓WebRTC能在實際中通訊:





sipML5 的開發者也開發了webrtc2sip的網關
Tethr and Tropo have demonstrated a framework for disaster communications 'in a briefcase', using an OpenBTS cell to enable communications between feature phones and computers via WebRTC. Telephone communication without a carrier! 



發現更多

WebRTC codelab: 一步一步教你怎麼打造一個視頻和文本聊天應用,使用Socket.io Signaling服務。在Node上面跑。


2013 Google I/O WebRTC presentation WebRTC領頭人Justin Uberti.
Chris Wilson 關於WebRTC的介紹:Introduction to WebRTC Apps.
WebRTC Book 這本書有很多關於數據、signaling、網絡拓撲結構的細節。
WebRTC and Signaling: What Two Years Has Taught Us:介紹爲什麼把signaling脫離出標準是個好主意
A Practical Guide to Building WebRTC Apps:提供很多WebRTC的技術和基礎建設信息。
WebRTC chapter 深入研究WebRTC的結構,使用案例和性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章