WebRTC技術(shù)專題(2)【大勢(shì)所趨,邁向認(rèn)識(shí) WebRTC 的第一步】

image

每日一句

人生的挑戰(zhàn),無(wú)處不在,滿懷信心,輕裝上路,明天永遠(yuǎn)是充滿希望的戰(zhàn)場(chǎng)。

承接上文

承接上文的內(nèi)容介紹完相關(guān)WebRTC技術(shù)的概念和發(fā)展歷程后,開(kāi)始初步摸索一下相關(guān)WebRTC技術(shù)的功能和原理。??【W(wǎng)ebRTC原理探索】未來(lái)可期,WebRTC的誕生發(fā)展

技術(shù)回顧

WebRTC概念定義

WebRTC名稱源自網(wǎng)頁(yè)實(shí)時(shí)通信(Web Real-Time Communication)的縮寫,是一個(gè)支持網(wǎng)頁(yè)瀏覽器進(jìn)行實(shí)時(shí)語(yǔ)音對(duì)話或視頻對(duì)話的技術(shù),是谷歌2010年以6820萬(wàn)美元收購(gòu)Global IP Solutions公司而獲得的一項(xiàng)技術(shù)。

WebRTC功能范疇

  • WebRTC是一個(gè)開(kāi)源項(xiàng)目,旨在使得瀏覽器能為實(shí)時(shí)通信(RTC)提供簡(jiǎn)單的 JavaScript接口。

  • WebRTC不僅可傳輸視頻,也可以傳輸其他數(shù)據(jù)例如文本、圖片等。需要注意的是,WebRTC并不是瀏覽器的一個(gè)子集,瀏覽器只是根據(jù) WebRTC 的標(biāo)準(zhǔn)協(xié)議實(shí)現(xiàn)了 WebRTC的原生接口。Android 和 IOS 系統(tǒng)也支持 WebRTC 。

WebRTC應(yīng)用包括下面四個(gè)主要的概念

  • 信令服務(wù)器(Signalling servers)

  • ICE服務(wù)器(ICE servers)

  • 媒體服務(wù)器(Media servers)

  • JavaScript接口 (JavaScript API)

WebRTC已經(jīng)納入HTML5標(biāo)準(zhǔn)

目前支持WebRTC協(xié)議的瀏覽器有:Chrome、Firefox Opera,IE不支持~

  • WebRTC沒(méi)有指定具體的信令協(xié)議,具體的信令協(xié)議留給應(yīng)用程序?qū)崿F(xiàn)。

  • WebRTC使用JSEP協(xié)議建立會(huì)話,什么是JSEP后面說(shuō)

  • WebRTC采用ICE實(shí)現(xiàn)NAT穿越。

  • WebRTC客戶端之間可以進(jìn)行點(diǎn)對(duì)點(diǎn)的媒體傳輸。

WebRTC的核心組件

  • 音視頻引擎:OPUS、VP8/VP9、H264

  • 傳輸層協(xié)議:底層傳輸協(xié)議為UDP

  • 媒體協(xié)議:SRTP/SRTCP

  • 數(shù)據(jù)協(xié)議:DTLS/SCTP

  • P2P內(nèi)網(wǎng)穿透:STUN / TURN / ICE / Trickle ICE

  • 信令與SDP協(xié)商:HTTP / WebSocket / SIP、 Offer Answer 模型

下圖為WebRTC內(nèi)部結(jié)構(gòu)簡(jiǎn)化圖:

  • 最底層是硬件設(shè)備。

  • 上面是音頻捕獲模塊和視頻捕獲模塊

image.png
  • 中間部分為音視頻引擎

    • 音頻引擎負(fù)責(zé)音頻采集和傳輸,具有降噪、回聲消除等功能。

    • 視頻引擎負(fù)責(zé)網(wǎng)絡(luò)抖動(dòng)優(yōu)化,互聯(lián)網(wǎng)傳輸編解碼優(yōu)化。

在音視頻引擎之上是一套C++ API,在C++ 的API之上是提供給瀏覽器的Javascript API。

JSEP

  • JSEP(JavaScript Session Establishment Protocol,JavaScript會(huì)話建立協(xié)議)是一個(gè)信令A(yù)PI,允許開(kāi)發(fā)者構(gòu)建更強(qiáng)大的應(yīng)用程序以及增加在信令協(xié)議選擇上的靈活性。

  • JSEP是干什么的呢,一方面提供接口如createOffer()供web應(yīng)用程序調(diào)用生成SDP,另一方面提供ICE功能接口。這些功能都由瀏覽器實(shí)現(xiàn),瀏覽器WebRTC傳輸信令(offer/answer)采用Websocket。

    • 建立會(huì)話最關(guān)鍵的就是媒體的協(xié)商,WebRTC雖然沒(méi)有指定具體的信令協(xié)議,但是媒體協(xié)商采用了SDP協(xié)議。

    • 如果web應(yīng)用程序不使用額外的信令協(xié)議,僅使用JSEP,兩個(gè)WebRTC client(同一個(gè)WebRTC client程序,兩處登陸)之間也是可以建立鏈接的,即只要應(yīng)用程序能解析用WS傳遞過(guò)來(lái)的Offer/Answer消息,提取出其中的SDP和ICE信息就可以了。

  • github上codelabdemo就是不用其他信令協(xié)議,直接使用JSEP生成offer/answer信令,然后采用ws協(xié)議傳輸實(shí)現(xiàn)的。

  • JSEP并不是信令協(xié)議,可以在JSEP的基礎(chǔ)上引入SIP等信令協(xié)議,使WebRTC應(yīng)用功能更加完備。

信令服務(wù)器

  • 信令服務(wù)器主要用于在兩個(gè)用戶之間交換信息。雖然WebRTC是點(diǎn)對(duì)點(diǎn)通信,但還是需要服務(wù)器來(lái)初始化連接,并傳遞一些信息。

WebRTC沒(méi)有定義用于建立信道的信令的協(xié)議,因此可以使用任意的傳輸方式,例如 WebSocket, XMPP, SIP, AJAX。

  • 可以使用實(shí)時(shí)的傳輸協(xié)議比如WebSocket來(lái)交換數(shù)據(jù),也可以使用簡(jiǎn)單的 GET/POST方式輪詢服務(wù)器來(lái)獲取數(shù)據(jù)。
信令服務(wù)器傳送的數(shù)據(jù)有
  1. 協(xié)商媒體功能和設(shè)置
  2. 標(biāo)識(shí)和驗(yàn)證會(huì)話參與者的身份
  3. 控制媒體會(huì)話指示進(jìn)度、更改會(huì)話和終止會(huì)話

其中只有第一項(xiàng)的必備功能。其他都可以根據(jù)業(yè)務(wù)需求自由調(diào)整。

SDP協(xié)議
  • 媒體協(xié)商最重要的功能在于,為參與點(diǎn)對(duì)點(diǎn)通信的兩個(gè)瀏覽器之間交換會(huì)話描述協(xié)議「SDP」。

  • 「SDP」包含瀏覽器的RTP媒體棧配置所需的全部信息,包括媒體類型(音頻、視頻、數(shù)據(jù))、所需的編解碼器,用于編解碼器參數(shù)或設(shè)置,以及有關(guān)帶寬的信息。

此外,信令通道還用于交換候選地址,以便進(jìn)行ICE打洞。

信令互通方案

WebRTC與SIP互通

要想讓W(xué)ebRTC與SIP互通,要解決兩個(gè)層面的問(wèn)題:信令層和媒體層。

兩個(gè)網(wǎng)絡(luò)使用的信令機(jī)制不同,所以要進(jìn)行信令的轉(zhuǎn)換,才能完成媒體的協(xié)商,建立會(huì)話。媒體層要完成編碼的轉(zhuǎn)換,以及RTP/SRTP轉(zhuǎn)換等功能。

這里主要說(shuō)項(xiàng)信令層面的互通。

目前SIP和WebRTC信令上互通有兩種解決方案:

  • JavaScript實(shí)現(xiàn)SIP協(xié)議棧,WebRTC應(yīng)用程序基于這個(gè)協(xié)議棧開(kāi)發(fā)。WebRTC Client發(fā)出的信令就是SIP信令,但一般采用websocket為信令傳輸協(xié)議。

    • 這樣WebRTC client就可以直接注冊(cè)到支持WS的SIP Server上了。jssip 、sipml5都是這種解決方案。
  • 通過(guò)轉(zhuǎn)換網(wǎng)關(guān)實(shí)現(xiàn)協(xié)議的轉(zhuǎn)換,從而互通。一個(gè)開(kāi)源的網(wǎng)關(guān)項(xiàng)目就是 WebRTC2SIP。

    • WebRTC2SIP是一個(gè)功能很完善的網(wǎng)關(guān),既實(shí)現(xiàn)了信令層,也實(shí)現(xiàn)了媒體層,編碼轉(zhuǎn)換功能很強(qiáng)大,也可以直接當(dāng)做媒體網(wǎng)關(guān),用于編解碼,溝通兩端的媒體。

ICE服務(wù)器

  • 實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)通信的關(guān)鍵在于兩個(gè)瀏覽器之間能直接發(fā)送和接收數(shù)據(jù)包,但一般情況下,瀏覽器或手機(jī)都是通過(guò)路由器訪問(wèn)Internet,所以存在網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)。

  • NAT之內(nèi)的IP地址是私有地址,外部無(wú)法訪問(wèn)。分配給NAT的IP地址才是公共地址。NAT每次從內(nèi)部到外部轉(zhuǎn)發(fā)數(shù)據(jù)包時(shí)都使用公共地址。

  • 交互式建立連接(ICE)是一種標(biāo)準(zhǔn)穿透協(xié)議,它利用STUN和TURN服務(wù)器來(lái)建立連接。

  • STUN服務(wù)器可以遍歷NAT,獲取瀏覽器的候選地址,包括私有地址、外層NAT的公共 IP地址等。

  • 通信信令通道可以交換候選地址,瀏覽器一旦發(fā)送并收到了候選地址,就會(huì)開(kāi)始進(jìn)行連接檢查,若檢查成功,便使用該候選項(xiàng)發(fā)送媒體。

  • 在大多情況下,通過(guò)穿透可以建立直接對(duì)等連接。但是,若NAT或防火墻限制非常嚴(yán)格,無(wú)法建立連接,就只能通過(guò)TURN服務(wù)器中繼媒體。

