全民K歌推流直播Web實踐

背景

2020年受到疫情的影響,大眾減少了線下娛樂,將更多的時間投入到了線上活動,直播行業迎來了一個小爆發,主播註冊數量與線上觀眾不斷增長。同時,在線直播演唱作為一種全新的演出模式,受到廣大網友的好評,4月以來TME承辦了近20場明星在線演唱會。

隨著站外直播場景業務需求逐步增多,K歌直播舊的業務代碼無法滿足不斷增長的產品功能需求和用戶體驗需求。在此背景下,Web側急需為推流直播業務提供更加可靠的技術支持。

HLS和HTTP FLV

目前K歌Web使用的直播流格式主要以HLS直播流為主。HLS(HTTP Live Streaming) 是由Apple提出的HTTP流媒體傳輸協議。其工作原理是服務端把整個流切分成一片片小的媒體流片段,客戶端通過下載一個包含源數據的extended M3U(m3u8)playlist文件用於尋找可用的媒體流,隨後開始下載格式為MPEG-TS的媒體片段,整體的流程圖如下:


全民K歌推流直播Web實踐

移動端 iOS 和 Android 都支持HLS協議,做好視頻採集、視頻流推流服務之後,便可以直接在H5頁面通過 video 標籤播放直播流。




<code>

<

video

>

<

source

id

=

"source"

src

=

"http://xxxx/video.m3u8"

type

=

"application/x-mpegURL"

/>

video

>

/<code>

HLS侷限性

HLS流最大的侷限性主要有:

  1. 在服務端對直播流進行切分處理之後客戶端才能拉取到數據,所以整體延遲較高,通常延遲可達到20~30s。
  2. 由於直播流分片拉取,所以客戶端需要頻繁地進行http請求,可能會導致播放卡頓。
  3. 通過video標籤進行hls播放,無法很好的在業務層進行定製化操作以及數據監控。

因此,前端還需支持更低延遲也更穩定的直播流,FLV直播流能滿足當下需求

HTTP FLV是將RTMP封裝在HTTP協議之上的用於傳輸flv格式的協議,其傳輸的http_flv是一個文件大小無上限的http流的文件。相較於HLS,HTTP FLV無需在服務端對直播流進行切片處理,所以具有低延遲的優勢,平均延遲只有1~2s。此外,HTTP FLV還具有一定程度上避免防火牆干擾、兼容302跳轉、支持HTTPS通道加密等優勢。

HTTP FLV侷限性

既然HTTP FLV相較於HLS有如此大的優勢,直接使用HTTP FLV不是更好嗎?

由於HTTP FLV的支持需要依賴於

MSE(Media Source Extensions) APIfetch+stream API ,而iOS瀏覽器不支持MSE API,所以flv流無法直接在iOS端播放。

FLV Web支持方案

通過原生的video標籤來進行flv流格式播放的方式不可行,是否有其他方法來支持flv在移動端的播放呢?調研發現,現階段支持移動端播放flv格式的js sdk主要有以下幾種,對比其在移動端的能力如下表所示:


全民K歌推流直播Web實踐

flv.js工作原理為:通過mse將flv流轉碼成fmp4給video進行播放,由於其本質還需依賴MSE,所以無法支持iOS。

NodePlayer.js 工作原理:通過ASM.js軟解碼H.264+AAC流,利用WebGL視頻渲染,WebAudio音頻播放來實現移動端flv直播流播放。

WXInlinePlayer與ffmpeg-player工作原理基本相似:

  1. 數據流獲取層:利用 XMLHttpRequest 或者 Fetch Api 從雲端的HTTP-FLV 流媒體獲取直播流數據。
  2. WASM解碼層:利用web worker開啟子線程,通過獲取視頻流metaData信息之後,對視頻進行解封裝,並將視頻流格式化為YUV,將音頻流格式化為PCM,進而將轉換好的數據回調給渲染層。
  3. 渲染層:渲染層將獲取到的視頻數據與音頻數據存入渲染緩存池中,WebGL 在 Canvas 上繪製視頻畫面,同時通過 Web Audio API 播放音頻。

WXInlinePlayer和now直播的ffmepg player兩者最大的區別在於其針對的目標有所不同。

  1. 解碼庫依賴方面

