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與微信小程序音視頻互通方案設計與實現


  1. WebRTC Gateway 作為一個特殊的 WebRTC 端與指定的另一個 WebRTC 端通過 Room Server 交換信令並建立會話
  2. 會話建立後,WebRTC 端與 WebRTC Gateway 直接(P2P)或間接(TURN)交換音視頻流
  3. WebRTC Gateway 將 WebRTC 端之音視頻流經 Streaming Server 轉發至微信小程序端;微信小程序音視頻輸入流經 Streaming Server 轉發至WebRtc 端


其中,WebRTC Gateway 使用成熟的服務來搭建,主要作為微信小程序端的 WebRTC 代理輔助微信小程序端參與 WebRTC 的會話,主要進行信令的溝通、Offer/Answer 的協商和媒體流數據的轉發;Streaming Server 包括 RTMP 中繼模塊和轉碼模塊,主要提供 RTP&RTCP 媒體流和 RTMP 媒體流數據的轉換和中繼;在已有的 Room Server 上擴展,添加了與接入微信小程序端相關的信令處理邏輯。

會話建立

需要支持 WebRTC 端與微信小程序端的音視頻流的互通,首先需要添加對其建立會話的支持;WebRTC 端與微信小程序端的會話建立,具體來說是指:

  1. WebRTC 音視頻(主叫) 與 微信小程序音視頻(被叫)
  2. WebRTC 音視頻(被叫) 與 微信小程序音視頻(主叫)
  3. WebRTC 音視頻(主叫) 與 WebRTC音視頻(被叫)
  4. 微信小程序音視頻(主叫) 與 微信小程序音視頻(被叫)

其中,case 3 和 case 4 不會涉及到 WebRTC 端與微信小程序端的交互:case 3 由 WebRTC 支持;case 4 由 RTMP 中繼方案可解決。

基於 WebRTC 音視頻和微信小程序音視頻的互通方案,需要能支持 case 1 和 case 2。由於 WebRTC 端需要信令交互,所以需要分別討論這兩種情況。

WebRTC 音視頻(主叫) 與 微信小程序音視頻(被叫)

在此case中,WebRTC Gateway 以被叫的身份與 WebRTC 端建立標準 WebRTC 會話。

  1. WebRTC 端首先初始化房間
  2. WebRTC 端加入房間
  3. 微信小程序端加入房間:Room Server 中添加了新的信令類型支持微信小程序以被叫的方式接入;此信令的處理過程中,回調 WebRTC Gateway 和 Streaming Server 進行資源初始化準備
  4. WebRTC 端發送 Offer 至 Room Server
  5. Room Server 接收到 Offer 之後,將該 Offer 信息轉發至 WebRTC Gateway;WebRTC Gateway 需要響應該 Offer,如果正常的話應該返回一個Answer 至 Room Server;Room Server 轉發 Answer 至 WebRTC 端
  6. 進入 ICE 協商和連接建立流程

此case下,WebRTC Gateway 作為微信小程序端的代理接入標準 WebRTC 棧,複用已有的 WebRTC 協議棧基礎設施(STUN/TURN/ICE/SDP),以減少對原 WebRTC 棧的侵入影響。

WebRTC與微信小程序音視頻互通方案設計與實現

WebRTC 音視頻(被叫) 與 微信小程序音視頻(主叫)

在此case中,WebRTC Gateway 需要以主叫的身份與 WebRTC 端建立標準 WebRTC 會話。

  1. 微信小程序端首先初始化房間
  2. 微信小程序端加入房間:Room Server 中添加了新的信令類型支持微信小程序以主叫的方式接入;此信令的處理過程中,回調 WebRTC Gateway 和 Streaming Server 進行資源初始化準備
  3. WebRTC 端加入房間
  4. WebRTC Gateway 生成固定 Offer,發送至 Room Server
  5. Room Server 接收到 Offer 之後,將該 Offer 信息轉發至 WebRTC 端;WebRTC 端需要響應該 Offer,如果正常的話應該返回一個Answer 至 Room Server;Room Server 轉發 Answer 至 WebRTC Gateway
  6. 進入 ICE 協商和連接建立流程

此case下,WebRTC Gateway 作為微信小程序端的代理接入標準 WebRTC 棧,複用已有的 WebRTC 協議棧基礎設施(STUN/TURN/ICE/SDP),以減少對原 WebRTC 棧的侵入影響。

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),並:

  1. 收到 WebRTC 端的媒體數據後轉發至音視頻端口 A
  2. 收到音視頻端口 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 的雙向轉換。

WebRTC與微信小程序音視頻互通方案設計與實現

具體來說,即:

  1. 將 RTP&RTCP 的媒體封包格式轉為RTMP的封包格式,反之亦然
  2. 將 RTP&RTCP 中的視頻(H264/vp8/vp9)轉為 RTMP 支持的H264,反之亦然
  3. 將 RTP&RTCP 中的音頻(opus)轉為 RTMP 支持的 AAC,反之亦然


中轉流程優化

在實際使用過程中,發現 Streaming Server 的轉碼模塊可以進行優化:WebRTC Gateway 轉發的 RTP&RTCP 流中的視頻編碼格式可以為 H264/VP8/VP9 等,具體格式由協商決定;微信小程序端支持的 RTMP 中可用的視頻流編碼格式為 H264;如果能夠限制 WebRTC 端使用的視頻編碼格式為 H264,可以優化為只解包不解碼,減少視頻編解碼耗時。

基於以上分析,本文對中轉流程進行了重構,限制會話使用 H264 編碼傳輸視頻數據,並使用自研的 H264 裸流編解包代碼替換原有的視頻編解碼邏輯進行音視頻流中轉。實現微信小程序端通話時延從之前的 1-5s 優化到 500ms-1s,效果明顯。

實現細節如下:

  1. 修改 WebRTC Gateway 的 SDP 響應機制,在生成 Offer 或者響應 Answer 時只返回 H264 的視頻協商信息。由於 58 的 WebRTC 端保證肯定支持 H264,所以不會導致協商失敗
  2. 解析帶 H264 數據的 RTP 報文之後直接包裝成 RTMP 報文發出,不進行編解碼操作和視頻幀操作
  3. 音頻數據仍然進行編解碼。由於音頻數據數據包小,不會對通話時延造成明顯影響


RTMP 首幀優化

微信小程序端與 Streaming Server 之間通過 RTMP 傳輸音視頻數據,在通話開始時可能會有多於 2s 的黑屏現象。這是由於微信小程序端在顯示視頻流時需要根據 H264 流中的 IDR幀[5]的數據進行繪製,如果微信小程序端在建立連接時刻附近沒有可用的 IDR幀數據,播放器會進行等待,出現黑屏。

基於以上分析,本文優化了 Streaming Server 的 RTMP 中繼模塊中的邏輯,在推流就緒而拉流未就緒時會開始緩存數據幀,緩存的數據幀包含最新一幀 IDR幀及其後的所有數據幀。在拉流就緒之前,新的非 IDR幀持續加入緩衝隊列,新的 IDR幀重建緩重隊列;在拉流就緒之後,使用已有邏輯,拉流消費推流生產的數據流。實現微信小程序端通話建立時延從之前的 2-3s 優化到 1-1.5s,效果明顯。

會話保持

在會話的過程中,由於參與者多,數據鏈路比較複雜,本文采取了以下策略實現錯誤恢復和通話保持。

  1. WebRTC Gateway 作為 WebRTC 代理人,需要在整通會話中保持可用;如果不可用,Room Server 會使當前會話失敗,並將該服務器從可用的列表中刪去。可用性的檢測目前是在 Room Server 中使用 WebSocket 保持心跳實現的
  2. Streaming Server 作為中轉服務維持著雙向的媒體流,需要在整通會話中保持可用;如果不可用,Room Server 會使當前會話失敗,並將該服務器從可用的列表中刪去。可用性的檢測是在 Room Server 中通過 58 RPC 週期性輪循實現的
  3. 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、區塊鏈、大數據、搜索、推薦、存儲、中間件、移動、前端、運維等方面的前沿技術和實踐經驗。


分享到:


相關文章: