初探WebRTC

WebRTC 概述

WebRTC,名稱源自網(wǎng)頁(yè)即時(shí)通信(Web Real-Time Communication的縮寫),是一個(gè)支持網(wǎng)頁(yè)瀏覽器進(jìn)行實(shí)時(shí)語(yǔ)音對(duì)話或視頻對(duì)話的API。它于2011年6月1日開(kāi)源并在Google、Mozilla、Opera支持下被納入萬(wàn)維網(wǎng)聯(lián)盟的W3C推薦標(biāo)準(zhǔn)。
WebRTC提供了視頻會(huì)議的核心技術(shù),包括音視頻的采集、編解碼、網(wǎng)絡(luò)傳輸、顯示等功能, 并且還支持跨平臺(tái):windows,linux,mac,android。


WebRTC架構(gòu)圖

從架構(gòu)圖中我們看到,WebRTC幫我實(shí)現(xiàn)了音頻引擎,視頻引擎,網(wǎng)絡(luò)傳輸引擎,封裝了上層API,讓開(kāi)發(fā)者能夠基于瀏覽器(Chrome\FireFox...)輕易快捷開(kāi)發(fā)出豐富的實(shí)時(shí)多媒體應(yīng)用,而無(wú)需下載安裝任何插件,也無(wú)需關(guān)注多媒體的數(shù)字信號(hào)處理過(guò)程,只需編寫簡(jiǎn)單的Javascript程序即可實(shí)現(xiàn)。

WebRTC原理

瀏覽器點(diǎn)對(duì)點(diǎn)P2P的信道(peer-to-peer),信道可發(fā)送任何數(shù)據(jù)并無(wú)需經(jīng)過(guò)服務(wù)器。WebRTC的實(shí)現(xiàn)是建立客戶端之間的直接連接而無(wú)需服務(wù)器中轉(zhuǎn)的,即P2P。所以要求彼此知道對(duì)方外網(wǎng)地址,而計(jì)算機(jī)大多位于NAT之后,只有少數(shù)主機(jī)擁有外網(wǎng)地址,這就需要一種可以穿透NAT技術(shù)。



NAT打洞

在處于使用NAT設(shè)備的私有TCP/IP網(wǎng)絡(luò)中的主機(jī)之間建立連接時(shí)需使用NAT穿越。NAT的行為是非標(biāo)準(zhǔn)化的,穿越技術(shù)大多使用公共服務(wù)器,使全球任何地方都能訪問(wèn)得到IP地址, 在RTCPeerConnection中實(shí)用ICE框架來(lái)保證RTCPeerConnection實(shí)現(xiàn)NAT穿越。

常見(jiàn)的NAT穿越技術(shù)有:應(yīng)用層網(wǎng)關(guān)(ALG)方式、M1DCOM (Middle-Bax Communications)代理方式、STUN方式、TURN方式、FuIIProxy方式、ICE方式。其中ICE己經(jīng)被公認(rèn)為在非對(duì)稱性NAT環(huán)境下首選的NAT穿越解決方案。ICE本身是一種方法,它綜合運(yùn)用STUN、 TURN等協(xié)議來(lái)提供一個(gè)通用的解決方案,使之在最適合的情況下工作,以彌補(bǔ)單獨(dú)使用其中任何一種所帶來(lái)的固有缺陷。

WebRTC建立連接

點(diǎn)對(duì)點(diǎn)連接過(guò)程

1.ClientA 創(chuàng)建WebRTC對(duì)象和RTC數(shù)據(jù)通道,并綁定一些事件

// 創(chuàng)建WebRTC對(duì)象
const pc = new RTCPeerConnection();

// 創(chuàng)建WebRTC數(shù)據(jù)通道,可以傳輸自定義數(shù)據(jù)
const dc = pc.createDataChannel("channel");

// 數(shù)據(jù)通道開(kāi)啟
dc.onopen = () => console.log("Data Channel Opened");

// 數(shù)據(jù)通道收到數(shù)據(jù)的事件
dc.onmessage = (e) => console.log("Get Message:", e.data);

// SDP變化的事件
pc.onicegatheringstatechange = () => {
   if (pc.iceGatheringState === "complete") {  // 在SPD創(chuàng)建完成的時(shí)候打印他
      console.log(JSON.stringify(pc.localDescription));
   }
}

2.ClientA 創(chuàng)建Offer
使用pc.createOffer()來(lái)創(chuàng)建Offer,并且調(diào)用setLocalDescription將Offer綁定在本地SDP,執(zhí)行完成后可以看到在控制臺(tái)中打印了你的Offer,復(fù)制這端Offer,我們可以來(lái)寫ClientB的代碼了

