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

本文由微醫(yī)云技術(shù)團(tuán)隊(duì)前端工程師張宇航分享,原題“從0到1打造一個(gè) WebRTC 應(yīng)用”,有修訂和改動(dòng)。
1、引言
去年初,突如其來的新冠肺炎疫情讓線下就醫(yī)渠道幾乎被切斷,在此背景下,在線問診模式快速解決了大量急需就醫(yī)病患的燃眉之急。而作為在線問診中重要的一環(huán)——醫(yī)患之間的視頻問診正是應(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ā)的在線問診產(chǎn)品中WebRTC技術(shù)的實(shí)踐經(jīng)驗(yàn),講述的如何基于WebRTC從零開發(fā)一個(gè)實(shí)時(shí)音視頻聊天功能。文章會(huì)從WebRTC的基本知識(shí)、技術(shù)原理開始,基于開源技術(shù)為你演示如何搭建一個(gè)WebRTC實(shí)時(shí)音視頻聊天功能。

學(xué)習(xí)交流:
- 即時(shí)通訊/推送技術(shù)開發(fā)交流5群:215477170?[推薦]
- 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK
(本文同步發(fā)布于:http://www.52im.net/thread-3680-1-1.html)
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ǔ)概念》(* 必讀)
《愛奇藝技術(shù)分享:輕松詼諧,講解視頻編解碼技術(shù)的過去、現(xiàn)在和將來》
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介紹詳見《了不起的WebRTC:生態(tài)日趨完善,或?qū)?shí)時(shí)音視頻技術(shù)白菜化》,本文不做贅述。
那么 WebRTC 能做些什么呢?
除了我們大家每天都在用的微信、釘釘、qq這類傳統(tǒng)的IM社交軟件中的實(shí)時(shí)音視頻通話以外,筆者公司產(chǎn)品中涉及醫(yī)療領(lǐng)域中的在線問診/遠(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ù)組成
來自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)在哪里、需要解決哪些問題?
總結(jié)一下,主要是下面這3個(gè)問題:
1)怎么知道彼此的存在也就是如何發(fā)現(xiàn)對(duì)方?
2)彼此音視頻編解碼能力如何溝通?
3)音視頻數(shù)據(jù)如何傳輸,怎么能讓對(duì)方看得自己?
下面我們將逐個(gè)討論這3個(gè)問題。
5.2 怎么知道彼此的存在(也就是如何發(fā)現(xiàn)對(duì)方)?
對(duì)于問題 1:WebRTC 雖然支持端對(duì)端通信,但是這并不意味著 WebRTC 不再需要服務(wù)器。
在P2P通信的過程中,雙方需要交換一些元數(shù)據(jù)比如媒體信息、網(wǎng)絡(luò)數(shù)據(jù)等等信息,我們通常稱這一過程叫做“信令(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)并沒有規(guī)定信令方法和協(xié)議。在本文后面的實(shí)踐章節(jié)會(huì)利用 Koa 和?Socket.io?技術(shù)實(shí)現(xiàn)一個(gè)信令服務(wù)器。
5.3 彼此音視頻編解碼能力如何溝通?
對(duì)于問題 2:我們首先要知道的是,不同瀏覽器對(duì)于音視頻的編解碼能力是不同的。
比如:?Peer-A 端支持?H264、VP8?等多種編碼格式,而 Peer-B 端支持 H264、VP9 等格式。為了保證雙方都可以正確的編解碼,最簡(jiǎn)單的辦法即取它們所都支持格式的交集-H264。

