零基礎(chǔ)入門:基于開源WebRTC滓窍,從0到1實(shí)現(xiàn)實(shí)時(shí)音視頻聊天功能

本文由微醫(yī)云技術(shù)團(tuán)隊(duì)前端工程師張宇航分享卖词,原題“從0到1打造一個(gè) WebRTC 應(yīng)用”,有修訂和改動(dòng)吏夯。

1此蜈、引言

去年初,突如其來(lái)的新冠肺炎疫情讓線下就醫(yī)渠道幾乎被切斷噪生,在此背景下裆赵,在線問(wèn)診模式快速解決了大量急需就醫(yī)病患的燃眉之急。而作為在線問(wèn)診中重要的一環(huán)——醫(yī)患之間的視頻問(wèn)診正是應(yīng)用了實(shí)時(shí)音視頻技術(shù)才得以實(shí)現(xiàn)跺嗽。

眾所周之战授,實(shí)時(shí)音視頻聊天技術(shù)門檻很高,一般的公司要想在短時(shí)間內(nèi)從零補(bǔ)齊這方面的技術(shù)短板相當(dāng)困難桨嫁,而開源音視頻工程WebRTC提供了這樣一個(gè)捷徑(包括筆者公司的產(chǎn)品在內(nèi)植兰,同樣是基于WebRTC技術(shù)才得以達(dá)成)。

本文將基于筆者公司開發(fā)的在線問(wèn)診產(chǎn)品中WebRTC技術(shù)的實(shí)踐經(jīng)驗(yàn)璃吧,講述的如何基于WebRTC從零開發(fā)一個(gè)實(shí)時(shí)音視頻聊天功能楣导。文章會(huì)從WebRTC的基本知識(shí)、技術(shù)原理開始畜挨,基于開源技術(shù)為你演示如何搭建一個(gè)WebRTC實(shí)時(shí)音視頻聊天功能筒繁。

2、本文源碼

完整源碼附件下載:https://gitee.com/instant_messaging_network/learn-webrtc

cdwebrtc-server

yarn

npm start

cdwebrtc-static

yarn

npm start

3巴元、知識(shí)準(zhǔn)備

3.1 音視頻理論基礎(chǔ)

在了解WebRTC技術(shù)之前毡咏,如果你對(duì)音視頻技術(shù)的基礎(chǔ)理論還不了解的話,建議優(yōu)先從以下幾篇入門文章先學(xué)一學(xué)逮刨。

零基礎(chǔ)呕缭,史上最通俗視頻編碼技術(shù)入門》(* 必讀)

寫給小白的實(shí)時(shí)音視頻技術(shù)入門提綱

零基礎(chǔ)入門:實(shí)時(shí)音視頻技術(shù)基礎(chǔ)知識(shí)全面盤點(diǎn)

實(shí)時(shí)音視頻面視必備:快速掌握11個(gè)視頻技術(shù)相關(guān)的基礎(chǔ)概念》(* 必讀)

愛(ài)奇藝技術(shù)分享:輕松詼諧,講解視頻編解碼技術(shù)的過(guò)去禀忆、現(xiàn)在和將來(lái)

3.2 什么是WebRTC

▲ 圖片引用自《了不起的WebRTC:生態(tài)日趨完善臊旭,或?qū)?shí)時(shí)音視頻技術(shù)白菜化

WebRTC(Web Real-Time Communication)是 Google 在 2010 年以 6820 萬(wàn)美元收購(gòu) VoIP 軟件開發(fā)商 Global IP Solutions 的 GIPS 引擎,并改名為“WebRTC”于 2011 年將其開源的旨在建立一個(gè)互聯(lián)網(wǎng)瀏覽器之間的音視頻和數(shù)據(jù)實(shí)時(shí)通信的平臺(tái)箩退。更多WebRTC介紹詳見(jiàn)《了不起的WebRTC:生態(tài)日趨完善离熏,或?qū)?shí)時(shí)音視頻技術(shù)白菜化》,本文不做贅述戴涝。

