webrtc (Web Real-Time Communications) 是一個實時通訊技術,也是實時音視訊技術的標準和框架。
大白話講,webrtc是一個集大成的實時音視訊技術集,包含了各種使用者端api、音視訊編/解碼lib、串流媒體傳輸協定、回聲消除、安全傳輸等。
對於開發者來說可以藉助webrtc非常方便的實現低延時視訊通話能力。
現在主流的直播系統、會議系統基本都是基於webrtc來實現。
我們先大概瞭解下webrtc的幾種架構及各自適用場景。
Mesh架構,需要所有參與連線的peer建立與所有其他peer的媒體連線。
該架構需要n-1個上下行,以此帶來的頻寬消耗(流量)、編/解碼消耗(手機效能)成線性增長。
該架構只能適用3-4個人的小型會議場景。
所有本房間的peer將本地媒體流推到遠端媒體伺服器,由媒體伺服器進行混流,然後再推到所有連線的peer端。
該架構的優點就是隻需要1路上下行,隨著peer人數不斷增加,依然不會對使用者造成頻寬、手機效能影響。
該架構將壓力轉嫁到伺服器端,由專用媒體伺服器來完成混流,轉推等功能。
相對於MCU來說SFU只做轉發,媒體伺服器壓力有限。與mesh架構相比,只需要n-1個下行,1個上行。
在大規模的場合該架構具有伸縮性。
廢話不多說,動手實踐下。
(麻雀雖小,五臟俱全。通過實現1v1的功能,來整體瞭解下webrtc協定的原理。)
github:https://github.com/Plen-wang/webrtc-demo-1v1
由於是私有證書問題,chrome會有安全提示。(demo地址暫時還能用 -_- )
有兩個方法可以試下。
第一個方法,手動設定一個類似不安全白名單列表,然後重啟瀏覽器。
chrome://flags/#unsafely-treat-insecure-origin-as-secure
如果不行,我們試下第二個方法肯定可以。
點選空白頁輸入 thisisunsafe
字元。
動手之前,我們先簡單瞭解下webrtc的連線的大致流程和涉及的相關技術點。
【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穿透)、信令伺服器、媒體伺服器(媒體資訊處理)、業務伺服器(可選)
整體流程大致如下。
(上述技術點較多,感興趣可以自行查詢相關資料)
為了支援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測試工具測試下
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice
stun: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架構需要 專用媒體伺服器 參與。
專用媒體伺服器有 OWT(open webrtc toolkit)、TWS(Kurento Media Server)等重量級的開源產品。
這兩款開源框架都支援MCU、SFU架構功能。
我們選擇OWT搗鼓下。
先看下部署起來的效果,預設MCU模式。
紅框部分是伺服器端混流之後的效果。
注意,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 引數控制
https://1.116.175.232:3004/?forward=true
OWT還配有管理後臺用於控制媒體伺服器的相關引數。
OWT還是比較強大的,有興趣可以研究研究。
參考資料:
github.com/googollee/go-socket.io
《WebRTC技術詳解:從0到1構建多人視訊會議系統》
《WebRTC音視訊實時互動技術:原理、實戰與原始碼分析》
《FFmpeg 音視訊開發基礎與實戰》