在 WebRTC 中:有一個(gè)專門的協(xié)議,稱為Session Description Protocol(SDP),可以用于描述上述這類信息。
因此:參與音視頻通訊的雙方想要了解對(duì)方支持的媒體格式,必須要交換 SDP 信息。而交換 SDP 的過程,通常稱之為媒體協(xié)商。
5.4 音視頻數(shù)據(jù)如何傳輸,怎么能讓對(duì)方看得自己?
對(duì)于問題 3:其本質(zhì)上就是網(wǎng)絡(luò)協(xié)商的過程,即參與音視頻實(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ì)稱型的話,那么就無法打洞成功。這時(shí)候 TURN 就派上用場(chǎng)了,TURN(Traversal USing Replays around NAT)是 STUN/RFC5389?的一個(gè)拓展協(xié)議在其基礎(chǔ)上添加了 Replay(中繼)功能。
簡(jiǎn)單來說:其目的就是解決對(duì)稱 NAT 無法穿越的問題,在 STUN 分配公網(wǎng) IP 失敗后,可以通過 TURN 服務(wù)器請(qǐng)求公網(wǎng) IP 地址作為中繼地址。
在 WebRTC 中有三種類型的 ICE 候選者,它們分別是:
1)主機(jī)候選者:表示的是本地局域網(wǎng)內(nèi)的 IP 地址及端口。它是三個(gè)候選者中優(yōu)先級(jí)最高的,也就是說在 WebRTC 底層,首先會(huì)嘗試本地局域網(wǎng)內(nèi)建立連接;
2)反射候選者:表示的是獲取 NAT 內(nèi)主機(jī)的外網(wǎng) IP 地址和端口。其優(yōu)先級(jí)低于 主機(jī)候選者。也就是說當(dāng) WebRTC 嘗試本地連接不通時(shí),會(huì)嘗試通過反射候選者獲得的 IP 地址和端口進(jìn)行連接;
3)中繼候選者:表示的是中繼服務(wù)器的 IP 地址與端口,即通過服務(wù)器中轉(zhuǎn)媒體數(shù)據(jù)。當(dāng) WebRTC 客戶端通信雙方無法穿越 P2P NAT 時(shí),為了保證雙方可以正常通訊,此時(shí)只能通過服務(wù)器中轉(zhuǎn)來保證服務(wù)質(zhì)量了。

從上圖我們可以看出:在非本地局域網(wǎng)內(nèi) WebRTC 通過 STUN server 獲得自己的外網(wǎng) IP 和端口,然后通過信令服務(wù)器與遠(yuǎn)端的 WebRTC 交換網(wǎng)絡(luò)信息,之后雙方就可以嘗試建立 P2P 連接了。當(dāng) NAT 穿越不成功時(shí),則會(huì)通過 Relay server (TURN)中轉(zhuǎn)。
值得一提的是:在 WebRTC 中網(wǎng)絡(luò)信息通常用candidate來描述,而上述圖中的 STUN server 和 Replay server 也都可以是同一個(gè) server。在文末的實(shí)踐章節(jié)即是采用了集成了 STUN(打洞)和 TURN(中繼)功能的開源項(xiàng)目?coturn。
綜上對(duì)三個(gè)問題的解釋,我們可以用下圖來說明 WebRTC 點(diǎn)對(duì)點(diǎn)通信的基本原理。

