一文帶你瞭解webrtc基本原理(動手實現1v1視訊通話)
webrtc (Web Real-Time Communications) 是一個實時通訊技術,也是實時音視訊技術的標準和框架。
大白話講,webrtc是一個集大成的實時音視訊技術集,包含了各種客戶端api、音視訊編/解碼lib、流媒體傳輸協議、回聲消除、安全傳輸等。
對於開發者來說可以藉助webrtc非常方便的實現低延時視訊通話能力。
現在主流的直播系統、會議系統基本都是基於webrtc來實現。
一、webrtc 三種架構
我們先大概瞭解下webrtc的幾種架構及各自適用場景。
【Mesh】
Mesh架構,需要所有參與連線的peer建立與所有其他peer的媒體連線。
該架構需要n-1個上下行,以此帶來的頻寬消耗(流量)、編/解碼消耗(手機效能)成線性增長。
該架構只能適用3-4個人的小型會議場景。
【MCU】
所有本房間的peer將本地媒體流推到遠端媒體伺服器,由媒體伺服器進行混流,然後再推到所有連線的peer端。
該架構的優點就是隻需要1路上下行,隨著peer人數不斷增加,依然不會對使用者造成頻寬、手機效能影響。
該架構將壓力轉嫁到服務端,由專用媒體伺服器來完成混流,轉推等功能。
【SFU】
相對於MCU來說SFU只做轉發,媒體伺服器壓力有限。與mesh架構相比,只需要n-1個下行,1個上行。
在大規模的場合該架構具有伸縮性。
二、實現 1v1 視訊通話
廢話不多說,動手實踐下。
(麻雀雖小,五臟俱全。通過實現1v1的功能,來整體瞭解下webrtc協議的原理。)
github: http://github.com/Plen-wang/webrtc-demo-1v1
由於是私有證書問題,chrome會有安全提示。(demo地址暫時還能用 -_- )
有兩個方法可以試下。
第一個方法,手動設定一個類似不安全白名單列表,然後重啟瀏覽器。
chrome://flags/#unsafely-treat-insecure-origin-as-secure
如果不行,我們試下第二個方法肯定可以。
點選空白頁輸入 thisisunsafe
字元。
動手之前,我們先簡單瞭解下webrtc的連線的大致流程和涉及的相關技術點。
【WebRTC P2P】
【NAT穿透】
peer基本都在內網,需要通過nat穿透技術來與peer建立連線。
根據nat的拓撲情況大致分為如下幾種:完全錐形、IP錐形、埠錐形、對稱形。
stun\turn協議:stun協議用來拿到peer公網ip,turn用來做relay資料轉發。
【SDP】
sdp是會話描述協議。
是媒體協商時使用,用於將本地支援的媒體(編解碼等)資訊、candidate(連線候選者)資訊打包傳送到信令伺服器。
sdp的交換是通過中間伺服器(信令伺服器)來完成的。
【ICE】
ICE是一個不斷嘗試連線的協議,不同的網路情況下ICE大概會嘗試如下幾種方式來建立通訊通道。
host(peers都在內網)、 srflx(nat穿透)、prflx(nat穿透-Full Cone)、relay(中繼)
【服務端】
在整個連線生命週期中都是需要服務端參與。參與webrtc協作的服務端大概分為這幾種型別。
stun/turn伺服器(p2p穿透)、信令伺服器、媒體伺服器(媒體資訊處理)、業務伺服器(可選)
整體流程大致如下。
(上述技術點較多,感興趣可以自行查詢相關資料)
【部署STUN\TURN伺服器】
為了支援1v1公網訪問,我們需要搭建一個stun/turn伺服器。
這裡我們使用 Coturn 開源元件,coturn的映象有很多,可自行選擇。
(注意準備coturn配置檔案時,記得設定使用者名稱和密碼。)
docker run -d --rm --name turn-server --network=host \ -v ${pwd}/turnserver.conf:/etc/coturn/turnserver.conf \ instrumentisto/coturn
部署好之後可以通過ICE測試工具測試下
http://webrtc.github.io/samples/src/content/peerconnection/trickle-icestun:1.15.11.173:3478?transport=tcp turn:1.15.11.173:3478?transport=tcp:user:pwd
如果正常返回了ICE嘗試的連線型別,說明部署沒有問題。
【實現信令伺服器與客戶端程式碼】
我們採用golang來實現一個簡單的信令伺服器,使用開源元件go-socket。
同時還需要實現一個web客戶端。
demo程式碼就不貼到文章裡了,放在github上。整體程式碼比較簡單,感興趣可以看下。
[email protected]:Plen-wang/webrtc-demo-1v1.git
【部署信令伺服器】
當在本地debug的差不多了,我們把信令伺服器打個映象發到雲主機上。
(如果部署本demo,可以直接使用此映象。)
docker push wangqingpei/rtc-signal-server:latest docker run --name signal-server -d -p:8080:8080 wangqingpei/rtc-signal-server
【部署web伺服器】
部署好信令伺服器之後,我們把靜態檔案放到web伺服器裡,直接使用nginx映象部署非常簡單。
docker run -d -p 80:80 -p 443:443 --rm --name webrtc-nginx \ -v /data/rtc-nginx.conf:/etc/nginx/nginx.conf \ -v /data/pem/server.key:/etc/nginx/server.key \ -v /data/pem/server.pem:/etc/nginx/server.pem \ -v /data/rtc-static-file:/usr/share/nginx/html nginx
部署前,記得修改js裡的stun伺服器地址。
//建立RTCPeerConnection物件 function createRTCPeerConnection() { try { const configuration = {'iceServers': [{'urls': 'stun:1.15.11.173:3478?transport=tcp'}]} rtcConnObject = new RTCPeerConnection(configuration); rtcConnObject.onicecandidate = handleRtcICECandidate;//ice 互動 rtcConnObject.onaddstream = handleRtcAddStream;//遠端stream加入 rtcConnObject.onremovestream = handleRtcRemoveStream;//遠端stream移除 rtcConnObject.addStream(localStreamObject);//新增本地stream console.log("create local RTCPeerConnection object ok."); } catch (e) { console.error("create RTCPeerConnection err.", e); } }
兩邊peer就可以藉助stun伺服器拿到公網ip實現nat穿透。
三、實現MCU/SFU 多人通話
MCU/SFU架構需要 專用媒體伺服器 參與。
【媒體伺服器選擇】
專用媒體伺服器有 OWT(open webrtc toolkit)、TWS(Kurento Media Server)等重量級的開源產品。
這兩款開源框架都支援MCU、SFU架構功能。
我們選擇OWT搗鼓下。
先看下部署起來的效果,預設MCU模式。
紅框部分是服務端混流之後的效果。
【部署OWT】
注意,owt-server-4.3映象與最新版chrome有相容性問題,會報錯 Empty candidate 錯誤。
我們直接使用5.0的映象部署。
docker run -d --name owt-demo --network host lmshao/owt-server
由於該映象是使用預設配置打的,啟動後手動進入容器修改下相關配置,換成你雲主機的公網ip,然後重啟服務。
配置檔案路徑
vi dist/webrtc_agent/agent.toml
配置項,這裡修改成你的公網ip
network_interfaces = [{name = "eth0", replaced_ip_address = "1.116.175.232"}] # default: []
stun伺服器可選
stunport = 3478 #default: 0 stunserver = "1.15.11.173" #default: ""
然後修改下portal.toml檔案,檔案路徑。
vi dist/portal/portal.toml
修改成公網ip
ip_address = "1.116.175.232" #default: ""
重啟下相關服務
./bin.restart-all.sh
注意啟動日誌裡有一個id、key,這是用來進入管理頁面用的。(沒錯,owt提供了後臺管理頁面 -_-)
superServiceId: xxx superServiceKey: xxx sampleServiceId: xxx sampleServiceKey: xxx
預設3004埠下是mcu模式,連線的人多了就會明顯示卡頓(看伺服器配置)。
我們切到SFU模式試下流暢度和伺服器負載情況。
通過 ?forward=true 引數控制
http://1.116.175.232:3004/?forward=true
OWT還配有管理後臺用於控制媒體伺服器的相關引數。
OWT還是比較強大的,有興趣可以研究研究。
參考資料:
github.com/googollee/go-socket.io
《WebRTC技術詳解:從0到1構建多人視訊會議系統》
《WebRTC音視訊實時互動技術:原理、實戰與原始碼分析》
《FFmpeg 音視訊開發基礎與實戰》
- 記一次批量更新整型型別的列 → 探究 UPDATE 的使用細節
- 編碼中的Adapter,不僅是一種設計模式,更是一種架構理念與解決方案
- 執行緒池底層原理詳解與原始碼分析
- 30分鐘掌握 Webpack
- 線性迴歸大結局(嶺(Ridge)、 Lasso迴歸原理、公式推導),你想要的這裡都有
- Django 之路由層
- 【前端必會】webpack loader 到底是什麼
- day42-反射01
- 中心化決議管理——雲端分析
- HashMap底層原理及jdk1.8原始碼解讀
- 詳解JS中 call 方法的實現
- 列印 Logger 日誌時,需不需要再封裝一下工具類?
- 初識設計模式 - 代理模式
- 設計模式---享元模式
- 密碼學奇妙之旅、01 CFB密文反饋模式、AES標準、Golang程式碼
- [ML從入門到入門] 支援向量機:從SVM的推導過程到SMO的收斂性討論
- 從應用訪問Pod元資料-DownwardApi的應用
- Springboot之 Mybatis 多資料來源實現
- Java 泛型程式設計
- CAS核心思想、底層實現