下面就來探討下常見的SFU開源解決方案,當然,你也可以自己實現 SFU 流媒體服務器,但自已實現流媒體服務器困難還是蠻多的,它里面至少要涉及到 DTLS 協議、ICE 協議、SRTP/SRTCP 協議等,光理解這些協議就要花不少的時間,更何況要實現它了。
前言
所以最常見的辦法就是使用開源的實現。但是這里我也想給大家說一定,用了開源的解決方案,能快速的搭建起業務,但是無疑也欠下了技術債,因為開源的解決方案肯定沒有自己實現的要熟悉,因為不熟悉很多時候出現了問題,並不能馬上解決,甚至解決不了,導致業務受到影響。而且熟悉開源解決方案都是需要一個時間和過程的,而一般領導會不會給你這個時間就兩說了。
但如果你要快速的搭建起音視頻系統的話,無疑使用開源技術解決方案是最快,最能節省人力成本的。下面我們就來分析下常見的SFU開源解決方案的優缺點,以便你選擇合適的開源解決方案。
Licode
Licode 既可以用作 SFU 類型的流媒體服務器,也可以用作 MCU 類型的流媒體服務器。一般情況下,它都被用於 SFU 類型的流媒體服務器。
Licode 不僅僅是一個流媒體通信服務器,而且還是一個包括了媒體通信層、業務層、用戶管理等功能的完整系統,並且該系統還支持分布式部署。
Licode 是由 C++ 和 Node.js 語言實現。其中,媒體通信部分由 C++ 語言實現,而信令控制、用戶管理、房間管理用 Node.js 實現。它的源碼地址為:https://github.com/lynckia/licode 。下面這張圖是 Licode 的整體架構圖:
通過這張圖你可以看出,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,和文檔。
但 Licode 也有以下一些缺點:
- github star 2.4k issue和pr相當活躍,社區采用的是傳統提問,及時溝通相對較差
- 在 Linux 下目前只支持 Ubuntu 14.04 版本,在其他版本上很難編譯通過。
- Licode 不僅包括了 SFU,而且包括了 MCU,所以它的代碼結構比較重,學習和掌握它要花不少的時間。
- Licode 的性能一般, 如果你把流媒體服務器的性能排在第一位的話,那么 Licode 就不是特別理想的 SFU 流媒體服務器了。
- 官方沒有看到android和ios的SDK,有其他人實現,但是早已經不更新,如果你要考慮安卓和ios的話,可能自己會下功夫。
Janus-gateway
Janus 是一個非常有名的 WebRTC 流媒體服務器,它是以 Linux 風格編寫的服務程序,采用 C 語言實現,支持 Linux/MacOS 下編譯、部署,但不支持 Windows 環境。
它是一個開源項目,其源碼的編譯、安裝非常簡單,只要按 GitHub 上的說明操作即可。源碼及編譯手冊的地址為:https://github.com/meetecho/janus-gateway 。
Janus 的部署也十分簡單,具體步驟詳見文檔,地址為:https://janus.conf.meetecho.com/docs/deploy.html 。
從上面的架構圖中,你可以看出 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 的開發、部署手冊也非常完善,因此它是一個非常棒的開源項目。
github star4.1k,並且處理issue和pr相對較快。
官方提供安卓和ios的sdk。
缺點:
- 架構太復雜,不適合初學者,公司采用的話人力成本和事件成本會比較高
- janus 底層沒有使用 epoll 這類異步I/O事件處理機制,這應該說是它的一大缺陷
- Janus還使用 glib 庫,由於 glib 庫對於國內的很多開發同學來說用的比較少,所以會有一定的學習成本
Mediasoup
Mediasoup 是推出時間不長的 WebRTC 流媒體服務器開源庫,其地址為:https://github.com/versatica/mediasoup/ 。
Mediasoup 由應用層和數據處理層組成。應用層是通過 Node.js 實現的;數據處理層由 C++ 語言實現,包括 DTLS 協議實現、ICE 協議實現、SRTP/SRTCP 協議實現、路由轉發等。
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
Medooze
Medooze 是一款綜合流媒體服務器,它不僅支持 WebRTC 協議棧,還支持很多其他協議,如 RTP、RTMP 等。其源碼地址為:https://github.com/medooze/media-server
從大的方面來講,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 要稍差一些。
jitsi
使用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)
優點:
- github star12.3k,issue和pr處理快
- 文檔齊全
- 官方提供安卓和ios SDK,也可以自行編譯SDK,使用的是React Native
- 官方提供web端的SDK,並提供使用electron進行桌面端打包(端很齊全)
- 社區采用論壇方式溝通,活躍較高
- 社區提供分布式解決方案,但是文檔偏少。
- 每周一維護團隊在jitsi上進行視頻會議,回答開發者的提問,溝通使用英文,國內時間好像是晚上。
- 社區版本更新迭代較快
Kurento
Kurento和jitsi是一樣,持續維護了很多年,經過了時間的檢驗。不同的是他是使用c++開發,有豐富的文檔和示例褲,對於開發者來說非常友好。
pion/webrtc
WebRTC API的Pure Go實現,github上star4.7k,目前用的人較少,不建議使用生成環境,可以學習參考使用,建議長期關注。
總結:
對流媒體服務器的選擇,沒有最好,只有最合適。每個開源實現都有其各自的特點,都可以應用到實際產品中,只不過作為開發人員都有自己獨特的技術背景,你需要根據自身特點以及項目特點選一個最合適的。接下來,我就介紹一下我是如何對這些開源項目進行評判和選擇的。
-
團隊 在一個團隊中肯定會選擇一種大家都比較熟悉的語言作為項目開發的語言,所以我們在選擇開源項目時,就要選擇使用這種語言開發的開源項目。 比如阿里系基本都用 Java 語言進行開發,所以它們在選擇開源項目時,基本都會選擇 Java 開發的開源項目; 而做音視頻流媒體服務的開發人員,為了追求性能,所以一般都選擇 C/C++ 語言開發的開源項目。 團隊人手如果不充裕的情況下,盡量就不要選擇特別復雜的,和文檔比較少的開源技術。
-
適合業務 要充分考慮到你的業務的用戶量和用戶群體,如果你的業務量很大,需要做分布式,那么你選擇的開源技術一定要先去了解下他是否支持分布式部署,分布式部署采用那種方式。單機支持多少並發,最好自己用服務器實際測試下,官方數據會和實際測試數據多少都有出入。 項目功能也需要考慮,比如業務需要錄制回放,開源技術並沒有這樣的功能,需要自己開發,時間成本很高,但選擇已經做好錄制回放功能的開源技術又不一樣了。
-
二次開發 Licode 是一個完整的系統,支持分布式集群部署,所以系統相對復雜,學習周期要長一些。它可以直接布署在生產環境,但是二次開發的靈活性不夠。 Janus-gateway 是一個獨立的服務,支持的信令協議很豐富,而且支持插件開發,易擴展,對於 Linux/C 背景的開發者是很不錯的選擇。 Medooze 和 Mediasoup 都是流媒體服務器庫,對於需要將流媒體服務器集成到自己產品中的開發者來說,應該選擇它們。
-
時間成本 公司對於項目的時間計划和成本也要考量,因為使用開源技術或多或少都會遇到坑,有可能一個坑會卡很久,所以使用文檔全,社區活躍的開源技術比較好。
無論選擇哪種開源技術,前期一定要做好調研,並實際自己搭建使用過在做決定,選擇好后,為了彌補技術債,需要去深入開源技術的代碼,不然還債的時候很疼苦。