前端要實(shí)現(xiàn)直播,通常有以下兩種方式:
- RTMP協(xié)議
RTMP(Real Time Messaging Protocol)是Adobe公司獨(dú)有的一種可用于直播的傳輸流媒體協(xié)議??梢越⒎?wù)器和客戶端之間的遠(yuǎn)程調(diào)用和流傳輸通道。
瀏覽器通過Flash插件播放RTMP流,實(shí)現(xiàn)直播效果。這種方式需要瀏覽器支持Flash,現(xiàn)在使用較少。
- WebRTC
WebRTC(Web Real-Time Communication)是支持瀏覽器端音視頻流傳輸?shù)募夹g(shù)標(biāo)準(zhǔn)。通過WebRTC API,瀏覽器可以獲取媒體流,并在本地進(jìn)行編碼和處理,然后傳送給其他瀏覽器,實(shí)現(xiàn)視頻通話或直播。
實(shí)現(xiàn)步驟:
(1) 通過getUserMedia()獲取本地音視頻流
(2) 對流進(jìn)行編碼,得到二進(jìn)制的Track軌道數(shù)據(jù)
(3) 通過RTCPeerConnection把編碼后的軌道數(shù)據(jù)發(fā)送給遠(yuǎn)端
(4) 遠(yuǎn)端通過RTCPeerConnection接收軌道數(shù)據(jù)
(5) 遠(yuǎn)端通過播放器進(jìn)行解碼和渲染
WebRTC是目前最可靠、性能好的瀏覽器端直播方案。它無插件、跨平臺(tái),是直播的首選技術(shù)。
什么是WebRTC?
WebRTC(Web Real-Time Communication)是一個(gè)谷歌開源項(xiàng)目,它提供了一套標(biāo)準(zhǔn) API,使 Web 應(yīng)用可以直接提供實(shí)時(shí)音視頻通信功能,不再需要借助任何插件。原生通信過程采用 P2P 協(xié)議,數(shù)據(jù)直接在瀏覽器之間交互,理論上不需要服務(wù)器端的參與。
“為瀏覽器、移動(dòng)平臺(tái)、物聯(lián)網(wǎng)設(shè)備提供一套用于開發(fā)功能豐富、高質(zhì)量的實(shí)時(shí)音視頻應(yīng)用的通用協(xié)議”是 WebRTC 的使命。
WebRTC的歷史
隨著網(wǎng)絡(luò)基礎(chǔ)設(shè)施日趨完善以及終端計(jì)算能力不斷提升,實(shí)時(shí)通信技術(shù)已經(jīng)滲透到各行各業(yè),支撐著人們的日常生活。在 WebRTC 誕生之前,實(shí)時(shí)通信技術(shù)非常復(fù)雜,想獲得核心的音視頻編碼及傳輸技術(shù)需要支付昂貴的專利授權(quán)費(fèi)用。此外,將實(shí)時(shí)通信技術(shù)與業(yè)務(wù)結(jié)合也非常困難,并且很耗時(shí),通常只有較大規(guī)模的公司才有能力實(shí)現(xiàn)。
WebRTC 的出現(xiàn)使實(shí)時(shí)通信技術(shù)得以廣泛應(yīng)用。WebRTC 制定、實(shí)現(xiàn)了一套統(tǒng)一且完整的實(shí)時(shí)通信標(biāo)準(zhǔn),并將這套標(biāo)準(zhǔn)開源。這套標(biāo)準(zhǔn)包含了實(shí)時(shí)通信技術(shù)涉及的所有內(nèi)容,使用這套標(biāo)準(zhǔn),開發(fā)人員無須關(guān)注音視頻編解碼、網(wǎng)絡(luò)連接、傳輸?shù)鹊讓蛹夹g(shù)細(xì)節(jié),可以專注于構(gòu)建業(yè)務(wù)邏輯,且這些底層技術(shù)是完全免費(fèi)的。
WebRTC 統(tǒng)一了各平臺(tái)的實(shí)時(shí)通信技術(shù),大部分操作系統(tǒng)及瀏覽器都支持 WebRTC,無須安裝任何插件,就可以在瀏覽器端發(fā)起實(shí)時(shí)視頻通話。
WebRTC 技術(shù)最初為 Web 打造,隨著 WebRTC 自身的演進(jìn),目前已經(jīng)可以將其應(yīng)用于各種應(yīng)用程序。
隨著 4G 的普及和 5G 技術(shù)的應(yīng)用,實(shí)時(shí)音視頻技術(shù)正在蓬勃發(fā)展。在互聯(lián)網(wǎng)領(lǐng)域,花椒、映客等直播平臺(tái)吸引了大量的用戶;在教育領(lǐng)域,通過實(shí)時(shí)直播技術(shù)搭建的“空中課堂”惠及全球數(shù)億學(xué)生;在醫(yī)療行業(yè),隨著電子處方單納入醫(yī)保,互聯(lián)網(wǎng)看病、復(fù)診正在興起,地域之間醫(yī)療資源不均衡的問題被實(shí)時(shí)直播技術(shù)逐步消除。
WebRTC 1.0 規(guī)范發(fā)布以來,以 Chrome、Firefox 為代表的瀏覽器對 WebRTC 提供了全方面的支持,Safari 11 也開始對 WebRTC 提供支持。
WebRTC的發(fā)展歷史如下:
- 2010 年 5 月,谷歌收購視頻會(huì)議軟件公司 GIPS,該公司在 RTC 編碼方面有深厚的技術(shù)積累。
- 2011 年 5 月,谷歌開源 WebRTC 項(xiàng)目。
- 2011 年 10 月,W3C 發(fā)布第一個(gè) WebRTC 規(guī)范草案。
- 2014 年 7 月,谷歌發(fā)布視頻會(huì)議產(chǎn)品 Hangouts,該產(chǎn)品使用了 WebRTC 技術(shù)。
- 2017 年 11 月,WebRTC 進(jìn)入候選推薦標(biāo)準(zhǔn)(Candidate Recommendation,CR)階段。
WebRTC的技術(shù)架構(gòu)
從技術(shù)實(shí)現(xiàn)的角度講,在瀏覽器之間進(jìn)行實(shí)時(shí)通信需要使用很多技術(shù),如音視頻編解碼、網(wǎng)絡(luò)連接管理、媒體數(shù)據(jù)實(shí)時(shí)傳輸?shù)龋€需要提供一組易用的 API 給開發(fā)者使用。這些技術(shù)組合在一起,就是 WebRTC 技術(shù)架構(gòu),如圖 1 所示。
圖 1 WebRTC技術(shù)架構(gòu)
WebRTC 技術(shù)架構(gòu)的頂層分為兩個(gè)部分:
- Web API:一組 JavaScript 接口,由 W3C 維護(hù),開發(fā)人員可以使用這些 API 在瀏覽器中創(chuàng)建實(shí)時(shí)通信應(yīng)用程序。
- 適用于移動(dòng)端及桌面開發(fā)的 libwebrtc:即使用 WebRTC C++ 源碼在 Windows、Android、iOS 等平臺(tái)編譯后的開發(fā)包,開發(fā)人員可以使用這個(gè)開發(fā)包打造原生的 WebRTC 應(yīng)用程序。
第二層是 WebRTC C ++ API,它是 Web API 和 libwebrtc 的底層實(shí)現(xiàn)。該層包含了連接管理、連接設(shè)置、會(huì)話狀態(tài)和數(shù)據(jù)傳輸?shù)?API?;谶@些 API,瀏覽器廠商可以方便地加入對 WebRTC 的支持。
WebRTC 規(guī)范里沒有包含信令協(xié)議,這部分需要研發(fā)人員依據(jù)業(yè)務(wù)特點(diǎn)自行實(shí)現(xiàn)。
WebRTC 支持的音頻編碼格式有 OPUS 和 G.711,同時(shí)還在音頻處理層實(shí)現(xiàn)了回音消除及降噪功能。WebRTC 支持的視頻編碼格式主要有 VP8 和 H264(還有部分瀏覽器支持 VP9 及 H265 格式),WebRTC 還實(shí)現(xiàn)了 Jitter Buffer 防抖動(dòng)及圖像增強(qiáng)等高級功能。
在媒體傳輸層,WebRTC 在 UDP 之上增加了 3 個(gè)協(xié)議:
- 數(shù)據(jù)包傳輸層安全性協(xié)議(DTLS):用于加密媒體數(shù)據(jù)和應(yīng)用程序數(shù)據(jù);
- 安全實(shí)時(shí)傳輸協(xié)議(SRTP):用于傳輸音頻和視頻流;
- 流控制傳輸協(xié)議(SCTP):用于傳輸應(yīng)用程序數(shù)據(jù)。
WebRTC 借助 ICE 技術(shù)在端與端之間建立 P2P 連接,它提供了一系列 API,用于管理連接。WebRTC 還提供了攝像頭、話筒、桌面等媒體采集 API,使用這些 API 可以定制媒體流。
WebRTC的網(wǎng)絡(luò)拓?fù)?/h2>
WebRTC 規(guī)范主要介紹了使用 ICE 技術(shù)建立 P2P 的網(wǎng)絡(luò)連接,即 Mesh 網(wǎng)絡(luò)結(jié)構(gòu)。在 WebRTC 技術(shù)的實(shí)際應(yīng)用中,衍生出了媒體服務(wù)器的用法。
使用媒體服務(wù)器的場景,通常是因?yàn)?P2P 連接不可控,而使用媒體服務(wù)器可以對媒體流進(jìn)行修改、分析、記錄等 P2P 無法完成的操作。
實(shí)際上,如果我們把媒體服務(wù)器看作 WebRTC 連接的另外一端,就很容易理解媒體服務(wù)器的工作原理了。媒體服務(wù)器是 WebRTC 在服務(wù)器端的實(shí)現(xiàn),起到了橋梁的作用,用于連接多個(gè) WebRTC 客戶端,并增加了額外的媒體處理功能。通常根據(jù)提供的功能,將媒體服務(wù)器區(qū)分成 MCU 和 SFU。
1) Mesh網(wǎng)絡(luò)結(jié)構(gòu)
Mesh 是 WebRTC 多方會(huì)話最簡單的網(wǎng)絡(luò)結(jié)構(gòu)。在這種結(jié)構(gòu)中,每個(gè)參與者都向其他所有參與者發(fā)送媒體流,同時(shí)接收其他所有參與者發(fā)送的媒體流。說這是最簡單的網(wǎng)絡(luò)結(jié)構(gòu),是因?yàn)樗?Web-RTC 原生支持的,無須媒體服務(wù)器的參與。
Mesh 網(wǎng)絡(luò)結(jié)構(gòu)如圖 2 所示。
圖 2 Mesh網(wǎng)絡(luò)結(jié)構(gòu)
在 Mesh 網(wǎng)絡(luò)結(jié)構(gòu)中,每個(gè)參與者都以 P2P 的方式相互連接,數(shù)據(jù)交換基本不經(jīng)過中央服務(wù)器(部分無法使用 P2P 的場景,會(huì)經(jīng)過 TURN 服務(wù)器)。由于每個(gè)參與者都要為其他參與者提供獨(dú)立的媒體流,因此需要 N-1 個(gè)上行鏈路和 N-1 個(gè)下行鏈路。眾多上行和下行鏈路限制了參與人數(shù),參與人過多會(huì)導(dǎo)致明顯卡頓,通常只能支持 6 人以下的實(shí)時(shí)互動(dòng)場景。
由于沒有媒體服務(wù)器的參與,Mesh 網(wǎng)絡(luò)結(jié)構(gòu)難以對視頻做額外的處理,不支持視頻錄制、視頻轉(zhuǎn)碼、視頻合流等操作。
2) MCU網(wǎng)絡(luò)結(jié)構(gòu)
MCU(Multipoint Control Unit)是一種傳統(tǒng)的中心化網(wǎng)絡(luò)結(jié)構(gòu),參與者僅與中心的 MCU 媒體服務(wù)器連接。MCU 媒體服務(wù)器合并所有參與者的視頻流,生成一個(gè)包含所有參與者畫面的視頻流,參與者只需要拉取合流畫面,MCU 網(wǎng)絡(luò)結(jié)構(gòu)如圖 3 所示。
圖 3 MCU網(wǎng)絡(luò)結(jié)構(gòu)
這種場景下,每個(gè)參與者只需要 1 個(gè)上行鏈路和 1 個(gè)下行鏈路。與 Mesh 網(wǎng)絡(luò)結(jié)構(gòu)相比,參與者所在的終端壓力要小很多,可以支持更多人同時(shí)在線進(jìn)行音視頻通信,比較適合多人實(shí)時(shí)互動(dòng)場景。但是 MCU 服務(wù)器負(fù)責(zé)所有視頻編碼、轉(zhuǎn)碼、解碼、合流等復(fù)雜操作,服務(wù)器端壓力較大,需要較高的配置。同時(shí)由于合流畫面固定,界面布局也不夠靈活。
3) SFU網(wǎng)絡(luò)結(jié)構(gòu)
在 SFU(Selective Forwarding Unit)網(wǎng)絡(luò)結(jié)構(gòu)中,仍然有中心節(jié)點(diǎn)媒體服務(wù)器,但是中心節(jié)點(diǎn)只負(fù)責(zé)轉(zhuǎn)發(fā),不做合流、轉(zhuǎn)碼等資源開銷較大的媒體處理工作,所以服務(wù)器的壓力會(huì)小很多,服務(wù)器配置也不像 MCU 的要求那么高。每個(gè)參與者需要 1 個(gè)上行鏈路和 N-1 個(gè)下行鏈路,帶寬消耗低于 Mesh,但是高于 MCU。
我們可以將 SFU 服務(wù)器視為一個(gè) WebRTC 參與方,它與其他所有參與方進(jìn)行 1 對 1 的建立連接,并在其中起到橋梁的作用,同時(shí)轉(zhuǎn)發(fā)各個(gè)參與者的媒體數(shù)據(jù)。SFU 服務(wù)器具備復(fù)制媒體數(shù)據(jù)的能力,能夠?qū)⒁粋€(gè)參與者的數(shù)據(jù)轉(zhuǎn)發(fā)給多個(gè)參與者。
SFU 服務(wù)器與 TURN 服務(wù)器不同,TURN 服務(wù)器僅僅是為 WebRTC 客戶端提供的一種輔助數(shù)據(jù)轉(zhuǎn)發(fā)通道,在無法使用 P2P 的情況下進(jìn)行透明的數(shù)據(jù)轉(zhuǎn)發(fā),TURN 服務(wù)器不具備復(fù)制、轉(zhuǎn)發(fā)媒體數(shù)據(jù)的能力。
SFU 對參與實(shí)時(shí)互動(dòng)的人數(shù)也有一定的限制,適用于在線教學(xué)、大型會(huì)議等場景,其網(wǎng)絡(luò)結(jié)構(gòu)如圖 4 所示。
圖 4 SFU網(wǎng)絡(luò)結(jié)構(gòu)
Simulcast聯(lián)播
在進(jìn)行 WebRTC 多方視頻會(huì)話時(shí),參與人數(shù)較多,硬件設(shè)施、網(wǎng)絡(luò)環(huán)境均有差異,這種情況下如何確保會(huì)話質(zhì)量呢?使用 MCU 時(shí),這個(gè)問題相對簡單一些。
MCU 可以根據(jù)參與者的網(wǎng)絡(luò)質(zhì)量和設(shè)備能力,提供不同的清晰度和碼率。但是隨之而來的問題是服務(wù)器資源壓力較大,難以支撐大規(guī)模并發(fā),同時(shí)也顯著增加了使用成本。
多人會(huì)話場景選擇 SFU 網(wǎng)絡(luò)結(jié)構(gòu)是目前通用的做法。早期的 SFU 只是將媒體流從發(fā)送端轉(zhuǎn)發(fā)給接收端,無法獨(dú)立為不同參與者調(diào)整視頻碼率,其結(jié)果是發(fā)送者需要自行調(diào)整碼率,以適應(yīng)接收條件最差的參與者。而那些網(wǎng)絡(luò)環(huán)境較好的參與者只能接收相同質(zhì)量的媒體流,別無選擇。
Simulcast 技術(shù)對 SFU 進(jìn)行了優(yōu)化,發(fā)送端可以同時(shí)發(fā)送多個(gè)不同質(zhì)量的媒體流給接收端。SFU 能夠依據(jù)參與者的網(wǎng)絡(luò)質(zhì)量,決定轉(zhuǎn)發(fā)給參與者哪種質(zhì)量的媒體流。
因?yàn)榘l(fā)送者需要發(fā)送多個(gè)不同質(zhì)量的媒體流,所以會(huì)顯著增加發(fā)送設(shè)備的載荷,同時(shí)占用發(fā)送者上行帶寬資源。
可伸縮視頻編碼
可伸縮視頻編碼(Scalable Video Coding,SVC)是 Simulcast 的改進(jìn)技術(shù)。它使用分層編碼技術(shù),發(fā)送端只需要發(fā)送一個(gè)獨(dú)立的視頻流給 SFU,SFU 根據(jù)不同的層,解碼出不同質(zhì)量的視頻流,并發(fā)送給不同接收條件的參與者。
SVC 中多個(gè)層次的媒體流相互依賴,較高質(zhì)量的媒體數(shù)據(jù)需要較低質(zhì)量的媒體數(shù)據(jù)解碼。SFU 接收到 SVC 編碼的內(nèi)容后,根據(jù)客戶端的接收條件選擇不同的編碼層次,從而獲得不同質(zhì)量的媒體流。
如果媒體流包括多個(gè)不同分辨率的層,則稱該編碼具有空間可伸縮性;如果媒體流包含多個(gè)不同幀率的層,則稱該編碼具有時(shí)間可伸縮性;如果媒體流包含多個(gè)不同碼率的層,則稱該編碼具有質(zhì)量可伸縮性。
在編碼空間、時(shí)間、質(zhì)量均可伸縮的情況下,SFU 可以生成不同的視頻流,以適應(yīng)不同客戶端的接收條件。
WebRTC的兼容性
據(jù)caniuse.com統(tǒng)計(jì),大部分瀏覽器都實(shí)現(xiàn)了對 WebRTC 的支持,各瀏覽器支持情況如下:
- Firefox版本22+
- Chrome版本23+
- Safari版本11+
- iOS Safari版本11+
- Edge版本15+
- Opera版本18+
- Android Browser版本81+
- Chrome for Android版本84+
- Firefox for Android版本68+
- IE不支持
Android 和 iOS 原生應(yīng)用都支持 WebRTC,可以使用原生 SDK 開發(fā)跨平臺(tái)的 WebRTC 應(yīng)用。
Android WebView 自 36 版本之后,提供了對 WebRTC 的支持,這意味可以使用 WebRTC API 開發(fā) Android 混合 App。注意,一些手機(jī)廠商對部分 Android 版本里的 WebView 進(jìn)行了裁剪,導(dǎo)致不能使用 WebRTC,這時(shí)候下載并安裝最新的 WebView 即可。
iOS WebView 目前還不支持 WebRTC,但是可以使用 cordova 的插件 cordova-plugin-iosrtc 在混合 App 中使用 WebRTC。
WebRTC 目前處于活躍開發(fā)階段,各個(gè)瀏覽器的實(shí)現(xiàn)程度不一樣。為了解決兼容性的問題,谷歌提供了 adapter.js 庫。
在 GitHub 上可以下載最新版本的 adapter.js 庫,地址是 https://github.com/webrtc/adapter/tree/master/release。將下載的文件放到 Web 服務(wù)器根目錄,在 Web 應(yīng)用中引用。
<script src="adapter.js"></script>