一、背景
近年來,直播競答、網絡游戲直播等新的實時音視頻通訊場景不斷推陳出新,實時音視頻應用的爆發(fā),使得WebRTC技術成為了人們關注的焦點。由于WebRTC技術可以幫助用戶在沒有插件和客戶端的情況下,輕松實現(xiàn)網頁瀏覽器之間的實時語音對話和視頻對話,加之研發(fā)成本相對較低,因此開源的WebRTC技術逐漸在眾多領域得到了廣泛應用。58集團目前很多業(yè)務場景對音視頻通話有需求,如IM、金融面審、招聘面試等。因此TEG結合實際業(yè)務場景基于WebRTC提供了一套完整的實時音視頻通話解決方案,以滿足各個業(yè)務場景的需求。
二、WebRTC的技術介紹
WebRTC是一個開源項目,旨在使得瀏覽器能為實時通信(RTC)提供簡單的JavaScript接口。說的簡單明了一點就是讓瀏覽器提供JS的即時通信接口。這個接口所創(chuàng)立的信道并不是像WebSocket一樣,打通一個瀏覽器與WebSocket服務器之間的通信,而是通過一系列的信令,建立一個瀏覽器與瀏覽器之間(peer-to-peer)的信道,這個信道可以發(fā)送任何數(shù)據,而不需要經過服務器。并且WebRTC通過實現(xiàn)MediaStream,通過瀏覽器調用設備的攝像頭、話筒,使得瀏覽器之間可以傳遞音頻和視頻。
WebRTC技術將語音視頻的采集和編解碼全部內嵌到了瀏覽器中,由此大大簡化了視頻通信所需的成本,即只需要一個支持WebRTC技術的瀏覽器即可實現(xiàn)視頻通信,并且可以跨越不同平臺和終端。

上圖為WebRTC的底層架構,其用到的技術非常多,包括視頻音頻處理以及網絡傳輸,防火墻穿越等技術。
WebRTC有三個模塊,Voice Engine(音頻引擎),Video Engine(視頻引擎)和Transport。
- Voice Engine包含iSAC/iLBC Codec(音頻編解碼器,前者是針對寬帶和超寬帶,后者是針對窄帶),NetEQ for voice(處理網絡抖動和語音包丟失),Echo Canceler(回聲消除器),Noise Reduction(噪聲抑制);
- Video Engine包含VP8 Codec(視頻圖像編解碼器),Video jitter buffer(視頻抖動緩沖器,處理視頻抖動和視頻信息包丟失),Image enhancements(圖像質量增強);
- Transport包含SRTP(安全的實時傳輸協(xié)議,用以音視頻流傳輸),Multiplexing(多路復用),P2P,STUN+TURN+ICE(用于NAT網絡和防火墻穿越的)。除此之外,安全傳輸可能還會用到DTLS(數(shù)據報安全傳輸),用于加密傳輸和密鑰協(xié)商。整個WebRTC通信是基于UDP的。
WebRTC有三個重要的部分:MediaStream、RTCPeerConnection、RTCDataChannel。
- getUserMedia 允許網頁瀏覽器獲取攝像頭和麥克風的使用權限,并且捕獲媒體。通過MediaStream的API能夠通過設備的攝像頭及話筒獲得音視頻的同步流。
- RTCPeerConnection 負責管理端到端連接,RTCPeerConnection 是 WebRTC 用于構建點對點之間穩(wěn)定、高效的流傳輸?shù)慕M件。
- RTCDataChannel 允許瀏覽器分享任意數(shù)據,RTCDataChannel 使得瀏覽器之間(點對點)建立一個高吞吐量、低延時的信道,用于傳輸任意數(shù)據。
MediaStream
MediaStream主要是從設備獲取數(shù)據流,比如說攝像頭和麥克風。
getUserMedia(constraints,successCallback,errCallback),用于獲取用戶授權提供的音頻視頻數(shù)據流,三個參數(shù)分別為約束對象,成功的回調函數(shù),發(fā)送錯誤的回調函數(shù)。
RTCPeerConnection
RTCPeerConnection 作為創(chuàng)建點對點連接的 API,是我們實現(xiàn)音視頻實時通信的關鍵。在點對點通信的過程中,需要交換一系列信息,通常這一過程叫做 — 信令(signaling)。在信令階段需要完成的任務:
- 為每個連接端創(chuàng)建一個 RTCPeerConnection,并添加本地媒體流;
- 獲取并交換本地和遠程描述:SDP 格式的本地媒體元數(shù)據;
- 獲取并交換網絡信息:潛在的連接端點稱為 ICE 候選者。
我們雖然把 WebRTC稱之為點對點的連接,但并不意味實現(xiàn)過程中不需要服務器的參與。因為在點對點的信道建立起來之前,二者之間是沒有辦法通信的。因此在信令階段,我們需要一個通信服務來幫助我們建立起這個連接。WebRTC本身沒有指定信令服務,所以,我們可以使用 XMPP、XHR、Socket等來做信令交換所需的服務。TEG是采用webSocket來做雙向通信。
NAT/防火墻穿越技術
建立點對點信道的問題是 NAT 穿越技術。簡單來說NAT就是為了解決 IPV4 下的 IP 地址匱乏而出現(xiàn)的一種技術,也就是一個 公網 IP 地址一般都對應 n個內網IP。這樣也就會導致不是同一局域網下的瀏覽器在嘗試 WebRTC 連接時,無法直接拿到對方的公網 IP 也就不能進行通信,所以就需要用到 NAT 穿越(也叫打洞)。以下為 NAT 穿越基本流程:

由于 NAT 的行為是非標準化的,在 RTCPeerConnection 中使用 ICE 框架來保證 RTCPeerConnection 能實現(xiàn) NAT 穿越。
ICE
ICE(Interactive Connectivity Establishment)交互式連接建立,一種綜合性的 NAT 穿越技術,是一種框架,可整合各種 NAT 穿越技術如 STUN、TURN(Traversal Using Relaying NAT,中繼NAT實現(xiàn)的穿透)。ICE 會先使用 STUN,嘗試建立一個基于 UDP 的連接,如失敗了就會去 TCP(先嘗試 HTTP,然后嘗試 HTTPS),若依舊失敗 ICE 就會使用一個中繼的 TURN 服務器。 在 P2P 連接被創(chuàng)建前,首先必須進行信令處理。為了完成讓用戶都具有另一端用戶的 IP以及其他任何用戶想要共享的涉及數(shù)據/視頻的信息,信令會在用戶和信令服務器之間進行多次往返。
信令交換過程:

顯而易見,在上述連接的過程中:首先呼叫端(ClientA)需要給 接收端(ClientB) 通過信令服務發(fā)送一條名為 offer(SDP) 的信息,接收端在接收到請求后,則通過信令服務返回一條 answer(SDP) 信息給呼叫端。然后在呼叫端和接收端的 ICE 候選信息準備完成后,通過信令服務進行交換,并互相保存對方的信息,這樣就完成了一次連接。
SDP 格式的本地媒體元數(shù)據的交換:
- v=0
- o=- 9161120045333372658 2 IN IP4 127.0.0.1
- s=-
- t=0 0
- a=group:BUNDLE audio video
- a=msid-semantic: WMS ZJeNpxjV9akPU8igui9Fr4KKKkDvVPLFWTBb
- m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
- c=IN IP4 0.0.0.0
- a=rtcp:9 IN IP4 0.0.0.0
- a=ice-ufrag:wIpU
- a=ice-pwd:x3WCaK1ZwTV9Shs0kmsyQQ6L
- a=ice-options:trickle
- … …
三、音視頻通話流程介紹
根據當前業(yè)務場景,TEG基于WebRTC進行了二次開發(fā),提供了一套自研 的完整解決方案,從而實現(xiàn)點對點的音視頻通話。以下是通過WebRTC進行音視頻通話連接的一系列的步驟:
呼叫/接聽流程:


主叫方發(fā)起通話,首先申請房間號并且加入房間(房間是一個音視頻空間,同一房間內的用戶可以相互觀看對方的實時視頻。用房間號來標識一個房間,即在同一個實時音視頻應用中間號相同的房間,可以認為是同一個房,房間是實時溝通功能的一個管理單元。),然后通過業(yè)務線服務器將房間號發(fā)到被叫方,被叫加入房間。此時被叫方可以選擇接聽或者拒絕,如果選擇接聽通話,此時主叫和被叫經過一系列信令交換過程完成視頻通話。
兼容性:
- iOS: 系統(tǒng)ios11以上支持webRTC,且僅限safari瀏覽器,微信內置瀏覽器尚不支持getUserMedia,視頻編解碼格式為H.264;
- Android: 安卓4.4以上(不含4.4),經測試各大手機廠商自帶瀏覽器均不支持getUserMedia,但微信內置瀏覽器可以正常運行,部分手機firefox和谷歌瀏覽器支持;
- PC: Chrome49以上,F(xiàn)irefox55以上,Edge支持,Safari系統(tǒng)11以上支持,IE不支持。
四、總結
WebRTC技術基于UDP,具有不需安裝插件或者客戶端,開源免費,強大的網絡穿透能力,出色的音視頻處理技術等優(yōu)點,但由于兼容性問題,尤其在安卓手機瀏覽器上的兼容性較差。不過隨著5G網絡的建設和直播等應用的持續(xù)火爆,實時的音視頻通話等場景需求十分強勁,在互聯(lián)網平臺音視頻直播互動這一領域,WebRTC依然是一個最佳的選擇。