ffmepg player是在web側複用FFmpeg中的H.265解碼模塊實現前端解碼,整套解碼器在依賴h264\acc\flv的同時還依賴了hevc,所以ffmepg player同時支持了H.265與H.264兩種格式的視頻流。但正因如此,ffmepg player輸出的wasm文件體量較大,約1.3M。

WXInlinePlayer提供了可選的三套構建方案:baseline(不使用OpenH264),all(在baseline基礎上支持OpenH264)以及h265 (基於OpenH265),開發者可根據需求來選擇不同的解碼器,最終輸出文件體量視構建方案而定。基於OpenH264的解碼文件約800K。

  1. 解碼算法方面

WXInlinePlayer使用的主要是SWSFASTBILINEAR 算法。

ffmepg player使用的則是SWSBICUBIC 算法。兩者具體算法的差異對比可以參考雷神的性能測試文章《ffmpeg中的swsscale算法性能測試》

  1. 文件部署方面

ffmepg player從網絡性能的角度考慮,將wasm和js膠水代碼部署在cdn上,通過fetch 請求web worker cdn的方式來實現項目對sdk的訪問。

WXInlinePlayer相對來說更"簡單粗暴",直接將wasm和膠水代碼轉成base64的形式注入到sdk代碼中,最終輸出為單個的js文件。

總結來說,要想讓web端可以很好的支持flv,實現多平臺的支持http-flv流播放器,主要開發思路如下:

通過wasm來編譯解碼器從而實現在前端進行flv格式的解碼,輸出YUV視頻數據以及PCM音頻數據,利用webgl渲染YUV,Web Audio API播放PCM音頻最終實現flv播放。

技術流程圖如下:


全民K歌推流直播Web實踐

為此,K歌web團隊封裝了一套同時支持hls和flv視頻流播放的kg-player SDK。

kg-player SDK

我們對WXInlinePlayer 以及騰訊自研的TCPlayer進行了源碼優化,解決了iOS端畫音不同步、移動端系統適配以及webgl渲染旋轉等問題,將其封裝成kg-player SDK。

例如,WXInlinePlayer使用的OpenH264解碼模塊,在iOS端和Android端有差異化的表現,在iOS端會對首幀進行額外解碼,導致第二段音頻每次都會包含第一段音頻,從而使得畫音不同步。對此,我們在邏輯層對iOS端的第一段音頻進行記錄,在audioSrc.start播放時減去第一段時長,使音頻時間軸整體前偏移首段音頻的長度,最終使音視頻保持同步。

再例如,由於K歌iOS主播端的推流沒有對直播源進行旋轉,導致原本豎屏的直播流為橫屏狀態。對此,我們在webgl渲染層面對其進行邏輯封裝,通過視頻的寬高信息對直播流進行檢測,通過矩陣變換視頻流進行旋轉。

優化後的flv解析流程如下:


全民K歌推流直播Web實踐

kg-player SDK 能夠同時支持flv和hls兩種格式的視頻流播放,支持多碼率流地址傳入以及流地址切換。通過兼容性測試發現,hls支持大部分移動端設備。而flv由於需要web端支持WASM所以僅支持iOS 12及以上系統, Android 5及以上系統。對此我們在sdk初始化階段會對當前使用的機型進行判斷,針對不同機型進行適配性降級,從而保證直播流能夠正常播放。此外,SDK能自動檢測瀏覽器的播放性能,當頁面發生卡頓或播放性能較糟糕時(如整體頁面fps低於24),會觸發降級回調事件,由業務層邏輯判斷是否降級到低碼率流或從flv切回hls流來保證整體播放性能。

技術架構

K歌Web側推流直播的整體技術架構圖如下:


全民K歌推流直播Web實踐

整個技術架構分為三個模塊,基於kg-player sdk的直播流播放模塊,基於kg-im sdk的直播間消息模塊以及禮物動畫渲染模塊。

kg-im sdk通過輪詢的方式獲取直播間的互動消息(禮物消息,評論消息,喇叭消息等),並根據消息池中消息的總數來彈性控制每次拉取消息間隔的時間,進而保證前端能夠及時高效拉取消息且不會造成額外的網絡開銷。同時SDK會對消息進行二次封裝,去掉冗餘字段,封裝成前端更易識別的消息結構體,減少前端業務代碼。kg-gift 同時支持視頻動畫,webgl動畫以及傳統的css動畫來滿足直播業務中較為複雜的禮物動畫需求。