簡(jiǎn)而言之:就是通過 WebRTC 提供的 API 獲取各端的媒體信息 SDP 以及 網(wǎng)絡(luò)信息 candidate ,并通過信令服務(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é)商過程可以簡(jiǎn)化為三個(gè)步驟對(duì)應(yīng)上述四個(gè)媒體協(xié)商方法。
具體是:
1)呼叫端 Amy 創(chuàng)建 Offer(createOffer)并將 offer 消息(內(nèi)容是呼叫端 Amy 的 SDP 信息)通過信令服務(wù)器傳送給接收端 Bob,同時(shí)調(diào)用 setLocalDesccription 將含有本地 SDP 信息的 Offer 保存起來;
2)接收端 Bob 收到對(duì)端的 Offer 信息后調(diào)用 setRemoteDesccription 方法將含有對(duì)端 SDP 信息的 Offer 保存起來,并創(chuàng)建 Answer(createAnswer)并將 Answer 消息(內(nèi)容是接收端 Bob 的 SDP 信息)通過信令服務(wù)器傳送給呼叫端 Amy;
3)呼叫端 Amy 收到對(duì)端的 Answer 信息后調(diào)用 setRemoteDesccription 方法將含有對(duì)端 SDP 信息的 Answer 保存起來。
經(jīng)過上述三個(gè)步驟,則完成了 P2P 通信過程中的媒體協(xié)商部分。
實(shí)際上:在呼叫端以及接收端調(diào)用 setLocalDesccription 同時(shí)也開始了收集各端自己的網(wǎng)絡(luò)信息(candidate),然后各端通過監(jiān)聽事件?onicecandidate?收集到各自的 candidate 并通過信令服務(wù)器傳送給對(duì)端,進(jìn)而打通 P2P 通信的網(wǎng)絡(luò)通道,并通過監(jiān)聽?onaddstream?事件拿到對(duì)方的視頻流進(jìn)而完成了整個(gè)視頻通話過程。
7、動(dòng)手編碼實(shí)踐
提示:本節(jié)所涉及的完整源碼,請(qǐng)從本文“2、本文源碼”一節(jié)的附件下載。
7.1 coturn 服務(wù)器的搭建
注意:如果只是本地局域網(wǎng)測(cè)試則無需搭建 [url=%5Burl=https://github.com/coturn/%5Dcoturn[/url]]coturn[/url] 服務(wù)器,如果需要外網(wǎng)訪問在搭建 coturn 服務(wù)器之前你需要購(gòu)買一臺(tái)云主機(jī)以及綁定支持 https 訪問的域名。以下是筆者自己搭建的過程,感興趣的可以參照著自已實(shí)踐一次。
coturn 服務(wù)器的搭建主要是為了解決 NAT 無法穿越的問題。
其安裝也較為簡(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)過程:
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 信息描述,并通過信令服務(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:前面提起過其實(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 端通過信令服務(wù)器拿到對(duì)端發(fā)送方 A 端的含有 SDP 的 offer 信息后則會(huì)調(diào)用 setRemoteDescription 存儲(chǔ)對(duì)端的 SDP 信息,創(chuàng)建及設(shè)置本地的 SDP 信息,并通過信令服務(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 通過信令服務(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ò)候選者通過信令服務(wù)器交換后,則會(huì)拿到彼此的視頻流:
socket.on('addIceCandidate', async (candidate) => {
????????await this.peer.addIceCandidate(candidate);
});
this.peer.onaddstream = (event) => {
????????// 拿到對(duì)方的視頻流
????????document.querySelector('#remote-video').srcObject = event.stream;
};
7.5 運(yùn)行效果

? ? ? ? ??


8、本文小結(jié)
經(jīng)過上個(gè)章節(jié)的6個(gè)步驟,即可完成一個(gè)基于WebRTC的完整 P2P 視頻實(shí)時(shí)通話功能(代碼可通過:本節(jié)所涉及的完整源碼,請(qǐng)從本文“2、本文源碼”一節(jié)的附件下載)。
值得一提的是:代碼中的?VIDEO_VIEW?是專注于視頻UI層的JS SDK,包含了發(fā)起視頻 Modal、接收視頻 Modal、視頻中 Modal,其是從筆者線上 Web 視頻問診產(chǎn)品所使用的 JS SDK 抽離出來的。
本文只是簡(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穿透原理
附錄:更多實(shí)時(shí)音視頻技術(shù)資料
[1] 開源實(shí)時(shí)音視頻技術(shù)WebRTC的文章:
《開源實(shí)時(shí)音視頻技術(shù)WebRTC的現(xiàn)狀》
《簡(jiǎn)述開源實(shí)時(shí)音視頻技術(shù)WebRTC的優(yōu)缺點(diǎn)》
《訪談WebRTC標(biāo)準(zhǔn)之父:WebRTC的過去、現(xiàn)在和未來》
《良心分享:WebRTC 零基礎(chǔ)開發(fā)者教程(中文)[附件下載]》
《WebRTC實(shí)時(shí)音視頻技術(shù)的整體架構(gòu)介紹》
《新手入門:到底什么是WebRTC服務(wù)器,以及它是如何聯(lián)接通話的?》
《WebRTC實(shí)時(shí)音視頻技術(shù)基礎(chǔ):基本架構(gòu)和協(xié)議?!?/p>
《淺談開發(fā)實(shí)時(shí)視頻直播平臺(tái)的技術(shù)要點(diǎn)》
《[觀點(diǎn)] WebRTC應(yīng)該選擇H.264視頻編碼的四大理由》
《基于開源WebRTC開發(fā)實(shí)時(shí)音視頻靠譜嗎?第3方SDK有哪些?》
《開源實(shí)時(shí)音視頻技術(shù)WebRTC中RTP/RTCP數(shù)據(jù)傳輸協(xié)議的應(yīng)用》
《簡(jiǎn)述實(shí)時(shí)音視頻聊天中端到端加密(E2EE)的工作原理》
《實(shí)時(shí)通信RTC技術(shù)棧之:視頻編解碼》
《開源實(shí)時(shí)音視頻技術(shù)WebRTC在Windows下的簡(jiǎn)明編譯教程》
《網(wǎng)頁(yè)端實(shí)時(shí)音視頻技術(shù)WebRTC:看起來很美,但離生產(chǎn)應(yīng)用還有多少坑要填?》
《了不起的WebRTC:生態(tài)日趨完善,或?qū)?shí)時(shí)音視頻技術(shù)白菜化》
《騰訊技術(shù)分享:微信小程序音視頻與WebRTC互通的技術(shù)思路和實(shí)踐》
《融云技術(shù)分享:基于WebRTC的實(shí)時(shí)音視頻首幀顯示時(shí)間優(yōu)化實(shí)踐》
《零基礎(chǔ)入門:基于開源WebRTC,從0到1實(shí)現(xiàn)實(shí)時(shí)音視頻聊天功能》
>>?更多同類文章 ……
[2] 實(shí)時(shí)音視頻開發(fā)的其它精華資料:
《即時(shí)通訊音視頻開發(fā)(一):視頻編解碼之理論概述》
《即時(shí)通訊音視頻開發(fā)(二):視頻編解碼之?dāng)?shù)字視頻介紹》
《即時(shí)通訊音視頻開發(fā)(三):視頻編解碼之編碼基礎(chǔ)》
《即時(shí)通訊音視頻開發(fā)(四):視頻編解碼之預(yù)測(cè)技術(shù)介紹》
《即時(shí)通訊音視頻開發(fā)(五):認(rèn)識(shí)主流視頻編碼技術(shù)H.264》
《即時(shí)通訊音視頻開發(fā)(六):如何開始音頻編解碼技術(shù)的學(xué)習(xí)》
《即時(shí)通訊音視頻開發(fā)(七):音頻基礎(chǔ)及編碼原理入門》
《即時(shí)通訊音視頻開發(fā)(八):常見的實(shí)時(shí)語(yǔ)音通訊編碼標(biāo)準(zhǔn)》
《即時(shí)通訊音視頻開發(fā)(九):實(shí)時(shí)語(yǔ)音通訊的回音及回音消除概述》
《即時(shí)通訊音視頻開發(fā)(十):實(shí)時(shí)語(yǔ)音通訊的回音消除技術(shù)詳解》
《即時(shí)通訊音視頻開發(fā)(十一):實(shí)時(shí)語(yǔ)音通訊丟包補(bǔ)償技術(shù)詳解》
《即時(shí)通訊音視頻開發(fā)(十二):多人實(shí)時(shí)音視頻聊天架構(gòu)探討》
《即時(shí)通訊音視頻開發(fā)(十三):實(shí)時(shí)視頻編碼H.264的特點(diǎn)與優(yōu)勢(shì)》
《即時(shí)通訊音視頻開發(fā)(十四):實(shí)時(shí)音視頻數(shù)據(jù)傳輸協(xié)議介紹》
《即時(shí)通訊音視頻開發(fā)(十五):聊聊P2P與實(shí)時(shí)音視頻的應(yīng)用情況》
《即時(shí)通訊音視頻開發(fā)(十六):移動(dòng)端實(shí)時(shí)音視頻開發(fā)的幾個(gè)建議》
《即時(shí)通訊音視頻開發(fā)(十七):視頻編碼H.264、VP8的前世今生》
《即時(shí)通訊音視頻開發(fā)(十八):詳解音頻編解碼的原理、演進(jìn)和應(yīng)用選型》
《即時(shí)通訊音視頻開發(fā)(十九):零基礎(chǔ),史上最通俗視頻編碼技術(shù)入門》
《實(shí)時(shí)語(yǔ)音聊天中的音頻處理與編碼壓縮技術(shù)簡(jiǎn)述》
《網(wǎng)易視頻云技術(shù)分享:音頻處理與壓縮技術(shù)快速入門》
《學(xué)習(xí)RFC3550:RTP/RTCP實(shí)時(shí)傳輸協(xié)議基礎(chǔ)知識(shí)》
《基于RTMP數(shù)據(jù)傳輸協(xié)議的實(shí)時(shí)流媒體技術(shù)研究(論文全文)》
《聲網(wǎng)架構(gòu)師談實(shí)時(shí)音視頻云的實(shí)現(xiàn)難點(diǎn)(視頻采訪)》
《淺談開發(fā)實(shí)時(shí)視頻直播平臺(tái)的技術(shù)要點(diǎn)》
《還在靠“喂喂喂”測(cè)試實(shí)時(shí)語(yǔ)音通話質(zhì)量?本文教你科學(xué)的評(píng)測(cè)方法!》
《實(shí)現(xiàn)延遲低于500毫秒的1080P實(shí)時(shí)音視頻直播的實(shí)踐分享》
《移動(dòng)端實(shí)時(shí)視頻直播技術(shù)實(shí)踐:如何做到實(shí)時(shí)秒開、流暢不卡》
《如何用最簡(jiǎn)單的方法測(cè)試你的實(shí)時(shí)音視頻方案》
《技術(shù)揭秘:支持百萬(wàn)級(jí)粉絲互動(dòng)的Facebook實(shí)時(shí)視頻直播》
《簡(jiǎn)述實(shí)時(shí)音視頻聊天中端到端加密(E2EE)的工作原理》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(一):開篇》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(二):采集》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(三):處理》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(四):編碼和封裝》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(五):推流和傳輸》
《移動(dòng)端實(shí)時(shí)音視頻直播技術(shù)詳解(六):延遲優(yōu)化》
《理論聯(lián)系實(shí)際:實(shí)現(xiàn)一個(gè)簡(jiǎn)單地基于HTML5的實(shí)時(shí)視頻直播》
《IM實(shí)時(shí)音視頻聊天時(shí)的回聲消除技術(shù)詳解》
《淺談實(shí)時(shí)音視頻直播中直接影響用戶體驗(yàn)的幾項(xiàng)關(guān)鍵技術(shù)指標(biāo)》
《如何優(yōu)化傳輸機(jī)制來實(shí)現(xiàn)實(shí)時(shí)音視頻的超低延遲?》
《首次披露:快手是如何做到百萬(wàn)觀眾同場(chǎng)看直播仍能秒開且不卡頓的?》
《Android直播入門實(shí)踐:動(dòng)手搭建一套簡(jiǎn)單的直播系統(tǒng)》
《網(wǎng)易云信實(shí)時(shí)視頻直播在TCP數(shù)據(jù)傳輸層的一些優(yōu)化思路》
《實(shí)時(shí)音視頻聊天技術(shù)分享:面向不可靠網(wǎng)絡(luò)的抗丟包編解碼器》
《P2P技術(shù)如何將實(shí)時(shí)視頻直播帶寬降低75%?》
《專訪微信視頻技術(shù)負(fù)責(zé)人:微信實(shí)時(shí)視頻聊天技術(shù)的演進(jìn)》
《騰訊音視頻實(shí)驗(yàn)室:使用AI黑科技實(shí)現(xiàn)超低碼率的高清實(shí)時(shí)視頻聊天》
《微信團(tuán)隊(duì)分享:微信每日億次實(shí)時(shí)音視頻聊天背后的技術(shù)解密》
《近期大熱的實(shí)時(shí)直播答題系統(tǒng)的實(shí)現(xiàn)思路與技術(shù)難點(diǎn)分享》
《福利貼:最全實(shí)時(shí)音視頻開發(fā)要用到的開源工程匯總》
《七牛云技術(shù)分享:使用QUIC協(xié)議實(shí)現(xiàn)實(shí)時(shí)視頻直播0卡頓!》
《實(shí)時(shí)音視頻聊天中超低延遲架構(gòu)的思考與技術(shù)實(shí)踐》
《理解實(shí)時(shí)音視頻聊天中的延時(shí)問題一篇就夠》
《實(shí)時(shí)視頻直播客戶端技術(shù)盤點(diǎn):Native、HTML5、WebRTC、微信小程序》
《寫給小白的實(shí)時(shí)音視頻技術(shù)入門提綱》
《微信多媒體團(tuán)隊(duì)訪談:音視頻開發(fā)的學(xué)習(xí)、微信的音視頻技術(shù)和挑戰(zhàn)等》
《騰訊技術(shù)分享:微信小程序音視頻技術(shù)背后的故事》
《微信多媒體團(tuán)隊(duì)梁俊斌訪談:聊一聊我所了解的音視頻技術(shù)》
《新浪微博技術(shù)分享:微博短視頻服務(wù)的優(yōu)化實(shí)踐之路》
《實(shí)時(shí)音頻的混音在視頻直播應(yīng)用中的技術(shù)原理和實(shí)踐總結(jié)》
《以網(wǎng)游服務(wù)端的網(wǎng)絡(luò)接入層設(shè)計(jì)為例,理解實(shí)時(shí)通信的技術(shù)挑戰(zhàn)》
《騰訊技術(shù)分享:微信小程序音視頻與WebRTC互通的技術(shù)思路和實(shí)踐》
《新浪微博技術(shù)分享:微博實(shí)時(shí)直播答題的百萬(wàn)高并發(fā)架構(gòu)實(shí)踐》
《技術(shù)干貨:實(shí)時(shí)視頻直播首屏耗時(shí)400ms內(nèi)的優(yōu)化實(shí)踐》
《愛奇藝技術(shù)分享:輕松詼諧,講解視頻編解碼技術(shù)的過去、現(xiàn)在和將來》
《零基礎(chǔ)入門:實(shí)時(shí)音視頻技術(shù)基礎(chǔ)知識(shí)全面盤點(diǎn)》
《實(shí)時(shí)音視頻面視必備:快速掌握11個(gè)視頻技術(shù)相關(guān)的基礎(chǔ)概念》
《淘寶直播技術(shù)干貨:高清、低延時(shí)的實(shí)時(shí)視頻直播技術(shù)解密》
《實(shí)時(shí)音視頻開發(fā)理論必備:如何省流量?視頻高度壓縮背后的預(yù)測(cè)技術(shù)》
>>?更多同類文章 ……
本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。
同步發(fā)布鏈接是:http://www.52im.net/thread-3680-1-1.html