/**
 * 創(chuàng)建Offer
 * @return {Promise<void>}
 */
async function createOffer() {
   const offer = await pc.createOffer();
   await pc.setLocalDescription(offer);
}

3.ClientB 創(chuàng)建WebRTC對(duì)象和RTC數(shù)據(jù)通道,并綁定一些事件
由于ClientA已經(jīng)有數(shù)據(jù)通道了,所以ClientB不需要自己創(chuàng)建,通過(guò)pc.ondatachannel綁定監(jiān)聽(tīng)事件

const pc = new RTCPeerConnection();

let dc = null;

// 同樣的監(jiān)聽(tīng)SDP變化的事件,在SPD創(chuàng)建完成的時(shí)候打印他
pc.onicegatheringstatechange = () => {
   if (pc.iceGatheringState === "complete") {
      console.log(JSON.stringify(pc.localDescription));
   }
}

// 監(jiān)聽(tīng)數(shù)據(jù)通道的事件,并添加上事件,保存一下這條數(shù)據(jù)通道
pc.ondatachannel = (e) => {
   console.log("data channel");
   dc = e.channel;
   dc.onmessage = (e) => console.log("get message", e.data);
   dc.onopen = async (e) => console.log("channel opened");
}

4.ClientB 綁定Offer
通過(guò)setRemoteDescription來(lái)設(shè)置遠(yuǎn)端OfferSDP

async function setOffer() {
   await pc.setRemoteDescription(JSON.parse(需要綁定的offer));
   console.log("Offer Set");
}

5.ClientB 創(chuàng)建Answer
使用createAnswer來(lái)創(chuàng)建一個(gè)Answer,并且用setLocalDescription設(shè)置到本地SDP,我們?cè)谠O(shè)置完Offer后立刻創(chuàng)建Answer,經(jīng)過(guò)上面的過(guò)程,可以在控制臺(tái)中看到打印的本地Answer,復(fù)制這個(gè)Answer,我們?nèi)lientA綁定它

async function setOffer() {
   await pc.setRemoteDescription(JSON.parse(需要綁定的offer));
   console.log("Offer Set");
   await createAnswer();
}

async function createAnswer() {
   const answer = await pc.createAnswer();
   await pc.setLocalDescription(answer);
}

6.ClientA 綁定Answer,建立P2P連接
在通過(guò)setRemoteDescription設(shè)置遠(yuǎn)端AnswerSDP,這樣就完成了數(shù)據(jù)通道連接,然后我們就可以通過(guò)dc.send('要發(fā)送的消息')進(jìn)行消息傳遞

async function setAnswer() {
   await pc.setRemoteDescription(JSON.parse(需要綁定的Answer));
   console.log("Answer Set");
}

7.將音視頻流推送給WebRTC,并接收對(duì)方傳來(lái)的音視頻流

async function openVideo() {
   const stream = await navigator.mediaDevices.getUserMedia({
      video: true, audio: true
   });
   myVideo.srcObject = stream;
   stream.getTracks().forEach((track) => {
      pc.addTrack(track, stream);
   });
}

// 通過(guò)監(jiān)聽(tīng)track,表示有音頻流進(jìn)來(lái)
pc.ontrack = (e) => {
   console.log("track");
   video.srcObject = e.streams[0];
}
最后編輯于
?著作權(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)容

  • 權(quán)限申請(qǐng): Info.plist中添加 Camera和Microphone訪問(wèn)權(quán)限 引入WebRTC庫(kù): 1、通過(guò)...
    呂建雄閱讀 8,275評(píng)論 4 11
  • 本篇主要介紹筆者在iOS開(kāi)發(fā)中使用WebRTC實(shí)現(xiàn)音視頻通話功能涉及的相關(guān)技術(shù),主要包括:1)Socket2)...
    江山風(fēng)雨閱讀 2,713評(píng)論 0 3
  • 什么是WebRTC WebRTC是一個(gè)由Google發(fā)起的實(shí)時(shí)通訊解決方案,其中包含視頻音頻采集,編解碼,數(shù)據(jù)傳輸...
    private_object閱讀 587評(píng)論 0 0
  • 參考Web前端的WebRTC攻略(一)基礎(chǔ)介紹[https://zhuanlan.zhihu.com/p/9105...
    合肥黑閱讀 1,258評(píng)論 1 1
  • WebRTC 是網(wǎng)絡(luò)實(shí)時(shí)通信(Web Real-Time Communication)的縮寫,通過(guò)它 Web 開(kāi)發(fā)...
    皺巴巴閱讀 2,089評(píng)論 0 2

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