一:多人互動架構方案
(一)WebRTC回顧,兩層含義:
1.WebRTC是google開源的流媒體客戶端,可以進行實時通訊,主要應用於瀏覽器之間進行實時通訊,也可以單獨編譯在自己的應用中
2.WebRTC也是一套規范,只對客戶端做了定義,如何進行媒體協商、通信流程...;對於服務端,比如信令服務端、中繼服務,並沒有在WebRTC中定義,由廠商定義;對於多人互動方案也沒有定義
(二)3種框架進行多人互動
Mesh方案:從WebRTC客戶端演變過來,多人互動--->變為多個1V1通訊,會導致網絡連接過多,任一個客戶端都需要與其他客戶進行連接,帶寬占用過多,不適用商業
MCU方案:硬件演變為軟件,包含一個中心服務器。中心服務器會對多路視頻進行混屏(解碼、編碼),降低帶寬,占CPU,支持的同時在線人數有限。此外,客戶端無法對其進行控制,靈活性較差。
SFU方案: 簡單、主流,不對數據處理,當服務器收到數據后直接進行數據轉發,只進行轉發。每個客戶端都會收到其他客戶端通過服務器轉發過來的數據,但是相對於Mesh,建立的連接只和服務器個數有關。並且相對於MCU,客戶端對於接受的其他各個客戶端的數據可以進行靈活控制。缺點:相對有MCU傳輸的數據更多,造成客戶端到服務端的帶寬占用過高,帶寬不夠時會造成丟包,服務質量無法保證!改進方法:1.降低碼流(上傳時/發送時)2.根據H264中SVC分層方式,將一路視頻分為核心層、擴展層、邊緣層,一層比一層清晰(增量累加),當帶寬足夠時可以全部下發給客戶端,不夠時可以選擇傳輸核心層或者核心層+擴展層從而降低下行帶寬數量,緩解質量不足問題
二: 架構模型詳解
(一)Mesh架構模型詳解
1. 1V1通訊模型
WebRTC學習(八)1V1音視頻實時互動直播系統
WebRTC學習(八)1V1音視頻實時互動直播系統(2)
2. Mesh通訊模型(未畫出信令服務器)
Mesh方案,不依賴於服務器進行數據中轉(不會走TURN),是各個端之間建立連接。
內部同1V1進行設備檢測、數據編解碼、媒體協商、建立連接、發送數據。唯一區別就是1V1可以通過TURN轉發。
Mesh一般使用P2P直連,不會經過TURN服務器轉發,太復雜,不易管理。但是國內需要考慮穿透率,所以該方案一般用在局域網中進行使用和學習!
(二)MCU架構模型詳解
在MCU中心服務器中,存在多個Room,這里只選取左側的進行講解:
1.對於每一個客戶端C1、C2...C4,進入房間中,在房間中(服務器端)都有對應的模塊進行連接,客戶端進行通訊的數據,比如音頻數據、視頻數據都通過該連接傳遞給服務端。
2.服務端模塊收到數據后,會對數據進行解復用,將音視頻數據拆解,將音頻放入音頻處理模塊,將視頻放入視頻處理模塊,實現對數據解碼,然后進行混屏,之后進行編碼壓縮。返回壓縮數據(一路流)到各個客戶端。
缺點:服務端無法支持大量客戶端,最多支持幾十路流處理;客戶端獲取的數據固定(由服務端處理后的),無法進行編輯(拉伸、改變清晰度)
(三)SFU架構模型詳解(主流)
與MCU類似,只是對於SFU而言,不對媒體流進行解碼、混屏、編碼;而是直接進行轉發!!對於終端,接受的數據是原始分辨率,可以對數據進行處理,比MCU更加靈活。
缺點:對於接受端的下行帶寬有考驗,如果帶寬不允許,可能導致服務質量不足
解決方案:
1.simulcast分層,可以設置成兩層、三層或是四層甚至更高層次的分辨率,比如最高層是640X360的分辨率,下一層是240X120的分辨率,再一層是80X60的分辨率。總之就是按比例的縮放。在上傳的時候將三層同時上傳,下發的時候SFU會判斷整個帶寬能否承載下行的數據,如果不能承載便選擇低一個層次的分辨率看能否承載,若不能承載,再選擇更低層次的,依次下去…
2.根據H264中SVC分層方式,將一路視頻分為核心層、擴展層、邊緣層,一層比一層清晰(增量累加,各層之間相互依賴),當帶寬足夠時可以全部下發給客戶端,不夠時可以選擇傳輸核心層或者核心層+擴展層從而降低下行帶寬數量,緩解質量不足問題。
simulcast和SVC不能混用。這兩個相比,simulcast的操作更簡單一些,實用性更高一些,國內的 聲網 便使用的這種方式。SVC更復雜一些,國外的 zoom 、思科 的解決方案便采用的這種方式。
三:流媒體服務器架構和特點
已知的多方通信框架有:Mesh MCU SFU 三種。
其中SFU是目前最優的一種多方通信架構方案,而且這種方案目前已經有比較流行的開源項目:Licode Janus-gateway Mediasoup Medooze
下面簡單的對這4種方案進行分析:
(一)Licode架構
Licode 既可以用作SFU 類型的流媒體服務器,也可以用作 MCU 類型的流媒體服務器。一般情況下,它都被用於SFU類型的流媒體服務器。
Licode 不僅僅是一個流媒體通信服務器,而且還是一個包括了媒體通信層、業務層、用戶管理等功能的完整系統,並且該系統還支持分布式部署。
Licode 是由 C++ 和 Node.js 語言實現。其中,媒體通信部分由 C++ 語言實現,而信令控制、用戶管理、房間管理用 Node.js 實現。它的源碼地址為:https://github.com/lynckia/licode 。
下面這張圖是 Licode 的整體架構圖:
如上圖所示,從大的框架上來看,Licode框架被分為2部分:服務端和客戶端
1.客戶端講解(簡單)
客戶端被分為了3個部分:ClientAPP(信令通訊,比如房間操作、媒體協商...)、Eriza.js(對房間相應邏輯進行控制)、WebRTC(抓取音視頻數據分享和展示)
2.服務端講解
通過上圖可以看出,Licode 從功能層面來講分成三部分,即 Nuve 、ErizoController 和 ErizoAgent 三部分,它們之間通過消息隊列進行通信。
- Nuve 是一個 Web 服務,用於管理用戶、房間、產生 token 以及房間的均衡負載等相關工作。它使用 MongoDB 存儲房間和 token 信息,但不存儲用戶信息。
- ErizoController,用於管理控制,信令和非音視頻數據都通過它接收。它通過消息隊列與 Nuve 進行通信,也就是說 Nuve 可以通過消息隊列對 ErizoController 進行控制。
- ErizoAgent,用於音視頻流媒體數據的傳輸,可以分布式布署。ErizoAgent 與 ErizoController 的通信也是通過消息隊列,信令消息通過 ErizoController 接收到后,再通過消息隊列發給 ErizoAgent,從而實現對 ErizoAgent 進行控制。
通過上面的描述,可以知道 Licode 不僅僅是一個 SFU 流媒體服務器,它還包括了與流媒體相關的業務管理系統、信令系統、流媒體服務器以及客戶端 SDK 等等,可以說它是一個比較完善的產品。
Licode缺點:
- 在 Linux 下目前只支持 Ubuntu 14.04 版本,在其他版本上很難編譯通過。(現在不清楚,畢竟已經過去一段時間)
- Licode 不僅包括了 SFU,而且包括了 MCU,所以它的代碼結構比較重,學習和掌握它要花不少的時間。
- Licode 的性能一般, 如果你把流媒體服務器的性能排在第一位的話,那么 Licode 就不是特別理想的 SFU 流媒體服務器了。
(二)Janus SFU架構
Janus 是一個非常有名的 WebRTC 流媒體服務器,它是以 Linux 風格編寫的服務程序,采用 C 語言實現,支持 Linux/MacOS 下編譯、部署,但不支持 Windows 環境。
它是一個開源項目,其源碼的編譯、安裝非常簡單,只要按 GitHub 上的說明操作即可。源碼及編譯手冊的地址為:https://github.com/meetecho/janus-gateway 。
Janus 的部署也十分簡單,具體步驟詳見文檔,地址為:https://janus.conf.meetecho.com/docs/deploy.html 。
Janus 的架構組成:
流程如Medooze架構圖流程一致!!(后面)
上面這張圖是 Janus 的整體架構圖。Janus 可以被分為以下三部分: Janus CORE、Janus Plugin 以及信令接口組成
1.信令接口,Janus 支持的信令協議比較多,如 HTTP、WebSocket、RabbitMQ 等。這些信令協議使得 Janus 具有非常好的接入性。因為很多公司喜歡各種不同的協議,如有的喜歡 websocket,有的喜歡http,proto等。因此 Janus 在信令接入方面具有很大的優勢。
2.Janus Plugin,Janus 的業務管理是按照 Plugin 的方式管理的,因此你可以在Janus中根據自己的需要實現自己的業務插件。實際上,對於一般性的需求 Janus 已經相關的插件。如:
- SIP:用於與傳統電話設備對接,這個插件使得 Janus 成了 SIP 用戶的代理,從而容許 WebRTC 終端在 SIP 服務器(如 Asterisk)上注冊,並向 SIP 服務器發送或接收音視頻流。
- TextRoom:該插件使用 DataChannel 實現了一個文本聊天室應用。
- Streaming:用於廣播,也就是我們通常所說的一人共享,多人觀看的直播模式;它容許 WebRTC 終端觀看 / 收聽由其余工具生成的預先錄制的文件或媒體。
- VideoRoom:它實現了視頻會議的 SFU 服務,實際就是一個音 / 視頻路由器,用於多人音視頻互動,像音視頻會議,在線教育都可以通過該插件來實現。
- VideoCall:這是一個簡單的視頻呼叫的應用,容許兩個 WebRTC 終端相互通訊,用於 1:1 的音視頻通信。它與 WebRTC 官網的例子類似(https://apprtc.appspot.com),不一樣點是這個插件要通過服務端進行音視頻流中轉,而 WebRTC 官網的例子走的是 P2P 直連。
- RecordPlay:該插件有兩個功能,一是將發送給 WebRTC 的數據錄制下來,二是能夠經過 WebRTC 進行回放。
3.Janus Core 是Janus的核心,其作用是處理流的轉發,各種協議的接入。以瀏覽器為例,要想讓瀏覽器接入到 WebRTC 流媒體服務器上,那流媒體服務器必須要支持 STUN、DTLS、SRTP、ICE 等協議。而 Janus Core 就是專門做這事兒的。
Janus 的整體架構:
Janus 分為兩層,即應用層和傳輸層
插件層又稱為應用層,每一個應用都是一個插件,能夠根據用戶的須要動態地加載或卸載掉某個應用。插件式架構方案是很是棒的一種設計方案,靈活、易擴展、容錯性強,尤為適用於業務比較復雜的業務,但缺點是實現復雜,成本比較高。
傳輸層包括媒體數據傳輸和信令傳輸。
- 媒體數據傳輸層主要實現了 WebRTC 中須要有流媒體協議及其相關協議,如 DTLS 協議、ICE 協議、SDP 協議、RTP 協議、SRTP 協議、SCTP 協議等。
- 信令傳輸層用於處理 Janus 的各類信令,它支持的傳輸協議包括 HTTP/HTTPS、WebSocket/WebSockets、NanoMsg、MQTT、PfUnix、RabbitMQ。不過須要注意的是,有些協議是能夠經過編譯選項來控制是否安裝的,也就是說這些協議並非默認所有安裝的。另外,Janus 全部信令的格式都是采用 Json 格式。
Janus 總體架構采用了插件的方案,這種架構方案很是優秀,用戶能夠根據本身的須要很是方便地在上面編寫本身的應用程序。並且它目前支持的功能很是多,好比支持 SIP、 RTSP、音視頻文件播放、錄制等等,因此在與其余系統的融合性上有很是大的優點。另外,它底層的代碼是由 C 語言編寫的,性能也很是強勁。Janus 的開發、部署手冊也很是完善,所以它是一個很是棒的開源項目。因此,它的架構設計比較復雜,對於初學者來講難度較大。
(三)Medooze架構
Medooze 的整體架構與 Mediasoup 類似,不過它的信令處理、業務管理以及媒體數據的轉發功能都是放在 Nodejs下進行統一管理的。實際上,這樣的管理方式也不會對性能造成什么影響,因為重的媒體流的轉發工作仍然是使用的 C++ 在 Nodejs 底層實現的。
Medooze 是一款綜合流媒體服務器,它不僅支持 WebRTC 協議棧,還支持很多其他協議,如 RTP、RTMP 等。其源碼地址為:https://github.com/medooze/media-server 。
Medooze架構流程圖:
Medooze架構模型如圖中所示:使用NodeJs實現整個服務(信令交互),在NodeJs下面使用MediaServer C++作為底層服務器進行使用(實現媒體流傳輸)
1.瀏覽器從服務器獲取客戶端代碼,通過V8引擎,啟動底層WebRTC 2.瀏覽器與服務端的MediaServer JS進行信令交互、房間操作、媒體協商 3.數據傳輸WebRTC到MediaServer C++
多客戶端流程一致!!!
Medooze整體架構圖:
Medooze 的核心層:
從大的方面來說,Medooze 支持 RTP/RTCP、SRTP/SRCP 等相關協議,從而能夠實現與 WebRTC 終端進行互聯。 除此以外,Medooze 還能夠接入 RTP 流、RTMP 流等,所以你可使用 GStreamer/FFmpeg 向 Medooze 推流,這樣進入到同一個房間的其余 WebRTC 終端就能夠看到 / 聽到由 GStream/FFmpeg 推送上來的音視頻流了。 另外,Medooze 還支持錄制功能,即上圖中的 Recorder 模塊的做用,能夠經過它將房間內的音視頻流錄制下來,以便后期回放。 為了提升多方通訊的質量,Medooze 在音視頻的內容上以及網絡傳輸的質量上都作了大量優化。
Medooze 的控制邏輯層:
是經過 Node.js 實現的,Medooze 經過 Node.js 對外提供了完整的控制邏輯操做相關的 API,經過這些 API 你能夠很容易的控制 Medooze 的行為了。
Medooze 的業務功能要比 Mediasoup 強大,像服務端錄制、推流這些 Mediasoup 沒有的功能它都支持。但它性能沒有 Mediasoup 做的極致,在Medooze的底層使用的poll來處理I/O事件,poll與epoll性能相差距大。除此之外,Medooze的業務邏輯也沒有Mediasoup簡潔;另外與 Janus 相比,它的業務管理不如 Janus 靈活,Janus 的插件管理方式顯然要優於 Medooze 和 mediasoup。
但總的來說,Medooze還是一款非常不錯的 WebRTC 流媒體服務器。雖然有一些小的暇疵,但還是非常不錯的一款流媒體服務器。
(四)Mediasoup架構
Mediasoup 是推出時間不長的 WebRTC 流媒體服務器開源庫,其地址為:https://github.com/versatica/mediasoup/ 。
下圖是Mediasoup整體架構圖:
流程如Medooze一致(前面)!
通過該圖我們可以知道 Mediasoup 流媒體服務器是由 Nodejs 和 Mediasoup(C++) 兩部分組成。
- Nodejs,負責 Mediasoup 的信令接收與業務管理。如創建/消毀房間,創建/關閉生產者,創建/關閉消費者等。
- Mediasoup(C++),這是一個單獨的程序,但該程序無法直接啟動。因為它在內部會判斷是否是 Nodejs 將它啟動起來了。只有在Nodejs 的 Mediasoup 管理模塊加載之后,再將 Mediasoup(C++)啟動起來,這樣它才能正常工作。
- Nodejs 與 Mediasoup之間通過管道進行通信。
在眾多的 WebRTC 流媒體服務器中,Mediasoup 可以說是性能最優秀的WebRTC流媒體服務器。它使用 C++ 作為開發語言,底層使用 libuv 處理 I/O 事件。
有很多人對 Nodejs 比較詬病,認為 Nodejs 提拱不了高性能的流媒體服務器。
實際上,如果按照傳輸的 Nodejs 應用開發出的流媒體服務器肯定是不能勝任這項工作的。但對於 Mediasoup 來講,它只不過使用 Nodejs 做 信令處理 及 業務的管理 工作,所以它的負擔並不重。 對性能要求高的是媒體數據流的轉發工作,而這部分工作是由 Mediasoup(C++)部分實現的。
Mediasoup是多進程程序,他會在業務層控制進程的個數,監聽系統的CPU核數,會對每一個CPU綁定一個Mediasoup進程
比如說你的服務器是個 8 核的CPU,那么在業務層你就該啟動 8 個Mediasoup進程。通過這種方式來達到對 CPU 的充分利用。
Meidasoup多進程圖:
- Host(最大的灰色底框)中,包含worker一、worker二、worker3(3個白色框),能夠認為是進程。
- 每一個worker中,包含1個或多個router(藍色的方片花),進程中有1個或多個房間。
- router周圍有:音視頻生產者(紅色的輸入)+ 音視頻消費者(綠色的輸出),每一個房間有多個生產者和消費者。
- producer:一路視頻是一個生產者,一路音頻也是一個生產者 。
- consumer:一路視頻是一個消費者,一路音頻也是一個消費者 。
- transport:一個Transport 就只關聯一個用戶。
Mediasoup中的每個進程稱為一個 Worker, 你也可以把它理解為一個節點
,在每個 Worker 中可以有多個 Router。
對於 Router,你站在不同的解度可以有不同的理解。如果你占在應用層的角度,你可以把它理解為一個房間;如果你站在數據流轉的角度,可以把它理解為一個路由器,數據通過 路由器
轉發給目標用戶。
大的綠色箭頭下面,有灰色的Transport字體,分為三種類型,即 WebRtcTransport、PlainRtpTransport 和 PipeTransport。
- WebRtcTransport 用於與 WebRTC 類型的客戶端進行鏈接,如瀏覽器。
- PlainRtpTransport 用於與傳統的 RTP 類型的客戶端鏈接,經過該 Transport 能夠播放多媒體文件、FFmpeg 的推流等。
- PipeTransport 用於 Router 之間的鏈接,也就是一個房間中的音視頻流經過 PipeTransport 傳到另外一個房間。
在每一個 Transport (每一個用戶)中能夠包括多個 Producer 和 Consumer。
- Producer 表示媒體流的共享者,它又分為兩種類型,即音頻的共享者和視頻的共享者。
- Consumer 表示媒體流的消費者,它也分為兩種類型,即音頻的消費者和視頻的消費者。
Mediasoup 的實現邏輯很是清晰,它不關心上層應用該如何作,只關心底層數據的傳輸,並將它作到極致。
(五)如何選擇SFU(選擇合適的)
實現語言:
1.Meooze、Mediasoup、Licode 這三個流媒體服務器的媒體通訊部分都是由 C++ 實現的,而控制邏輯是經過 Node.js 實現,所以若是你是 C++ 開發人員,且有 JavaScript 技術背景,那么你就應該在這三種流媒體服務器之間選擇,由於這樣更容易入門。
2.而 Janus-gateway 是徹底經過 C 語言實現的,服務部署是傳統的 Linux 風格,所以若是你是 Linux/C 開發者,則應該選擇 Janus 做為你的流媒體服務器。
系統特色:
1.像 Licode 是一個完整的系統,支持分布式集群部署,因此系統相對復雜,學習周期要長一些。它能夠直接布署在生產環境,可是二次開發的靈活性不夠。
2.Janus-gateway 是一個獨立的服務,支持的信令協議很豐富,並且支持插件開發,易擴展,對於 Linux/C 背景的開發者是很不錯的選擇。
3.Medooze 和 Mediasoup 都是流媒體服務器庫,對於須要將流媒體服務器集成到本身產品中的開發者來講,應該選擇它們。
性能特色:
1.Licode、Meooze、Mediasoup、Janus-gateway 單台服務均可以支持 500 方參會人,因此它們的性能都仍是不錯的。
2.相對來講,Licode 的性能與其余流媒體服務器相比要低一些;
3.Medooze 因為沒有使用 epoll 來處理異步 IO 事件,因此性能也受到一些影響。
不過總的來講,它們在 500 方的容量下,視頻質量均可以獲得很好的保證,延遲在 100ms 左右。