那么 WebRTC 能做些什么呢滋戳?

除了我們大家每天都在用的微信钻蔑、釘釘、qq這類傳統(tǒng)的IM社交軟件中的實(shí)時(shí)音視頻通話以外奸鸯,筆者公司產(chǎn)品中涉及醫(yī)療領(lǐng)域中的在線問(wèn)診/遠(yuǎn)程門診/遠(yuǎn)程會(huì)診咪笑,還有時(shí)下較為流行的互動(dòng)直播、在線教育等場(chǎng)景娄涩。除此之外窗怒,伴隨著 5G 的快速建設(shè),WebRTC 也為云游戲提供了很好的技術(shù)支撐蓄拣。

3.3 WebRTC的學(xué)習(xí)資源

WebRTC官方資源:

WebRTC開源工程官網(wǎng)

WebRTC開源工程源碼托管地址

WebRTC標(biāo)準(zhǔn)API在線文檔

其它WebRTC學(xué)習(xí)資源:

開源實(shí)時(shí)音視頻技術(shù)WebRTC在Windows下的簡(jiǎn)明編譯教程

WebRTC實(shí)時(shí)音視頻技術(shù)的整體架構(gòu)介紹

良心分享:WebRTC 零基礎(chǔ)開發(fā)者教程(中文)[附件下載]

4扬虚、WebRTC技術(shù)組成

來(lái)自WebRTC 官網(wǎng)的整體技術(shù)組成圖:

整個(gè)WebRTC大致可以分為以下 3 部分:

1)紫色提供給 Web 前端開發(fā)使用的 API;

2)藍(lán)色實(shí)線部分提供各大瀏覽器廠商使用的 API球恤;

3)藍(lán)色虛線部分包含 3 部分:音頻引擎辜昵、視頻引擎、網(wǎng)絡(luò)傳輸 (Transport)咽斧,都可以自定義實(shí)現(xiàn)堪置。

因篇幅有限,本節(jié)不深入討論张惹,有興趣可以讀讀《WebRTC實(shí)時(shí)音視頻技術(shù)的整體架構(gòu)介紹》舀锨。

5、WebRTC的P2P通信原理

5.1 P2P通信的技術(shù)難點(diǎn)

P2P通信即點(diǎn)對(duì)點(diǎn)通信宛逗。

要實(shí)現(xiàn)兩個(gè)不同網(wǎng)絡(luò)環(huán)境(具有麥克風(fēng)雁竞、攝像頭設(shè)備)的客戶端(可能是不同的 Web 瀏覽器或者手機(jī) App)之間的實(shí)時(shí)音視頻通信的難點(diǎn)在哪里、需要解決哪些問(wèn)題拧额?

總結(jié)一下,主要是下面這3個(gè)問(wèn)題:

1)怎么知道彼此的存在也就是如何發(fā)現(xiàn)對(duì)方彪腔?

2)彼此音視頻編解碼能力如何溝通侥锦?

3)音視頻數(shù)據(jù)如何傳輸,怎么能讓對(duì)方看得自己德挣?

下面我們將逐個(gè)討論這3個(gè)問(wèn)題恭垦。

5.2 怎么知道彼此的存在(也就是如何發(fā)現(xiàn)對(duì)方)?

對(duì)于問(wèn)題 1:WebRTC 雖然支持端對(duì)端通信格嗅,但是這并不意味著 WebRTC 不再需要服務(wù)器番挺。

在P2P通信的過(guò)程中,雙方需要交換一些元數(shù)據(jù)比如媒體信息屯掖、網(wǎng)絡(luò)數(shù)據(jù)等等信息,我們通常稱這一過(guò)程叫做“信令(signaling)”玄柏。

對(duì)應(yīng)的服務(wù)器即“信令服務(wù)器 (signaling server)”,通常也有人將之稱為“房間服務(wù)器”贴铜,因?yàn)樗粌H可以交換彼此的媒體信息和網(wǎng)絡(luò)信息粪摘,同樣也可以管理房間信息瀑晒。

比如:

1)通知彼此 who 加入了房間;

2)who 離開了房間

3)告訴第三方房間人數(shù)是否已滿是否可以加入房間徘意。

為了避免出現(xiàn)冗余苔悦,并最大限度地提高與已有技術(shù)的兼容性,WebRTC 標(biāo)準(zhǔn)并沒(méi)有規(guī)定信令方法和協(xié)議椎咧。在本文后面的實(shí)踐章節(jié)會(huì)利用 Koa 和?Socket.io?技術(shù)實(shí)現(xiàn)一個(gè)信令服務(wù)器玖详。

5.3 彼此音視頻編解碼能力如何溝通?

對(duì)于問(wèn)題 2:我們首先要知道的是勤讽,不同瀏覽器對(duì)于音視頻的編解碼能力是不同的蟋座。

比如:?Peer-A 端支持?H264、VP8?等多種編碼格式地技,而 Peer-B 端支持 H264蜈七、VP9 等格式。為了保證雙方都可以正確的編解碼莫矗,最簡(jiǎn)單的辦法即取它們所都支持格式的交集-H264飒硅。

在 WebRTC 中:有一個(gè)專門的協(xié)議,稱為Session Description Protocol(SDP)作谚,可以用于描述上述這類信息三娩。

因此:參與音視頻通訊的雙方想要了解對(duì)方支持的媒體格式,必須要交換 SDP 信息妹懒。而交換 SDP 的過(guò)程雀监,通常稱之為媒體協(xié)商。

5.4 音視頻數(shù)據(jù)如何傳輸眨唬,怎么能讓對(duì)方看得自己会前?

對(duì)于問(wèn)題 3:其本質(zhì)上就是網(wǎng)絡(luò)協(xié)商的過(guò)程,即參與音視頻實(shí)時(shí)通信的雙方要了解彼此的網(wǎng)絡(luò)情況匾竿,這樣才有可能找到一條相互通訊的鏈路瓦宜。

理想的網(wǎng)絡(luò)情況是每個(gè)瀏覽器的電腦都有自己的私有公網(wǎng) IP 地址,這樣的話就可以直接進(jìn)行點(diǎn)對(duì)點(diǎn)連接岭妖。

但實(shí)際上:出于網(wǎng)絡(luò)安全和 IPV4 地址不夠的考慮临庇,我們的電腦與電腦之間或大或小都是在某個(gè)局域網(wǎng)內(nèi),需要NAT(“Network Address Translation,” 中文譯為“網(wǎng)絡(luò)地址轉(zhuǎn)換”)昵慌。在 WebRTC 中我們使用 ICE 機(jī)制建立網(wǎng)絡(luò)連接假夺。

那么何為 ICE?

ICE (Interactive Connecctivity Establishment, 交互式連接建立)斋攀,ICE 不是一種協(xié)議已卷,而是整合了 STUN 和 TURN 兩種協(xié)議的框架。

其中:STUN(Sesssion Traversal Utilities for NAT, NAT 會(huì)話穿越應(yīng)用程序)蜻韭,它允許位于 NAT(或多重 NAT)后的客戶端找出自己對(duì)應(yīng)的公網(wǎng) IP 地址和端口悼尾,也就是俗稱的P2P“打洞”柿扣。

但是:如果 NAT 類型是對(duì)稱型的話,那么就無(wú)法打洞成功闺魏。這時(shí)候 TURN 就派上用場(chǎng)了未状,TURN(Traversal USing Replays around NAT)是 STUN/RFC5389?的一個(gè)拓展協(xié)議在其基礎(chǔ)上添加了 Replay(中繼)功能。

簡(jiǎn)單來(lái)說(shuō):其目的就是解決對(duì)稱 NAT 無(wú)法穿越的問(wèn)題析桥,在 STUN 分配公網(wǎng) IP 失敗后司草,可以通過(guò) TURN 服務(wù)器請(qǐng)求公網(wǎng) IP 地址作為中繼地址。

在 WebRTC 中有三種類型的 ICE 候選者泡仗,它們分別是:

1)主機(jī)候選者:表示的是本地局域網(wǎng)內(nèi)的 IP 地址及端口戈咳。它是三個(gè)候選者中優(yōu)先級(jí)最高的久窟,也就是說(shuō)在 WebRTC 底層贴彼,首先會(huì)嘗試本地局域網(wǎng)內(nèi)建立連接泛粹;

2)反射候選者:表示的是獲取 NAT 內(nèi)主機(jī)的外網(wǎng) IP 地址和端口。其優(yōu)先級(jí)低于 主機(jī)候選者截亦。也就是說(shuō)當(dāng) WebRTC 嘗試本地連接不通時(shí)爬泥,會(huì)嘗試通過(guò)反射候選者獲得的 IP 地址和端口進(jìn)行連接;

3)中繼候選者:表示的是中繼服務(wù)器的 IP 地址與端口崩瓤,即通過(guò)服務(wù)器中轉(zhuǎn)媒體數(shù)據(jù)袍啡。當(dāng) WebRTC 客戶端通信雙方無(wú)法穿越 P2P NAT 時(shí),為了保證雙方可以正常通訊却桶,此時(shí)只能通過(guò)服務(wù)器中轉(zhuǎn)來(lái)保證服務(wù)質(zhì)量了境输。

從上圖我們可以看出:在非本地局域網(wǎng)內(nèi) WebRTC 通過(guò) STUN server 獲得自己的外網(wǎng) IP 和端口,然后通過(guò)信令服務(wù)器與遠(yuǎn)端的 WebRTC 交換網(wǎng)絡(luò)信息颖系,之后雙方就可以嘗試建立 P2P 連接了嗅剖。當(dāng) NAT 穿越不成功時(shí),則會(huì)通過(guò) Relay server (TURN)中轉(zhuǎn)嘁扼。

值得一提的是:在 WebRTC 中網(wǎng)絡(luò)信息通常用candidate來(lái)描述窗悯,而上述圖中的 STUN server 和 Replay server 也都可以是同一個(gè) server。在文末的實(shí)踐章節(jié)即是采用了集成了 STUN(打洞)和 TURN(中繼)功能的開源項(xiàng)目?coturn偷拔。

綜上對(duì)三個(gè)問(wèn)題的解釋,我們可以用下圖來(lái)說(shuō)明 WebRTC 點(diǎn)對(duì)點(diǎn)通信的基本原理亏钩。

簡(jiǎn)而言之:就是通過(guò) WebRTC 提供的 API 獲取各端的媒體信息 SDP 以及 網(wǎng)絡(luò)信息 candidate 莲绰,并通過(guò)信令服務(wù)器交換,進(jìn)而建立了兩端的連接通道完成實(shí)時(shí)視頻語(yǔ)音通話姑丑。

PS:有關(guān)P2P的相關(guān)知識(shí)蛤签,可以深入學(xué)習(xí)一下文章:

P2P技術(shù)詳解(一):NAT詳解——詳細(xì)原理、P2P簡(jiǎn)介

P2P技術(shù)詳解(二):P2P中的NAT穿越(打洞)方案詳解(基本原理篇)

P2P技術(shù)詳解(三):P2P中的NAT穿越(打洞)方案詳解(進(jìn)階分析篇)

P2P技術(shù)詳解(四):P2P技術(shù)之STUN栅哀、TURN震肮、ICE詳解

通俗易懂:快速理解P2P技術(shù)中的NAT穿透原理

6称龙、WebRTC的幾個(gè)重要的API

6.1 音視頻采集 API

音視頻采集 API,即 MediaDevices.getUserMedia()戳晌。

示例代碼:

const constraints = {

????????video: true,

????????audio: true

};

//?? 非安全模式(非https/localhost)下 navigator.mediaDevices 會(huì)返回 undefined

try{

????????const stream = await navigator.mediaDevices.getUserMedia(constraints);

????????document.querySelector('video').srcObject = stream;

????}?? catch(error) {

????????console.error(error);

????}

6.2 獲取音視頻設(shè)備輸入輸出列表

獲取音視頻設(shè)備輸入輸出列表API鲫尊,即 MediaDevices.enumerateDevices()

示例代碼:

try{

????????const devices = await navigator.mediaDevices.enumerateDevices();

????????this.videoinputs = devices.filter(device => device.kind === 'videoinput');

????????this.audiooutputs = devices.filter(device => device.kind === 'audiooutput');

????????this.audioinputs = devices.filter(device => device.kind === 'audioinput');

??????} catch(error) {

????????console.error(error);

??????}

6.3 RTCPeerConnection

RTCPeerConnection?作為創(chuàng)建點(diǎn)對(duì)點(diǎn)連接的 API,是我們實(shí)現(xiàn)音視頻實(shí)時(shí)通信的關(guān)鍵沦偎。

在本文的實(shí)踐章節(jié)中疫向,主要運(yùn)用到了以下方法。

媒體協(xié)商方法:

createOffer

createAnswer

localDesccription

remoteDesccription

重要事件:

onicecandidate

onaddstream

在上個(gè)章節(jié)的描述中可以知道 P2P 通信中最重要的一個(gè)環(huán)節(jié)就是交換媒體信息豪嚎。

媒體協(xié)商原理:

從上圖不難發(fā)現(xiàn)搔驼,整個(gè)媒體協(xié)商過(guò)程可以簡(jiǎn)化為三個(gè)步驟對(duì)應(yīng)上述四個(gè)媒體協(xié)商方法。

具體是:

1)呼叫端 Amy 創(chuàng)建 Offer(createOffer)并將 offer 消息(內(nèi)容是呼叫端 Amy 的 SDP 信息)通過(guò)信令服務(wù)器傳送給接收端 Bob,同時(shí)調(diào)用 setLocalDesccription 將含有本地 SDP 信息的 Offer 保存起來(lái)侈询;

2)接收端 Bob 收到對(duì)端的 Offer 信息后調(diào)用 setRemoteDesccription 方法將含有對(duì)端 SDP 信息的 Offer 保存起來(lái)舌涨,并創(chuàng)建 Answer(createAnswer)并將 Answer 消息(內(nèi)容是接收端 Bob 的 SDP 信息)通過(guò)信令服務(wù)器傳送給呼叫端 Amy;

3)呼叫端 Amy 收到對(duì)端的 Answer 信息后調(diào)用 setRemoteDesccription 方法將含有對(duì)端 SDP 信息的 Answer 保存起來(lái)扔字。

經(jīng)過(guò)上述三個(gè)步驟囊嘉,則完成了 P2P 通信過(guò)程中的媒體協(xié)商部分。

實(shí)際上:在呼叫端以及接收端調(diào)用 setLocalDesccription 同時(shí)也開始了收集各端自己的網(wǎng)絡(luò)信息(candidate)啦租,然后各端通過(guò)監(jiān)聽事件?onicecandidate?收集到各自的 candidate 并通過(guò)信令服務(wù)器傳送給對(duì)端哗伯,進(jìn)而打通 P2P 通信的網(wǎng)絡(luò)通道,并通過(guò)監(jiān)聽?onaddstream?事件拿到對(duì)方的視頻流進(jìn)而完成了整個(gè)視頻通話過(guò)程篷角。

7焊刹、動(dòng)手編碼實(shí)踐

提示:本節(jié)所涉及的完整源碼,請(qǐng)從本文“2恳蹲、本文源碼”一節(jié)的附件下載虐块。

7.1 coturn 服務(wù)器的搭建

注意:如果只是本地局域網(wǎng)測(cè)試則無(wú)需搭建 [url=%5Burl=https://github.com/coturn/%5Dcoturn[/url]]coturn[/url] 服務(wù)器,如果需要外網(wǎng)訪問(wèn)在搭建 coturn 服務(wù)器之前你需要購(gòu)買一臺(tái)云主機(jī)以及綁定支持 https 訪問(wèn)的域名嘉蕾。以下是筆者自己搭建的過(guò)程贺奠,感興趣的可以參照著自已實(shí)踐一次。

coturn 服務(wù)器的搭建主要是為了解決 NAT 無(wú)法穿越的問(wèn)題错忱。

其安裝也較為簡(jiǎn)單:

1. git clone [url=https://github.com/coturn/coturn.git]https://github.com/coturn/coturn.git[/url]

2. cdcoturn/

3. ./configure--prefix=/usr/local/coturn

4. make-j 4

5. makeinstall

//生成 key

6. openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes

7.2 coturn 服務(wù)配置

我的配置如下:

vim /usr/local/coturn/etc/turnserver.conf

listening-port=3478

external-ip=xxx.xxx //你的主機(jī)公網(wǎng) IP

user=xxx:xxx //賬號(hào): 密碼

realm=xxx.com //你的域名

7.3 啟動(dòng) coturn 服務(wù)

我的啟動(dòng)過(guò)程:

1. cd/usr/local/coturn/bin/

2. ./turnserver-c ../etc/turnserver.conf

//注意:云主機(jī)內(nèi)的 TCP 和 UDP 的 3478 端口都要開啟

7.4 實(shí)踐代碼

在編寫代碼之前儡率,結(jié)合上述章節(jié) WebRTC 點(diǎn)對(duì)點(diǎn)通信的基本原理,可以得出以下流程圖以清。

從圖中不難看出儿普,假設(shè) PeerA 為發(fā)起方,PeerB 為接收方要實(shí)現(xiàn) WebRTC 點(diǎn)對(duì)點(diǎn)的實(shí)時(shí)音視頻通信掷倔,信令(Signal)服務(wù)器是必要的眉孩,以管理房間信息以及轉(zhuǎn)發(fā)網(wǎng)絡(luò)信息和媒體信息的。

在本文中是利用 koa 及 socket.io 搭建的信令服務(wù)器:

// server 端 server.js

const Koa = require('koa');

const socket = require('socket.io');

const http = require('http');

const app = newKoa();

const httpServer = http.createServer(app.callback()).listen(3000, ()=>{});

socket(httpServer).on('connection', (sock)=>{

????// ....

});


// client 端 socket.js

import io from 'socket.io-client';

const socket = io.connect(window.location.origin);

export defaultsocket;

在搭建好信令服務(wù)器后,結(jié)合流程圖浪汪,有以下步驟巴柿。

步驟1:PeerA 和 PeerB 端分別連接信令服務(wù)器,信令服務(wù)器記錄房間信息:

// server 端 server.js

socket(httpServer).on('connection', (sock)=>{

????// 用戶離開房間

????sock.on('userLeave',()=>{

????????// ...

????});

????// 檢查房間是否可加入

????sock.on('checkRoom',()=>{

????????// ...

????});

????// ....

});

// client 端 Room.vue

import socket from '../utils/socket.js';


// 服務(wù)端告知用戶是否可加入房間

socket.on('checkRoomSuccess',()=>{

????????// ...

});

// 服務(wù)端告知用戶成功加入房間

socket.on('joinRoomSuccess',()=>{

????????// ...

});

//....

步驟2:A 端作為發(fā)起方向接收方 B 端發(fā)起視頻邀請(qǐng)死遭,在得到 B 同意視頻請(qǐng)求后广恢,雙方都會(huì)創(chuàng)建本地的 RTCPeerConnection,添加本地視頻流殃姓,其中發(fā)送方會(huì)創(chuàng)建 offer 設(shè)置本地 sdp 信息描述袁波,并通過(guò)信令服務(wù)器將自己的 SDP 信息發(fā)送給對(duì)端

socket.on('answerVideo', async (user) => {

????????VIDEO_VIEW.showInvideoModal();

????????// 創(chuàng)建本地視頻流信息

????????const localStream = await this.createLocalVideoStream();

????????this.localStream = localStream;

????????document.querySelector('#echat-local').srcObject = this.localStream;

????????this.peer = newRTCPeerConnection();

????????this.initPeerListen();

????????this.peer.addStream(this.localStream);

????????if(user.sockId === this.sockId) {

??????????// 接收方

????????} else{

??????????// 發(fā)送方 創(chuàng)建 offer

??????????const offer = await this.peer.createOffer(this.offerOption);

??????????await this.peer.setLocalDescription(offer);

??????????socket.emit('receiveOffer', { user: this.user, offer });

????????}

?});

步驟3:前面提起過(guò)其實(shí)在調(diào)用 setLocalDescription 的同時(shí),也會(huì)開始收集自己端的網(wǎng)絡(luò)信息(candidate)蜗侈,如果在非局域網(wǎng)內(nèi)或者網(wǎng)絡(luò)“打洞”不成功篷牌,還會(huì)嘗試向 Stun/Turn 服務(wù)器發(fā)起請(qǐng)求,也就是收集“中繼候選者”踏幻,因此在創(chuàng)建 RTCPeerConnection 我們還需要監(jiān)聽 ICE 網(wǎng)絡(luò)候選者的事件:

init PeerListen () {

??????// 收集自己的網(wǎng)絡(luò)信息并發(fā)送給對(duì)端

??????this.peer.onicecandidate = (event) => {

????????if(event.candidate) { socket.emit('addIceCandidate', { candidate: event.candidate, user: this.user }); }

??????};

??????// ....

????}

步驟4:當(dāng)接收方 B 端通過(guò)信令服務(wù)器拿到對(duì)端發(fā)送方 A 端的含有 SDP 的 offer 信息后則會(huì)調(diào)用 setRemoteDescription 存儲(chǔ)對(duì)端的 SDP 信息枷颊,創(chuàng)建及設(shè)置本地的 SDP 信息,并通過(guò)信令服務(wù)器傳送含有本地 SDP 信息的 answer:

socket.on('receiveOffer', async (offer) => {

????????await this.peer.setRemoteDescription(offer);

????????const answer = await this.peer.createAnswer();

????????await this.peer.setLocalDescription(answer);

????????socket.emit('receiveAnsewer', { answer, user: this.user });

?});

步驟5:當(dāng)發(fā)起方 A 通過(guò)信令服務(wù)器接收到接收方 B 的 answer 信息后則也會(huì)調(diào)用 setRemoteDescription,這樣雙方就完成了 SDP 信息的交換:

socket.on('receiveAnsewer', (answer) => {

????????this.peer.setRemoteDescription(answer);

??????});

步驟6:當(dāng)雙方 SDP 信息交換完成并且監(jiān)聽 icecandidate 收集到網(wǎng)絡(luò)候選者通過(guò)信令服務(wù)器交換后该面,則會(huì)拿到彼此的視頻流:

socket.on('addIceCandidate', async (candidate) => {

????????await this.peer.addIceCandidate(candidate);

});

this.peer.onaddstream = (event) => {

????????// 拿到對(duì)方的視頻流

????????document.querySelector('#remote-video').srcObject = event.stream;

};

8夭苗、本文小結(jié)

經(jīng)過(guò)上個(gè)章節(jié)的6個(gè)步驟,即可完成一個(gè)基于WebRTC的完整 P2P 視頻實(shí)時(shí)通話功能(代碼可通過(guò):本節(jié)所涉及的完整源碼隔缀,請(qǐng)從本文“2题造、本文源碼”一節(jié)的附件下載)。

值得一提的是:代碼中的?VIDEO_VIEW?是專注于視頻UI層的JS SDK猾瘸,包含了發(fā)起視頻 Modal界赔、接收視頻 Modal、視頻中 Modal牵触,其是從筆者線上 Web 視頻問(wèn)診產(chǎn)品所使用的 JS SDK 抽離出來(lái)的淮悼。

本文只是簡(jiǎn)單地介紹了WebRTC P2P的通信基本原理以及簡(jiǎn)單的代碼實(shí)踐,事實(shí)上我們生產(chǎn)環(huán)境所使用的 SDK 不僅支持點(diǎn)對(duì)點(diǎn)通信揽思,還支持多人視頻通話袜腥,屏幕共享等功能這些都是基于WebRTC實(shí)現(xiàn)的。

9钉汗、參考資料

[1]?WebRTC標(biāo)準(zhǔn)API在線文檔

[2]?WebRTC in the real world: STUN, TURN and signaling

[3]?WebRTC 信令控制與 STUN/TURN 服務(wù)器搭建

[4]?了不起的WebRTC:生態(tài)日趨完善羹令,或?qū)?shí)時(shí)音視頻技術(shù)白菜化

[5]?開源實(shí)時(shí)音視頻技術(shù)WebRTC在Windows下的簡(jiǎn)明編譯教程

[6]?WebRTC實(shí)時(shí)音視頻技術(shù)的整體架構(gòu)介紹

[7]?良心分享:WebRTC 零基礎(chǔ)開發(fā)者教程(中文)[附件下載]

[8]?P2P技術(shù)詳解(二):P2P中的NAT穿越(打洞)方案詳解(基本原理篇)

[9]?P2P技術(shù)詳解(四):P2P技術(shù)之STUN、TURN损痰、ICE詳解

[10]?通俗易懂:快速理解P2P技術(shù)中的NAT穿透原理

(本文同步發(fā)布于:http://www.52im.net/thread-3680-1-1.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末特恬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子徐钠,更是在濱河造成了極大的恐慌,老刑警劉巖役首,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尝丐,死亡現(xiàn)場(chǎng)離奇詭異显拜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)爹袁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門远荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人失息,你說(shuō)我怎么就攤上這事譬淳。” “怎么了盹兢?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵邻梆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绎秒,道長(zhǎng)浦妄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任见芹,我火速辦了婚禮剂娄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玄呛。我一直安慰自己阅懦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布徘铝。 她就那樣靜靜地躺著耳胎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庭砍。 梳的紋絲不亂的頭發(fā)上场晶,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音怠缸,去河邊找鬼诗轻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛揭北,可吹牛的內(nèi)容都是我干的扳炬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼搔体,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恨樟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起疚俱,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤劝术,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體养晋,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衬吆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绳泉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逊抡。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖零酪,靈堂內(nèi)的尸體忽然破棺而出冒嫡,到底是詐尸還是另有隱情,我是刑警寧澤四苇,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布孝凌,位于F島的核電站,受9級(jí)特大地震影響蛔琅,放射性物質(zhì)發(fā)生泄漏胎许。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一罗售、第九天 我趴在偏房一處隱蔽的房頂上張望辜窑。 院中可真熱鬧,春花似錦寨躁、人聲如沸穆碎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)所禀。三九已至,卻和暖如春放钦,著一層夾襖步出監(jiān)牢的瞬間色徘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工操禀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留褂策,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓颓屑,卻偏偏與公主長(zhǎng)得像斤寂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揪惦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言: WebRTC遍搞,名稱源自網(wǎng)頁(yè)實(shí)時(shí)通信(Web Real-Time Communication)的縮寫,簡(jiǎn)而言...
    涂耀輝閱讀 50,608評(píng)論 134 430
  • WebRTC通話最典型的應(yīng)用場(chǎng)景應(yīng)該是一對(duì)一視頻通話器腋,如微信視頻溪猿,QQ視頻等钩杰。我們回想一下日常生活中是怎么進(jìn)行“實(shí)...
    詩(shī)人和酒閱讀 439評(píng)論 0 0
  • iOS 基于WebRTC的音視頻通信 總結(jié)篇(2020最新) 附上我的swfit項(xiàng)目, 項(xiàng)目里面有整個(gè)swift應(yīng)...
    coder_xiang閱讀 21,333評(píng)論 15 84
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn)诊县,但是人生放棄了冒險(xiǎn)榜苫,也就放棄了無(wú)數(shù)的可能。 ...
    yichen大刀閱讀 6,033評(píng)論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,870評(píng)論 0 2