媒體服務(wù)器

媒體服務(wù)器不是必須的,但在多方會(huì)話或需要對(duì)媒體做額外處理的情況下可以考慮加入。對(duì)于有多個(gè)瀏覽器參與的會(huì)議,可以采用一個(gè)集中式媒體服務(wù)器。在這種情況下,美國(guó)瀏覽器都只需與媒體服務(wù)器建立單個(gè)連接即可,這種結(jié)構(gòu)的優(yōu)勢(shì)是額能夠擴(kuò)展非常大的會(huì)話,同時(shí)可以在最大限度上減少當(dāng)有新加入者加入會(huì)話事美國(guó)瀏覽器所需的處理工作量。同時(shí),媒體服務(wù)器也可對(duì)媒體進(jìn)行分析、處理、保存等工作。

JavaScript接口

getUserMedia

通過(guò)調(diào)用navigator.getUserMedia()可以獲取視頻或音頻的數(shù)據(jù),constraints 參數(shù)可以選擇是否獲取視頻音頻。下面是一個(gè)簡(jiǎn)單的示例

var constraints = {
  audio: false,
  video: true
};
var video = document.querySelector('video');

function successCallback(stream) {

  if (window.URL) {
    video.src = window.URL.createObjectURL(stream);
  } else {
    video.src = stream;
  }
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}


navigator.getUserMedia(constraints, successCallback, errorCallback);

RTCPeerConnection

RTCPeerConnection是WebRTC中最重要的一個(gè)接口,用于確定ICE服務(wù)器、交換 SDP。連接過(guò)程如下:

創(chuàng)建RTCPeerConnection對(duì)象
  1. RTCPeerConnection的參數(shù)用于確定ICE服務(wù)器,下面是使用了 google 開(kāi)放的 STUN 服務(wù)器
let iceServer = {
    "iceServers": [{
        "url": "stun:stun.l.google.com:19302"
    }]
};
let pc = new RTCPeerConnection(servers);
  1. 將媒體流放入 RTCPeerConnection 對(duì)象中
pc.addStream(localStream);

通過(guò)offer和answer交換SDP描述符

  1. 甲和乙各自建立一個(gè)PC實(shí)例

    • 甲通過(guò)PC所提供的createOffer()方法建立一個(gè)包含甲的SDP描述符的offer信令。

    • 甲通過(guò)PC所提供的setLocalDescription()方法,將甲的SDP描述符交給甲的PC實(shí)例。

  2. 甲將offer信令通過(guò)服務(wù)器發(fā)送給乙

    • 乙將甲的offer信令中所包含的的SDP描述符提取出來(lái),通過(guò)PC所提供的 setRemoteDescription()方法交給乙的PC實(shí)例

    • 乙通過(guò)PC所提供的createAnswer()方法建立一個(gè)包含乙的SDP描述符 answer信令

    • 乙通過(guò)PC所提供的setLocalDescription()方法,將乙的SDP描述符交給乙的PC實(shí)例

  3. 乙將answer信令通過(guò)服務(wù)器發(fā)送給甲

甲接收到乙的answer信令后,將其中乙的SDP描述符提取出來(lái),調(diào)用setRemoteDescripttion()方法交給甲自己的PC實(shí)例。

ICE打洞

  1. 當(dāng)網(wǎng)絡(luò)候選可用時(shí),通過(guò)信令服務(wù)器將其發(fā)送到對(duì)方瀏覽器
pc.onicecandidate = function(event) {
  if (event.candidate) {
    sendToServer(event.candidate)
  }
};
  1. 當(dāng)接受到對(duì)方網(wǎng)絡(luò)候選時(shí),將其加入
let candidate = new RTCIceCandidate(candidate);
pc.addIceCandidate(candidate);
  1. 監(jiān)聽(tīng)對(duì)方發(fā)送的媒體是否可用,并播放媒體
pc.onaddstream = event => {
  remoteVideo.src = window.URL.createObjectURL(event.stream);
}

RTCDataChannel

RTCDataChannel是RTCPeerConnectionAPI的一部分,只有在創(chuàng)建了 RTCPeerConnection實(shí)例后才能創(chuàng)建數(shù)據(jù)通道。

數(shù)據(jù)通道可以用于發(fā)送文本或是文件。

pc = new RTCPeerConnection();
dc =  pc.createDataChannel('dc');
dc.onmessage = event => console.log(event.data);
dc.send('text');
dc.sed(new arraybuffer(32))

在另一端可以使用 ondatachannel 獲得 RTCDataChannel 對(duì)象

pc.ondatachannel = event => dc = event.channel;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容