2020年11月9日 星期一

WebRTC伺服器開源解決方案

WebRTC伺服器可以自己實現 SFU 流媒體伺服器,但自已實現流媒體伺服器困難還是蠻多的,它裡面至少要涉及到 DTLS 協議、ICE 協議、SRTP/SRTCP 協議等,光理解這些協議就要花不少的時間,更何況要實現它,常見的SFU開源解決方案有很多,說明如後。

如何選擇SFU

對流媒體服務器的選擇是一個 Balance,沒有最好,只有最合適。

  • 實現語言:Meooze、Mediasoup、Licode 這三個流媒體服務器的媒體通信部分都是由C++ 實現的,而控制邏輯是通過Node.js 實現,因此如果你是C++ 開發人員,且有JavaScript 技術背景,那麼你就應該在這三種流媒體服務器之間選擇,因為這樣更容易入門。而 Janus-gateway 是完全通過 C 語言實現的,服務部署是傳統的 Linux 風格,因此如果你是 Linux/C 開發者,則應該選擇 Janus 作為你的流媒體服務器。
  • 系統特點:像 Licode 是一個完整的系統,支持分佈式集群部署,所以系統相對複雜,學習週期要長一些。它可以直接佈署在生產環境,但是二次開發的靈活性不夠。 Janus-gateway 是一個獨立的服務,支持的信令協議很豐富,而且支持插件開發,易擴展,對於 Linux/C 背景的開發者是很不錯的選擇。 Medooze 和 Mediasoup 都是流媒體服務器庫,對於需要將流媒體服務器集成到自己產品中的開發者來說,應該選擇它們。
  • 性能特點:Licode、Meooze、Mediasoup、Janus-gateway 單台服務都可以支持 500 方參會人,所以它們的性能都還是不錯的。相對來說,Licode 的性能與其他流媒體服務器相比要低一些;Medooze 由於沒有使用 epoll 來處理異步 IO 事件,所以性能也受到一些影響。不過總的來說,它們在 500 方的容量下,視頻質量都可以得到很好的保證,延遲在 100ms 左右。

主要的媒體服務器

匯總表,請務必閱讀右側的評論。


Intel Collaboration Suite for WebRTC

包括客戶端SDK(JS/Android/iOS / Windows),服務器SDK(SFU/MCU/SIP網關)。它提供了幾乎所有你想要的東西。 MCU/SFU不是從頭開始開發,而是基於Licode的。


順便說一句,最近它被提及作為intel和韓國電信運營商巨頭SK電訊合作的核心技術。


Janus

Janus核心是WebRTC的“gateway”,它是用C語言實現並且是在libsrtp和libnice之上開發的(實現SRTP和ICE協議也被Google和mozilla使用),支援 Linux/MacOS 下編譯、部署,但不支援 Windows 環境。通過添加各種插件,可以實現不同的功能或用例,例如SFU。正如我在前一篇文章中所寫的,它已經在Slack中使用了。許可證最初是AGPL,但是在Alex和Oleg(CoTurn的創建者)討論後,更改為GPLv3。

Janus架構圖

Janus 分為應用層和傳輸層,外掛層又稱為應用層,每個應用都是一個外掛,可以根據使用者的需要動態地載入或解除安裝掉某個應用。外掛式架構方案是非常棒的一種設計方案,靈活、易擴充套件、容錯性強,尤其適用於業務比較複雜的業務,但缺點是實現複雜,成本比較高。


在 Janus 中預設支援的外掛包括以下幾個。

  • SIP:這個外掛使得 Janus 成了 SIP 使用者的代理,從而允許 WebRTC 終端在 SIP 伺服器(如 Asterisk)上註冊,並向 SIP 伺服器傳送或接收音影片流。
  • TextRoom:該外掛使用 DataChannel 實現了一個文字聊天室應用。
  • Streaming:它允許 WebRTC 終端觀看 / 收聽由其他工具生成的預先錄製的檔案或媒體。
  • VideoRoom:它實現了影片會議的 SFU 服務,實際就是一個音 / 影片路由器。
  • VideoCall:這是一個簡單的影片呼叫的應用,允許兩個 WebRTC 終端相互通訊,它與 WebRTC 官網的例子相似(https://apprtc.appspot.com),不同點是這個外掛要經過服務端進行音影片流中轉,而 WebRTC 官網的例子走的是 P2P 直連。
  • RecordPlay:該外掛有兩個功能,一是將傳送給 WebRTC 的資料錄製下來,二是可以通過 WebRTC 進行回放。

傳輸層包括媒體資料傳輸和信令傳輸。媒體資料傳輸層主要實現了 WebRTC 中需要有流媒體協議及其相關協議,如 DTLS 協議、ICE 協議、SDP 協議、RTP 協議、SRTP 協議、SCTP 協議等。


信令傳輸層用於處理 Janus 的各種信令,它支援的傳輸協議包括 HTTP/HTTPS、WebSocket/WebSockets、NanoMsg、MQTT、PfUnix、RabbitMQ。不過需要注意的是,有些協議是可以通過編譯選項來控制是否安裝的,也就是說這些協議並不是預設全部安裝的。另外,Janus 所有信令的格式都是採用 Json 格式。


Janus 整體架構採用了外掛的方案,這種架構方案非常優秀,使用者可以根據自己的需要非常方便地在上面編寫自己的應用程式。


而且它目前支援的功能非常多,比如支援 SIP、 RTSP、音影片檔案播放、錄製等等,所以在與其他系統的融合性上有非常大的優勢。


另外,它底層的程式碼是由 C 語言編寫的,效能也非常強勁。Janus 的開發、部署手冊也非常完善,因此它是一個非常棒的開源專案。

官方提供安卓和ios的sdk。

缺點:

  • 架構太複雜,不適合初學者,公司採用的話人力成本和事件成本會比較高
  • janus 底層沒有使用 epoll 這類非同步I/O事件處理機制,這應該說是它的一大缺陷
  • Janus還使用 glib 庫,由於 glib 庫對於國內的很多開發同學來說用的比較少,所以會有一定的學習成本

Janus github

Janus官網


Jitsi

被Atlassian收購,它是一個用Java編寫的SFU。 Atlassian允許該項目保持開放源代碼(即使他們更改了許可證),並且開發仍在繼續。從一開始,Jitsi一直使用XMPP(與客戶端)進行信號傳輸,並使用自己的XMPP擴展:Colibri與信令服務器進行交換。它還提供了一個REST API。

整個團隊非常接近IETF標準和瀏覽器。這是實現同步聯播最快(也許是目前唯一的)。 Jitsi的前任首席執行官兼創始人兼視頻橋技術負責人Emil也是Trickle ICE的作者。

雖然 Atlassian 在他們的產品中使用它,但是像http://talky.io/這樣的其他公司已經將它用於不同的場景。

使用Java構建的服務端,底層也是使用c/c++,使用Java語言所以效能上沒有使用c/c++的表現好。

主要模組及實現語言:

  • Jitsi Video-Bridge (Software video-bridge 實現語言java)
  • Jitsi Jicofo (Component mandatory for jitsi conference 實現語言java)
  • Prosody ( XMPP Server 實現語言lua)
  • Nginx (Web Server)
  • Jitsi Meet (Web application – to which the end user will interact. 實現語言js)
接口(SDK)語言:
  • Libjitsi:java接口SDK,用於服務端開發
  • lib-jitsi-meet:javascript接口SDK,用於web客戶端的開發

優點:

  • github star12.3k,issue和pr處理快
  • 文件齊全
  • 官方提供安卓和ios SDK,也可以自行編譯SDK,使用的是React Native
  • 官方提供web端的SDK,並提供使用electron進行桌面端打包(端很齊全)
  • 社群採用論壇方式溝通,活躍較高
  • 社群提供分散式解決方案,但是文件偏少。
  • 每週一維護團隊在jitsi上進行影片會議,回答開發者的提問,溝通使用英文,國內時間好像是晚上。
  • 社群版本更新迭代較快
  • 比較穩定,家族產品較多,即時通訊,電子白板,文件共享都有。2017年8月發布android和IOS原生API接口。
缺點:
  • 協議用的是SIP和XMPP,編譯部署過程過於複雜,依賴庫較多,且文檔比較少。缺少android和IOS的demo和文檔。多人對講時採用的是單路分發機制,對伺服器網絡等要求較高。


Kurento

最初設計為MCU,Kurento本身是用C++實現的。有JS / Node /和Java的SDK。開發人員可以使用SDK操作Kurento。有使用Node.js(Kurento + WebRTC + Node.js)管理Kurento媒體服務器非常詳細的文檔和代碼。目前,它也可以作為SFU模式。

[Alex Note]:2016年9月20日由twilio收購。

還有一個基於Kurento的被稱為NUBOMEDIA的託管服務,那些不想在自己的服務器上運行的人可以使用那個或者彈性的RTC。


接口(SDK)語言:
  • 服務端SDK:java,node.js
  • 客戶端SDK:java,js
  • 支持Json-Rpc

優點:

文檔齊全,功能、封裝API都比較齊全,對Android和IOS也有原生API支持,支持h264

缺點:

bug較多,不是很穩定,接口太多,所以使用起來相對複雜,Android和IOS缺少官方demo,因其中增加了視覺增強等圖像處理功能,所以會有視頻延遲風險

Kurento github

Kurento官網

Licode

Licode本身是用 C++ 和 Node.js 實現,媒體通訊部分由 C++ 語言實現,而信令控制、使用者管理、房間管理用 Node.js 實現。INTEL已將其用作其媒體服務器邏輯的基礎。Licode 既可以用作 SFU 型別的流媒體伺服器,也可以用作 MCU 型別的流媒體伺服器。一般情況下,它都被用於 SFU。 包括了媒體通訊層、業務層、使用者管理等功能的完整系統,並且該系統還支援分散式部署。

Licode架構圖

從功能層面來講分成三部分,即 Nuve 、ErizoController 和 ErizoAgent 三部分,它們之間通過訊息佇列進行通訊。
  • Nuve 是一個 Web 服務,用於管理使用者、房間、產生 token 以及房間的均衡負載等相關工作。它使用 MangoDB 儲存房間和 token 資訊,但不儲存使用者資訊。
  • ErizoController,用於管理控制,信令和非音影片資料都通過它接收。它通過訊息佇列與 Nuve 進行通訊,也就是說 Nuve 可以通過訊息佇列對 ErizoController 進行控制。
  • ErizoAgent,用於音影片流媒體資料的傳輸,可以分散式佈署。ErizoAgent 與 ErizoController 的通訊也是通過訊息佇列,信令訊息通過 ErizoController 接收到後,再通過訊息佇列發給 ErizoAgent,從而實現對 ErizoAgent 進行控制。
Licode 不僅僅是一個 SFU 流媒體伺服器,它還包括了與流媒體相關的業務管理系統、信令系統、流媒體伺服器以及客戶端 SDK 等等,可以說它是一個比較完善的產品。

如果你使用 Licode 作為流媒體伺服器,基本上不需要做二次開發了,所以這樣一套系統對於沒有音影片積累的公司和個人具有非常大的誘惑力。目前 Intel CS 專案就是在 Licode 基礎上研發出來的,已經為不少公司提供了服務。

官網提供學習demo和文件。

主要模塊及實現語言:

  • Erizo:MCU模塊,實現語言C++
  • erizoAPI:Node.js addon wrapper for Erizo,實現語言C++
  • erizo_controller:跟Rooms管理相關的服務,實現語言JS
  • nuve:跟Rooms管理相關的API,實現語言JS
接口(SDK)語言:
  • Client API: Javascript
  • Sercer API: node.js

優點:

  • 接口簡潔,服務輕量級,支持h264

缺點:

  • github star 2.4k issue和pr相當活躍,社群採用的是傳統提問,及時溝通相對較差
  • 在 Linux 下目前只支援 Ubuntu 14.04 版本,在其他版本上很難編譯通過。
  • Licode 不僅包括了 SFU,而且包括了 MCU,所以它的程式碼結構比較重,學習和掌握它要花不少的時間。
  • Licode 的效能一般, 如果你把流媒體伺服器的效能排在第一位的話,那麼 Licode 就不是特別理想的 SFU 流媒體伺服器了。
  • 官方沒有看到android和ios的SDK,有其他人實現,但是早已經不更新,如果你要考慮安卓和ios的話,可能自己會下功夫。
  • API文檔比較簡單且其他文檔較少;客戶端接口只有js的,沒有android和IOS原生API;不是很穩定,經常中斷。


licode github

licode官網

參考:https://www.terena.org/activities/tf-webrtc/meeting1/slides/Ly​​nckia.pdf


Meedooze

Medooze 是一款綜合流媒體伺服器,它不僅支援 WebRTC 協議棧,還支援很多其他協議,如 RTP、RTMP 等。

從大的方面來講,Medooze 支援 RTP/RTCP、SRTP/SRCP 等相關協議,從而可以實現與 WebRTC 終端進行互聯。除此之外,Medooze 還可以接入 RTP 流、RTMP 流等,因此你可以使用 GStreamer/FFmpeg 向 Medooze 推流,這樣進入到同一個房間的其他 WebRTC 終端就可以看到 / 聽到由 GStream/FFmpeg 推送上來的音影片流了。另外,Medooze 還支援錄製功能,即上圖中的 Recorder 模組的作用,可以通過它將房間內的音影片流錄製下來,以便後期回放。

Medooze 的控制邏輯層是通過 Node.js 實現的,Medooze 通過 Node.js 對外提供了完整的控制邏輯操作相關的 API,通過這些 API 你可以很容易的控制 Medooze 的行為了。

Medooze 與 Mediasoup 相比,兩者在核心層實現的功能都差不多,但 Medooze 的功能更強大,包括了錄製、推 RTMP 流、播放 FLV 檔案等相關的操作,而 Mediasoup 則沒有這些功能。

Medooze 也有一些缺點,儘管 Medooze 也是 C++ 開發的流媒體服務務器,使用了非同步 IO 事件處理機制,但它使用的非同步 IO 事件處理的 API 是 poll,poll 在處理非同步 IO 事件時,與 Linux 下最強勁的非同步 IO 事件 API epoll 相比要遜色不少,這導致它在接收 / 傳送音影片包時效能比 Mediasoup 要稍差一些。


Medooze github


MediaSoup

Mediasoup 是推出時間不長的 WebRTC 流媒體伺服器開源庫(使用例如libuv)實現的。其餘的代碼是使用最多的JavaScript(ECMAScript 6)。有很多未實現的webrtc功能,根據Twitter的帖子,媒體運行良好。有趣的是,它可以使用JavaScript處理RTP包。

Mediasoup 由應用層和資料處理層組成。應用層是通過 Node.js 實現的;資料處理層由 C++ 語言實現,包括 DTLS 協議實現、ICE 協議實現、SRTP/SRTCP 協議實現、路由轉發等。

Mediasoup架構圖
  • Host(最大的灰色底框)中,包含worker1、worker2、worker3(3個白色框),可以認為是進程。
  • 每個worker中,包含1個或多個router(藍色的方片花),進程中有1個或多個房間。
  • router周圍有:音視頻生產者(紅色的輸入)+ 音視頻消費者(綠色的輸出),每個房間有多個生產者和消費者。
  • producer:一路視頻是一個生產者,一路音頻也是一個生產者 。
  • consumer:一路視頻是一個消費者,一路音頻也是一個消費者 。
  • transport:一個Transport 就相當於一個用戶。
Mediasoup 把每個例項稱為一個 Worker,在 Worker 內部有多個 Router,每個 Router 相當於一個房間。在每個房間裡可以有多個使用者或稱為參與人,每個參與人在 Mediasoup 中由一個 Transport 代理。換句話說,對於房間(Router)來說,Transport 就相當於一個使用者。

Transport 有三種類型,即 WebRtcTransport、PlainRtpTransport 和 PipeTransport。
  • WebRtcTransport 用於與 WebRTC 型別的客戶端進行連線,如瀏覽器。
  • PlainRtpTransport 用於與傳統的 RTP 型別的客戶端連線,通過該 Transport 可以播放多媒體檔案、FFmpeg 的推流等。
  • PipeTransport 用於 Router 之間的連線,也就是一個房間中的音影片流通過 PipeTransport 傳到另一個房間。
在每個 Transport 中可以包括多個 Producer 和 Consumer。
  • Producer 表示媒體流的共享者,它又分為兩種型別,即音訊的共享者和影片的共享者。
  • Consumer 表示媒體流的消費者,它也分為兩種型別,即音訊的消費者和影片的消費者。
Mediasoup 的實現邏輯非常清晰,它不關心上層應用該如何做,只關心底層資料的傳輸,並將它做到極致。

Mediasoup 底層使用 C++ 開發,使用 libuv 作為其非同步 IO 事件處理庫,所以保證了其效能的高效性。同時它支援了幾乎所有 WebRTC 為了實時傳輸做的各種優化,所以說它是一個特別優秀的 WebRTC SFU 流媒體伺服器。

它與 Janus 相比,它更聚焦於資料傳輸的實時性、高效性、簡潔性,而 Janus 相比 Mediasoup 做的事兒更多,架構和邏輯也更加複雜。

對於開發能力比較強的公司來說,根據自己的業務需要在 Mediasoup 上做二次開發也是非常值得推薦的技術方案。

手機端的話需要自己實現安卓和ios的SDK

Mediasoup github

Mediasoup官網


PowerMedia XMS

Dialogic開發,它是一個商業媒體服務器。固定的佈局是痛苦的,但是從RFC5707來的是一個歷史問題。如果你已經實現了對RFC5707的支持,你可以控制它。值得注意的是,在日本,軟銀公司正在使用它作大規模的安裝。


SORA

與其他SFU不同的是,除了作為視頻路由器之外,還實現了資源優化功能(通過快照)以及許多其他獨特功能。請參閱Shiguredo WebRTC SFU Sora開發日誌以獲取其他高級功能。

pion/webrtc

WebRTC API的Pure Go實現,github上star4.7k,目前用的人較少,不建議使用生成環境,可以學習參考使用,建議長期關注。


結論

每個開源實現都有其各自的特點,都可以應用到實際產品中,只不過作為開發人員都有自己獨特的技術背景,你需要根據自身特點以及專案特點選一個最合適的。接下來介紹如何對這些開源專案進行評判和選擇的。

  • 團隊 在一個團隊中肯定會選擇一種大家都比較熟悉的語言作為專案開發的語言,所以我們在選擇開源專案時,就要選擇使用這種語言開發的開源專案。 比如阿里系基本都用 Java 語言進行開發,所以它們在選擇開源專案時,基本都會選擇 Java 開發的開源專案; 而做音影片流媒體服務的開發人員,為了追求效能,所以一般都選擇 C/C++ 語言開發的開源專案。 團隊人手如果不充裕的情況下,儘量就不要選擇特別複雜的,和文件比較少的開源技術。
  • 適合業務 要充分考慮到你的業務的使用者量和使用者群體,如果你的業務量很大,需要做分散式,那麼你選擇的開源技術一定要先去了解下他是否支援分散式部署,分散式部署採用那種方式。單機支援多少併發,最好自己用伺服器實際測試下,官方資料會和實際測試資料多少都有出入。 專案功能也需要考慮,比如業務需要錄製回放,開源技術並沒有這樣的功能,需要自己開發,時間成本很高,但選擇已經做好錄製回放功能的開源技術又不一樣了。
  • 二次開發 Licode 是一個完整的系統,支援分散式叢集部署,所以系統相對複雜,學習週期要長一些。它可以直接佈署在生產環境,但是二次開發的靈活性不夠。 Janus-gateway 是一個獨立的服務,支援的信令協議很豐富,而且支援外掛開發,易擴充套件,對於 Linux/C 背景的開發者是很不錯的選擇。 Medooze 和 Mediasoup 都是流媒體伺服器庫,對於需要將流媒體伺服器整合到自己產品中的開發者來說,應該選擇它們。
  • 時間成本 公司對於專案的時間計劃和成本也要考量,因為使用開源技術或多或少都會遇到坑,有可能一個坑會卡很久,所以使用文件全,社群活躍的開源技術比較好。

無論選擇哪種開源技術,前期一定要做好調研,並實際自己搭建使用過在做決定,選擇好後,為了彌補技術債,需要去深入開源技術的程式碼,不然還債的時候很疼苦。


測試比較

  • Jitsi Meet(JVB版本0.1.1077),
  • Janus Gateway(版本0.4.3)及其视频室插件,
  • Medooze(版本0.32.0) SFU应用程序,
  • Kurento(来自OpenVidu Docker容器,Kurento Media Server版本6.7.0),
  • mediasoup(版本2.2.3)

JItsi在240名參與者失敗。 Kurento / OpenVidu很早就遇到了問題。 Janus和mediasoup似乎比Medooze更好。它似乎與更好的CPU優化有關,因為拐點與各個CPU的飽和度相關。
JItsi在240名參與者失敗,Kurento / OpenVidu在50左右出現問題。否則SFU表現出類似的行為。
視頻質量僅在實驗結束時下降,表明擁塞控制機制正在完成其工作,並設法做出正確的妥協,以便在調整其他參數的同時保持感知質量高。

前和後)將補丁應用於Janus和Jitsi。我們還添加了mediasoup結果(綠色)。 Medooze和Kurento / OpenVidu結果在兩個圖中都是相同的,因為第二次沒有更好的結果。







RTT或延遲,作為負載的函數(對數標度)。前和後將補丁應用於Janus和Jitsi。我們還添加了mediasoup結果(綠色)。 Medooze和Kurento / OpenVidu結果來自同一數據集。



Reference:

WebRTC SFU Load Testing (Alex Gouaillard)

谁是最好的WebRTC SFU?

WebRTC媒体服务器

史上最全的WebRTC伺服器技術選型分析

三个基于WebRTC开源MCU框架的横向对比


沒有留言:

張貼留言