直播性能數據

hls流與flv流各有優劣,在接入kg-player sdk之後,具體的性能對比數據如下:

首幀渲染時間


全民K歌推流直播Web實踐

由於flv播放需要通過前端的WASM進行軟解碼,所以從第一幀傳輸到渲染上屏需要的時間要略長於hls流播放。

播放卡頓率

在kg-player內會設置心跳檢測,其核心邏輯是通過設置timeInterval來進行心跳記錄,心跳間隔2秒,2秒內如果出現當前播放時間和上一次心跳時的播放時間一致的情況則標記當前出現卡頓並進行一次"卡頓"上報,否則則進行一次"流暢"上報。


全民K歌推流直播Web實踐

注:Web頁面在某些交互場景如微信端點擊右上角或播放時切後臺等操作,會導致心跳計數誤差,上報的卡頓率要略大於實際卡頓率

可以看到FLV流由於不需要切片請求,使得整體的拉流更為流暢,同樣的網絡狀況下,其播放的卡頓率要遠低於HLS。

降級

kg-player SDK在檢測到頁面出現卡頓時會對播放流進行降級,從720p分辨率的流降級到540p,或者從flv降級到hls,由於flv流播放依賴於WebGL渲染,而WebGL渲染又依賴手機硬件性能,所以對於低端機會出現降級情況。


全民K歌推流直播Web實踐

可以看到,整體降級率約為11.49%,這也表明flv在web端的支持有一定的優化空間。

進一步優化

通過wasm進行軟解碼並通過webgl進行渲染的技術方案,雖然能夠很好的解決移動端播放不了flv直播流的問題,但是由於軟解碼和webgl渲染十分依賴硬件性能,導致很多中低端機型無法很好的播放flv流。

通過對比發現,iOS系統能夠很好的解碼並播放720p的直播流視頻,但是Android端只能勉強支持540p的直播流視頻,且在頁面進行其他渲染(禮物動畫,喇叭廣播動畫,評論滾動動畫)時,由於硬件性能跟不上,Android端有一部分機型會降級到hls直播流,Android端的降級率接近iOS的三倍。


全民K歌推流直播Web實踐

針對上述問題,我們對kg-player SDK進行了進一步的優化,對於Android端這一類性能不穩定的系統,我們迴歸到通過MSE的方式進行flv直播流的加載,利用現有的sdk如flv.js或者videojs來進行flv直播流加載。使用優化策略後,整體降級率大幅降低,對比圖如下:


全民K歌推流直播Web實踐

且優化後無需使用WASM進行軟解碼,所以首幀平均耗時也得到了降低:


全民K歌推流直播Web實踐


除此之外,播放卡頓方面也有進一步的優化空間,通過實時監控頁面的卡頓率,我們可以自適應的降級到後臺提供的更低分辨率的直播流,使得直播源能夠自適應用戶網絡環境。

上層業務支持

利用推流直播技術基礎,我們能夠較好的支撐現有的直播業務。目前主要的落地場景包括K歌直播站外H5分享頁(日均PV 30W左右)以及TME live直播(場均PV50W左右),在保證前端渲染性能的同時也能給用戶提供很好的交互體驗。


全民K歌推流直播Web實踐

總結與展望

通過對現有的直播技術方案進行封裝優化,我們實現了滿足K歌業務需求的技術框架,在此基礎上能夠很好的支持各個直播項目,也提升了開發效率。

未來我們還將支持更多的Web直播業務場景例如直播歌房等,而K歌直播技術架構也將會不斷完善,從整體性能以及用戶體驗上出發,不斷進行優化以便更好的支撐起更多更復雜的直播項目。

整個技術架構的sdk代碼也在優化封裝中,功能穩定成熟之後也將嘗試開源。

另外關於c++ Linux後臺服務器開發的一些知識點分享:Linux,Nginx,MySQL,Redis,P2P,K8S,Docker,TCP/IP,協程,DPDK,webrtc,音視頻等等視頻。

喜歡的朋友可以後臺私信【1】獲取學習視頻

全民K歌推流直播Web實踐

全民K歌推流直播Web實踐

喜歡的朋友可以後臺私信【1】獲取學習視頻以及一套Protobuf協議詳解語法給大家


分享到:


相關文章: