背景
在之前的WebRTC實時音視訊通話之語音通話設計與實踐中介紹了58 TEG部門基于 WebRTC 的實時音視訊通話解決方案。
考慮到騰訊微信的小程式平台提供了音視訊通話與直播的支援,如果能打通基于 WebRTC 的實時音視訊通話與微信小程式,就能夠極大地擴充音視訊直播的能力範圍,為業務線的産品和服務提供更多更好的選擇。
本文主要介紹打通 WebRTC 端和微信小程式端的音視訊互通方案,實作在盡量不需要改動 WebRTC 端代碼的情況下,添加對主叫和被叫微信小程式端的支援。
基于 WebRTC 的實時音視訊方案
58 已搭建了成熟的基于 WebRTC 的實時音視訊方案,能夠有效地支援多端(iOS/Android/Web)之間的音視訊會話。其通過後端的 Room Server 服務來管理會話;某端需要發起音視訊會話,首先需要到 Room Server 中注冊一個房間,之後基于房間來進行信令的互動;主叫端和被叫端的音視訊資料傳輸通過 PeerConnection 進行。
WebRTC 端的媒體流方案是采用标準的 RTP[1] 和 RTCP[2] 協定。
微信小程式的音視訊支援
微信的小程式對外開放了音視訊直播[3] 的能力,使用方可以通過 live-pusher 标簽實作基于 RTMP[4] 的音視訊推流(錄制),live-player 标簽實作基于 RTMP 的音視訊拉流(播放)。
- 微信 App iOS 最低版本要求:6.5.21
- 微信 App Android 最低版本要求:6.5.19
- 小程式基礎庫最低版本要求:1.7.0
微信小程式的音視訊方案是基于 RMTP 流媒體協定的。
互通方案
總體架構
方案的總體架構如下:
- WebRTC Gateway 作為一個特殊的 WebRTC 端與指定的另一個 WebRTC 端通過 Room Server 交換信令并建立會話
- 會話建立後,WebRTC 端與 WebRTC Gateway 直接(P2P)或間接(TURN)交換音視訊流
- WebRTC Gateway 将 WebRTC 端之音視訊流經 Streaming Server 轉發至微信小程式端;微信小程式音視訊輸入流經 Streaming Server 轉發至WebRtc 端
其中,WebRTC Gateway 使用成熟的服務來搭建,主要作為微信小程式端的 WebRTC 代理輔助微信小程式端參與 WebRTC 的會話,主要進行信令的溝通、Offer/Answer 的協商和媒體流資料的轉發;Streaming Server 包括 RTMP 中繼子產品和轉碼子產品,主要提供 RTP&RTCP 媒體流和 RTMP 媒體流資料的轉換和中繼;在已有的 Room Server 上擴充,添加了與接入微信小程式端相關的信令處理邏輯。
會話建立
需要支援 WebRTC 端與微信小程式端的音視訊流的互通,首先需要添加對其建立會話的支援;WebRTC 端與微信小程式端的會話建立,具體來說是指:
- WebRTC 音視訊(主叫) 與 微信小程式音視訊(被叫)
- WebRTC 音視訊(被叫) 與 微信小程式音視訊(主叫)
- WebRTC 音視訊(主叫) 與 WebRTC音視訊(被叫)
- 微信小程式音視訊(主叫) 與 微信小程式音視訊(被叫)
其中,case 3 和 case 4 不會涉及到 WebRTC 端與微信小程式端的互動:case 3 由 WebRTC 支援;case 4 由 RTMP 中繼方案可解決。
基于 WebRTC 音視訊和微信小程式音視訊的互通方案,需要能支援 case 1 和 case 2。由于 WebRTC 端需要信令互動,是以需要分别讨論這兩種情況。
WebRTC 音視訊(主叫) 與 微信小程式音視訊(被叫)
在此case中,WebRTC Gateway 以被叫的身份與 WebRTC 端建立标準 WebRTC 會話。
- WebRTC 端首先初始化房間
- WebRTC 端加入房間
- 微信小程式端加入房間:Room Server 中添加了新的信令類型支援微信小程式以被叫的方式接入;此信令的處理過程中,回調 WebRTC Gateway 和 Streaming Server 進行資源初始化準備
- WebRTC 端發送 Offer 至 Room Server
- Room Server 接收到 Offer 之後,将該 Offer 資訊轉發至 WebRTC Gateway;WebRTC Gateway 需要響應該 Offer,如果正常的話應該傳回一個Answer 至 Room Server;Room Server 轉發 Answer 至 WebRTC 端
- 進入 ICE 協商和連接配接建立流程
此case下,WebRTC Gateway 作為微信小程式端的代理接入标準 WebRTC 棧,複用已有的 WebRTC 協定棧基礎設施(STUN/TURN/ICE/SDP),以減少對原 WebRTC 棧的侵入影響。
WebRTC 音視訊(被叫) 與 微信小程式音視訊(主叫)
在此case中,WebRTC Gateway 需要以主叫的身份與 WebRTC 端建立标準 WebRTC 會話。
- 微信小程式端首先初始化房間
- 微信小程式端加入房間:Room Server 中添加了新的信令類型支援微信小程式以主叫的方式接入;此信令的處理過程中,回調 WebRTC Gateway 和 Streaming Server 進行資源初始化準備
- WebRTC 端加入房間
- WebRTC Gateway 生成固定 Offer,發送至 Room Server
- Room Server 接收到 Offer 之後,将該 Offer 資訊轉發至 WebRTC 端;WebRTC 端需要響應該 Offer,如果正常的話應該傳回一個Answer 至 Room Server;Room Server 轉發 Answer 至 WebRTC Gateway
- 進入 ICE 協商和連接配接建立流程
此case下,WebRTC Gateway 作為微信小程式端的代理接入标準 WebRTC 棧,複用已有的 WebRTC 協定棧基礎設施(STUN/TURN/ICE/SDP),以減少對原 WebRTC 棧的侵入影響。
此 case 與前一個 case 的差別在于 SDP 資訊(Offer/Answer)的生成和處理。微信小程式端主叫時,由于微信小程式端不能正常參與到 WebRTC 棧的協定協商過程中來,需要在生成Offer時做一些針對性的優化和處理。
媒體流交換
由于 WebRTC 端和微信小程式端分别是用不同的媒體協定:WebRTC 端使用 RTP&RTCP;微信小程式端使用 RTMP,是以采用了 WebRTC Gateway 轉發 RTP 流和 Streaming Server 居中轉換的方案。
RTP 轉發
RTP 轉發即是将 WebRTC Gateway 作為微信小程式端的 WebRTC 代理,在通話過程中,将 WebRTC 端上傳的的 RTP 媒體流轉發至 Streaming Server,同時将微信小程式端上傳的經 Streaming Server 轉換過的 RTP 流轉發至 WebRTC 端。
具體實作基于 WebRTC Gateway 的擴充機制:為每一通會話預配置設定兩組音視訊端口(A & B),并:
- 收到 WebRTC 端的媒體資料後轉發至音視訊端口 A
- 收到音視訊端口 B 的媒體資料後轉發至 WebRTC 端
其中,音視訊端口 A 轉發的是 WebRTC 端發向微信小程式端的媒體流,由 Streaming Server 監聽;音視訊端口 B 收到的是微信小程式端發向 WebRTC 端的媒體流,來源是 Streaming Server,由 WebRTC Gateway 監聽。
轉碼子產品
Streaming Server 的轉碼子產品将 WebRTC Gateway 轉發的 RTP&RTCP 流轉換為 RTMP 流輸出至微信小程式端,也将微信小程式端上傳的 RTMP 流轉為 RTP&RTCP 流輸出至 WebRTC Gateway;最初的實作使用成熟的音視訊編解碼方案搭建,可以很好地支援 RTP&RTCP 與 RTMP 的雙向轉換。
具體來說,即:
- 将 RTP&RTCP 的媒體封包格式轉為RTMP的封包格式,反之亦然
- 将 RTP&RTCP 中的視訊(H264/vp8/vp9)轉為 RTMP 支援的H264,反之亦然
- 将 RTP&RTCP 中的音頻(opus)轉為 RTMP 支援的 AAC,反之亦然
中轉流程優化
在實際使用過程中,發現 Streaming Server 的轉碼子產品可以進行優化:WebRTC Gateway 轉發的 RTP&RTCP 流中的視訊編碼格式可以為 H264/VP8/VP9 等,具體格式由協商決定;微信小程式端支援的 RTMP 中可用的視訊流編碼格式為 H264;如果能夠限制 WebRTC 端使用的視訊編碼格式為 H264,可以優化為隻解包不解碼,減少視訊編解碼耗時。
基于以上分析,本文對中轉流程進行了重構,限制會話使用 H264 編碼傳輸視訊資料,并使用自研的 H264 裸流編解包代碼替換原有的視訊編解碼邏輯進行音視訊流中轉。實作微信小程式端通話時延從之前的 1-5s 優化到 500ms-1s,效果明顯。
實作細節如下:
- 修改 WebRTC Gateway 的 SDP 響應機制,在生成 Offer 或者響應 Answer 時隻傳回 H264 的視訊協商資訊。由于 58 的 WebRTC 端保證肯定支援 H264,是以不會導緻協商失敗
- 解析帶 H264 資料的 RTP 封包之後直接包裝成 RTMP 封包發出,不進行編解碼操作和視訊幀操作
- 音頻資料仍然進行編解碼。由于音頻資料資料包小,不會對通話時延造成明顯影響
RTMP 首幀優化
微信小程式端與 Streaming Server 之間通過 RTMP 傳輸音視訊資料,在通話開始時可能會有多于 2s 的黑屏現象。這是由于微信小程式端在顯示視訊流時需要根據 H264 流中的 IDR幀[5]的資料進行繪制,如果微信小程式端在建立連接配接時刻附近沒有可用的 IDR幀資料,播放器會進行等待,出現黑屏。
基于以上分析,本文優化了 Streaming Server 的 RTMP 中繼子產品中的邏輯,在推流就緒而拉流未就緒時會開始緩存資料幀,緩存的資料幀包含最新一幀 IDR幀及其後的所有資料幀。在拉流就緒之前,新的非 IDR幀持續加入緩沖隊列,新的 IDR幀重建緩重隊列;在拉流就緒之後,使用已有邏輯,拉流消費推流生産的資料流。實作微信小程式端通話建立時延從之前的 2-3s 優化到 1-1.5s,效果明顯。
會話保持
在會話的過程中,由于參與者多,資料鍊路比較複雜,本文采取了以下政策實作錯誤恢複和通話保持。
- WebRTC Gateway 作為 WebRTC 代理人,需要在整通會話中保持可用;如果不可用,Room Server 會使目前會話失敗,并将該伺服器從可用的清單中删去。可用性的檢測目前是在 Room Server 中使用 WebSocket 保持心跳實作的
- Streaming Server 作為中轉服務維持着雙向的媒體流,需要在整通會話中保持可用;如果不可用,Room Server 會使目前會話失敗,并将該伺服器從可用的清單中删去。可用性的檢測是在 Room Server 中通過 58 RPC 周期性輪循實作的
- Streaming Server 在單通會話中會保持雙向的媒體流,其任一媒體流失敗的機率都較高,是以實作了失敗重試邏輯;由于媒體流是有狀态的,在多伺服器部署環境下,重試任務時能根據伺服器進行隔離
出現錯誤或不可用的情況下,目前的通話會受到影響,在幾秒鐘内會被關閉;後續的新通話不會受到影響。
總結
本文主要介紹了在保持已有 WebRTC 的音視訊通話系統的基礎上實作的基于 WebRTC Gateway 的 WebRTC 端和微信小程式端的互通方案,分析了總體的架構方案和各個元件的實作邏輯細節。目前該方案已經成功落地,能提供穩定的音視訊通話能力;後續将繼續在整體方案的基礎之上,在 WebRTC Gateway 和 Streaming Server 進行持續優化,最終形成成熟可推廣的綜合方案。
參考:
[1]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
[2]: https://en.wikipedia.org/wiki/RTP_Control_Protocol
[3]: https://cloud.tencent.com/document/product/454/12517
[4]: https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol
[5]: https://en.wikipedia.org/wiki/Network_Abstraction_Layer#Coded_Video_Sequences
歡迎大家關注“58架構師”微信公衆号,定期分享雲計算、AI、區塊鍊、大資料、搜尋、推薦、存儲、中間件、移動、前端、運維等方面的前沿技術和實踐經驗。