基于WebRTC的互动直播实践
互動直播已經逐漸成為直播的主要形式。映客直播資深音視頻工程師葉峰峰在LiveVideoStackCon 2018大會的演講中詳細介紹了INKE自研連麥整體設計思路、如何基于WebRTC搭建互動直播SDK以及針對用戶體驗進行優化。本文由LiveVideoStack整理而成。
文 / 葉峰峰
整理 / LiveVideoStack
大家好,我是葉峰峰,來自映客直播,從事實時音視頻的開發工作大概有七八年時間了,在加入映客后,也參與了映客實時互動直播的開發過程。本次分享主要介紹映客互動直播開發過程中遇到的一些問題,以及對直播場景下互動直播的一些優化。
本次分享內容可以分為四個部分。第一部分,簡單介紹互動直播的發展;第二部分,介紹映客互動直播SDK是如何從0到1構建起來的,并從推流端和播放端兩方面來介紹對它進行的優化;第三部分,介紹配合互動直播體系的一些監控和運營相關的內容,以及我們如何依賴于這種體系解決線上的問題;第四部分,總結和展望,主要是對下一步工作的思考。
一、互動直播發展簡介
1、CDN直播
CDN直播指的是單個主播使用RTMP協議進行推流的直播形式。主播端推流使用的是基于TCP的RTMP協議,直接推流到我們的CDN源站,觀眾端通過CDN的邊緣節點進行拉流和播放,整條鏈路都是使用的TCP,所以技術是比較成熟的。雖然這種形式便于我們的業務推廣,但同時也存在著直播形式單一、缺少互動話題的缺點。為了解決CDN直播缺乏觀眾和主播間交互的問題,進而引入了互動直播。
2、互動直播
互動直播一般是指主播和主播之間通過RTP來進行推拉流的方式,它的形式比較多樣、話題點也非常豐富。與觀眾互動的方式除了評論區互動外,還可以通過音頻、視頻連麥的方式使觀眾加入到直播過程中與主播面對面進行交流。但是,互動直播的缺點是對傳輸時延比較敏感,并且整個直播系統的實現比較復雜。在CDN直播里面,只需要將流推到CDN源站就可以了,而互動直播既不僅要把我們的流推到連麥服務器,還要解決主播與主播之間拉流進行互動播放的問題。
3、主播PK介紹及CDN vs 互動
接下來,我們重點看一下互動直播中比較特殊的一個場景即主播PK場景。連麥場景中的所有觀眾都屬于當前某個主播的觀眾,輔麥沒有自己的觀眾,而直播PK場景與之不同。在PK開始之前,兩邊的主播都有各自的觀眾,所以在播放端就需要針對PK場景進行一些特殊的優化。雖然我們的互動直播已經加入了觀眾與主播之間通過音頻、視頻進行溝通的渠道,但并沒有形成一個非常有效的協作,不能很直接的引起觀眾對平臺做貢獻的行為,如送禮物等。因此,在PK發起的過程中,觀眾可以通過送禮物來影響PK的整個 過程。我們可以看到上圖右側所展示的主播1v1PK場景中,每個主播會顯示有一個血條,當觀眾送禮時血條則會增長,結束時哪方觀眾送的禮物多就會勝利。這樣一來,就能讓觀眾更多地參與到直播的過程中,而且是通過送禮物的方式。如果大家最近觀看過映客直播,就會看到我們最近在開展PK排位賽的業務。PK排位賽業務指的是在PK的過程中,當有人第一個給主播送禮,就會在兩個主播中間展示一個首殺的動畫特效,使得用戶獲得一種不一樣的參與感。而且在PK結束時,會在勝利一方的觀眾里選出對本場勝利貢獻最多的觀眾稱之為MVP,同樣會是在兩個主播中間的位置展現一個三秒的動畫特效。目前來講,PK業務是我們整個互動直播中最有價值的一個業務場景。
介紹完CDN直播和互動直播后,接下來把它們進行一個對比。從主播端來看,在業務形式上,CDN直播一般是單個主播的,而互動直播是多個主播的。在傳輸協議上,CDN直播主播端是使用基于TCP的RTMP協議來推流的,而互動直播一般是使用基于UDP的RTP協議來推流的。由于互動直播是基于UDP的,所以我們還需要考慮應用層的丟包重傳問題。在實現復雜度上,CDN直播是相對較低的,而互動直播實現復雜度相對較高。從觀眾端來看,都是使用HTTP-FLV/RTMP來進行拉流播放,且都是基于TCP的。但是,CDN直播只有一路流,而互動直播考慮到直播場景的卡頓率或者一些指標的體驗優化,我們目前使用的是主播多流的方式。多個主播之間可能使用的是不同CDN分發的多流,互動直播在觀眾端還會考慮一些多流間同步的操作。
4、直播系統架構拓撲
下面簡單介紹一下CDN直播和互動直播的架構拓撲。對于CDN直播,它是直接通過RTMP協議推流到CDN源站,CDN源站包含邊緣節點,在觀眾拉流時,從邊緣節點請求拉流,然后進行播放。在設計互動直播系統的時候,考慮到不可能在觀眾端自己搭建CDN,所以觀眾端同樣是使用我們的CDN進行轉發、分發的。我們在打造互動直播系統過程中,更多的是進行主播端系統的搭建和開發,包括參與互動的主播之間的音視頻實時推拉流、連麥服務器,主播之間數據的中轉和轉發,以MCU服務器。對于多流,MCU服務器負責把RTP流轉成RTMP流并推到CDN源站,實現主播的RTP和CDN節點之間的解耦合,這樣從MCU服務器出來的流就是一個標準的RTMP流,也便于不同用戶、主播調用不同的CDN來分發數據。與此同時,MCU也會進行合流,合流的部分主要應用于錄像和審核系統。
二、映客互動直播SDK及體驗優化
1、什么是直播需要的互動SDK?
什么是直播需要的互動SDK?其實直播里的互動是屬于VOIP實時通話領域的一種特殊應用,接下來會介紹它的一些特點。如上圖左邊部分所示,這是在我們做互動直播SDK之前的一個CDN推流的SDK。它包含了一個PushManager接口層,下面有AudioStream和VideoStream這兩部分,AudioStream里面有音頻的采集、前處理、編碼,VideoStream同樣有視頻的采集、前處理和編碼,最后,音頻和視頻數據會送到LibRTMP來直接推到我們的CDN源站。這是一個CDN直播的基本架構,對于互動直播的實現,首先想到的是通過WebRTC。但是,經過對WebRTC的分析發現,其實我們并不能完全地照搬WebRTC來實現我們的互動直播的業務。主要原因如下:第一,WebRTC是一個面向通話的解決方案。它采集的音頻是8K或16K的,因為人在通話過程中信號的頻率是不超過4KHz的,而互動直播里我們要解決的是主播唱歌等一些音樂場景,所以必須要求是高采樣率的,我們用的是48K的采樣率。第二, WebRTC里音頻編碼用的是iLBC和Opus,這兩個是低碼率的實時音視頻的音頻編碼器,而在互動直播里一般都是用AAC-LC的編碼方式,用LC是為了兼容性更好。第三,為了延時更低,WebRTC是10~32Kbps的低碼率音頻編碼,視頻編碼采用的是VP8和VP9,而我們音視頻直播里要用到64~128Kbps的高碼率的音頻編碼,VP8和VP9也不適合在我們的CDN上廣泛傳播,我們使用的是H.264這種比較通用的視頻編碼。第四,從視頻參數上來講,WebRTC一般是VGA、800Kpbs的分辨率格式的,而我們視頻直播里一般都是576P、1.2Mbps的高碼率視頻編碼格式。第五,最重要的,在傳輸方式上,WebRTC使用P2P方式來進行媒體中轉,它只是解決端到端的問題,而對于互動直播來說,主播的數據是非常重要的數據,并不僅僅解決主播端的音視頻互通問題,我們還要把主播的數據推送到連麥服務器、CDN,且要保證到達我們的觀眾端,所以在連麥系統上我們采用的是Relay的方式,很好地避免了P2P跨運營商,跨地域的問題。
2、互動SDK和直播SDK結構
雖然WebRTC并不能完全滿足我們的互動直播場景,但我們能參考WebRTC的是什么呢?因為我們已經有了音頻采集、音頻編碼、視頻采集、視頻編碼,這些都是可以復用的,所以在構建互動直播SDK的過程中,我們需要實現的是一個實時連麥庫。通過參考WebRTC,我們的實時連麥庫如上圖左邊所示,在發送端,有一個RTP Packer把編碼器輸出的AAC和H264數據進行拆幀,拆為RTP包并進行封裝,送FEC模塊進行前向冗余后再通過發送模塊發送出去。連麥服務器數據被對端的主播拉流下來并進行播放時,他會先進到NACK和GCC模塊,在底下的傳輸模塊如果出現丟包,NACK模塊會進行丟包重傳,FEC模塊前向冗余以后,在解碼時可以通過冗余數據恢復出丟包數據。接下來,RTP包送到NetEQ模塊和VCM模塊,音頻送到NetEQ模塊,視頻送到VCM模塊。NetEQ會對AAC進行解碼,解碼后會嘗試進行一些錯誤恢復,如果出現丟包會進行一些等待。VCM模塊把RTP包組成video frame,當它接收到完整數據以后就回到上層進行音視頻的播放。如上圖右邊所示,在互動直播SDK中,左邊是我們的推流模塊,最下面變成了LibRTMP和連麥庫,我們進行連麥操縱時,編碼數據會送到連麥庫推到連麥服務器。那么在連麥過程中,如何去播放另一個主播的數據呢?這里就會用我們的連麥庫把另一主播的數據下載下來,實時拉流后采用ijkPlayer進行播放。另外,我們的連麥流也會以私有協議的方式送到RTP Player里來播放,觀眾會使用RTP Player直接拉CDN的FLV流來進行播放。這樣一來,整個SDK就可以實現CDN的推流、CDN的拉流、連麥推流、連麥拉流的過程。
3、如何提升用戶體驗?
?
我們在構建了推流和連麥SDK后,又做了哪些用戶體驗和優化呢?在這里會分兩部分來介紹,一個是主播推流端的優化,一個是觀眾端的優化。對于主播推流端,主要解決的是弱網的傳輸問題,在傳輸上可能發生UDP丟包,所以我們要解決丟包的問題,抗丟包主要包括碼率自適應和4G通道冗余技術,還有就是在主播推流之前要選最優的推流網絡。另外,在推流端還有移動端的性能開銷問題,我會介紹一下我們的前處理優化和硬編解優化。對于觀眾端,我會介紹一下秒開相關的技術,以及多流的相關優化,再就是既然我們可以用UDP來加速主播端,那么在觀眾端也是可以通過UDP來優化下行的,在QUIC我們也做了一些嘗試。
4、主播端體驗優化
a)?傳輸,性能
主播端體驗優化包括四個部分如下:
第一部分是動態策略。主播端在傳輸的過程中,采用了更嚴苛的碼率自適應策略。由于WebRTC是面向實時音視頻通話的,可能對丟包、花屏不是特別地關心,所以在WebRTC里,丟包率2%以下是允許碼率上升的,丟包率2%~10%是保持著一種狀態,只有丟包率大于10%時才會進行碼率的下調。但是在互動直播里,我們必須做到出現丟包就下調碼率,來保證直播不花屏、不卡頓。此外,我們的碼率自適應有一個快降慢升的邏輯,并不是實時地隨著網絡去變化,因為網絡是非常復雜的,如果我們的碼率上調太快,則會導致網絡出現一個很不穩定的狀態。快降慢升的方式就是當出現丟包的時候,馬上下調碼率,并且只有當保持了5秒以上的穩定狀態后,才允許碼率上調。此外,還有一個Hybrid的ARQ模塊,這個模塊指的是針對不同的網絡要使用不同的策略。在低延時的網絡中,可能丟包后使用ARQ是最高效的,而高延時的情況下,就要加上FEC了。雖然FEC會增加發送端的網絡開銷,但是它是一種更加實時性、高效的方式。在用到FEC過程中,我們會依賴不同的用戶網絡來調整我們的冗余策略,以此達到一個比較好的傳輸效果。最后,我們的連麥服務器是允許實時切換的,如果連麥服務器在連麥過程中出現了問題,我們可以切到其他的連麥服務器上,整個過程會卡一下,但不會影響業務的正常進行。
第二部分是多徑冗余。當主播端在用WiFi進行推流時,就可以嘗試使用我們的4G路徑進行補償。因為互動推流是推到連麥服務器上的,如果用戶使用WiFi時出現了丟包,一方面,可以使用我們的ARQ和FEC來解決,另一方面,如果用戶給了我們4G權限,我們就會建立另外一條4G通道來進行數據傳輸形成一個4G的路徑補償,當然這個數據傳輸是有限制的,大約最高不超過WiFi路徑20%的流量。另外,4G路徑也只是對一些高價值的數據進行傳輸,高價值數據指的是已經在WiFi路徑上出現丟包的數據。如果出現了丟包,我們會在WiFi和4G路徑上同時進行這個包的傳輸,來保證丟包可以更高效的恢復出來。引入了4G補償的多徑冗余方式以后,整體的觀看卡頓率降低了1%。
第三部分是基礎網絡的建設。我們在全國有5個BGP機房,兩條海外專線,我們的服務端是有保障的。另外,我們的主播端也是有保障的,因為主播既是我們的用戶,也是我們的合作人,主播也會提供有保障的網絡。最后,在前面有提到過開播前的網絡優選,當主播在發起直播的過程中,他會調參數或給直播間起名字,在這個過程中我們就能探測他的網絡,然后從所有的節點里面選出一個比較好的節點來完成主播推流網絡的優選。
第四部分是性能優化。在直播過程中經常遇到的一個問題就是設備發熱,發熱會導致系統降頻,以及對攝像頭的采集掉幀嚴重。在性能優化這塊,我們又做了哪些工作呢?首先,就是我們的美顏和特效是可配置的,類似于白名單的機制。我們的美顏在一些性能比較差的機器上是可以選擇不開的,特效在不同的機型都有不同的展示。其次,除了個別機型不能支持音視頻硬編解外,我們的機房都實現了音視頻的硬編解。再者,在部分機型上,禮物的動畫特效展示的效果是不一樣的。最后,在連麥里邊,我們把對網絡的Ping、DNS解析等操作進行封裝,進行一個異步的IO網絡庫優化,這樣能節約一部分網絡操作的開銷。
b)?傳輸優化結果展示
上圖是傳輸優化結果的展示,左邊的部分展示的是我們使用一個推流Demo,做了一個Echo模式的推拉流,延遲基本在有一百多毫秒。經過我們的優化,我們能保證主播與主播之間的延遲在150毫秒延遲左右,主播端與觀眾端延遲基本在兩到三秒。基于重傳自適應策略與4G補償策略,我們可以保障在50毫秒20%丟包率的情況下流暢直播。
5、觀眾端體驗優化
a)?秒開、多流、傳輸
觀眾端體驗優化分為秒開、多流和傳輸三部分。
第一部分是秒開。秒開是直播里非常重要的一個概念,指的是從進入直播間到設備出現畫面的時間,對于秒開優化分為以下幾個方面:在服務端上,第一,在CDN上支持關鍵幀GOP緩存。用戶播放某個直播間的數據時,是從關鍵幀開始播放的,基本上現在所有的CDN都支持這樣的一個特性。第二,我們自己有一個優選服務,用戶從不同的CDN拉流時,我們會進行一個優選服務。但并不是逐個房間進行優選,而是支持批量加載和服務端的結果緩存,這樣能瞬間將批量的流一次性加載下來,合并以后進行后續探測來獲得優選的效果。目前,優選主要是客戶端對大廳數據的批量加載,然后送到優選服務器,獲取下行拉流節點后,就進行一個快速的PING探測,探測以后在我們用戶播放的時候,就直接從固定的機器上拉流就可以了。
b)?多流
第二部分是多流。在前面的介紹中,我們知道PK場景和連麥場景的差別,連麥場景中輔麥加入時,對于主麥來說,它是不需要停流的,只是需要把它的流合并到主流中。而PK場景是A主播的流中斷,B主播的流也中斷,我們采用的是多人多流的方式來進行直播。另外,為了低延時,我們的實時流只能是使用多流的方式。再就是,觀眾端也使用CDN多流來減少PK場景的卡頓率。
c)?多流同步、H.264 SEI
第三部分是多流同步。大家可能都知道,一條流里音頻、視頻的同步是依賴于音頻流和視頻流使用的是同一個機器,因為這樣它們就有同樣的時間軸,只需要采集各自的時間,然后進行偏移量的移植,基本上就可以實現音視頻同步。但是多流之間要如何實現同步播放呢?另外,在我們的直播系統中,存在一個數據由不同協議分發的問題,并且還要保證時間信息能和數據一同傳到觀眾端。為了解決這個問題,我們使用H.264 SEI自定義幀的方式來進行多流同步。我們通過在H264數據里加入自定義數據,連麥服務器、CDN都會保留這份數據到觀眾端,在觀眾端兩條流拉下來后,依賴于這樣一個流同步的數據來進行多流之間的同步。主播在開播之前,需要從NTP時間服務器來進行對時,對時以后,我們認為多個主播之間有一條時間軸和我們的NTP服務器是同步的,多個流之間就依賴于這個時間軸來進行同步。H.264里的SEI數據是一個留給用戶擴展的數據,尤其SEI里類型33的Unregistered SEI,就是我們可以自己擴展的。幀格式如上圖所示,這個幀前面有一個4字節的70碼,還有一個1字節的幀類型的碼,接下來就是SEI類型碼,后邊是一個BUFFERLENGTH的長度,它是一個動態的公式。在這個PayLoad之后,是一個16字節的UUID,類似于消息類型的格式,每一種應用都會定義自己的UUID來校驗不同的消息類型,后面就是自定義的消息,最后有個2字節的尾部。PayLoadSize是動態的,每增加255字節,則多一個字節的BufferLength來表示這個BufferLength,這樣是為了避免數據幀里邊的數據和提示碼會進行競爭,也是SEI的標準規范的一個方式。再往下面看,我們在流A的I幀前面加了SEI同步信息,在流B的I幀前面也加了SEI信息,兩個流就算在CDN分發上有時間差,播放端依賴于這兩個流里的SEI同步信息,也能實現兩條流在播放端同步。
d)?傳輸優化
第三部分是傳輸優化。觀眾端在最開始的時候,是通過CDN源站的CDN邊緣節點來實現播放的。但是,有一些特殊的業務可能是主播帶著大家一起玩游戲,主播把大家的游戲畫面投上去,此時需要參與的用戶能實時地接收到主播的協同指令,這樣就要求游戲的這邊拉RTP流,但是它只是單向的拉流,不會向主播端推流,因為游戲過程中,主播是不需要關注其他人的畫面的。此外,我們也有在考慮QUIC的建設,依賴于QUIC節點來優化客戶端在弱網環境下的流暢率。
e)?QUIC的介紹
接下來介紹一下我們在QUIC方面的工作,QUIC是基于UDP的,是Google提供的一個開源項目,集成在Chrome中。由于HTTP網頁在弱網環境下的加載是比較低效的,當出現阻塞或卡頓時,后面的數據都不能進行有效的傳輸。為了提高頁面上的響應速度,Google就開發了基于UDP的QUIC,QUIC能提供和TCP+TLS+HTTP/2一樣的功能,并且QUIC是基于UDP的有保障的傳輸,它在內部做了重傳機制。此外,YouTube用到QUIC后減少了緩沖, QQ空間在使用了QUIC以后也提高了網頁的加載速度,映客直播在使用QUIC后也是能夠減少弱網卡頓,并優化弱網秒開和降低卡頓率的。
f)?QUIC在直播中的應用
QUIC在映客直播里的應用包括主播端的RTMP or QUIC和播放端的HTTP or QUIC。在這里主要用到它的兩個特性,一個是減少了連接時間,優化秒開,一個是改進了丟包算法,優化了弱網卡頓。其中我們所做的工作包括:第一,移植QUIC。QUIC并不是一個協議的形式,它是集成在Chrome中的,因此我們需要把它移植到安卓平臺、IOS平臺。通過客戶端移植QUIC,讓內部RTMP支持QUIC,播放器也支持QUIC,我們服務端支持QUIC,可能稍微好一點,由于QUIC Go這樣的項目比較容易集成,推流和拉流CDN也支持QUIC。在500Kbps和1%丟包的情況下,主播端使用QUIC和TCP同時進行RTMP推流。觀看對比就發現使用QUIC推流,播放基本上是比較流暢的,而使用TCP推流的播放則是非常卡頓的。
三、監控與運營支撐
1、為什么要做直播追蹤和運營相關系統?
?
在這部分,我會介紹一些運營相關的內容。在開發過程中遇到大量的問題時,不能完全依賴開發去定位問題,這時直播流程追蹤系統和大數據分析系統都是非常重要的。直播流程追蹤系統可以把直播過程中的關鍵事件進行匯報,在追蹤系統上進行逐個排列,出現問題時只要對主播的UUID進行輸入,就能定位到出現問題的點,這樣一來,能讓我們非常容易定位開播失敗的原因,而且能把我們的工作量轉移出去。在我們進行傳輸的優化時,要依賴于大數據系統,包括要上新的特性去做A/B測試都要依賴于大數據分析系統。
2、如何做到直播質量每一秒都可追蹤?
接下來,通過一個例子來介紹我們如何做到直播質量每一秒都可以追蹤。有一天我們發現在APP上有個熱門流播放卡頓,我們希望能定位它到底是因為手機性能還是網絡引起的問題。我們分為四步來定位這個問題,第一步是收集主播信息,第二步是捕捉卡頓點,第三步是對推流鏈路系統進行數據分析,第四步是進行問題定位。我們會先把主播當時的采集幀率、推流ID、機型系統等資料進行收集。然后抓到主播的卡頓點后,就要去定位它的時間點,這里用到了就是剛才提到的流里面的SEI信息,通過SEI信息可以換算出卡頓出現的精確時間,這樣有助于在大數據系統里定位問題。如上圖所示,我們定位到問題發生在11點03分的某一秒,通過查看推流埋點數據發現主播端的采集幀率只有6幀,出現一個很明顯的采集幀率下降,但只看這部分是不夠的,還可能是其他系統的問題。
與此同時,我們去查看轉推服務,發現并沒有出現丟包的情況,用戶的網絡還是非常好的。于是,我們就推測是主播手機性能下降引起的問題,通過回看數據發現,在有觀眾送禮的時候,禮物特效展示時出現了明顯的性能采集幀率的下降。最后的定位的總結就是,主播使用iPhon6S加上IOS11.4長時間開播后出現了手機發熱,導致性能下降,從而導致采集幀率下降。我們的解決辦法就是針對iPhone6S比較老的機型,我們會對它的一些美顏特效會進行降級、參數調整,讓它開銷不是那么大。
四、總結及展望
最后這部分就是對我們未來工作的一個思考。首先,我們會推動H.265繼續的向前發展,我們已經支持了H.265的CDN直播、RTMP直播、短視頻制作,目前正在考慮支持H265的互動直播,目前H.265只在IOS上面硬編做得比較好,既能兼顧效率、性能,也能比較好的用起來,這里可能還存在一些適配的工作量。其次,在QUIC方向上,我們的QUIC源站已經上線了,使用QUIC可以優化秒開和卡頓率。目前,在做的就是QUIC下行邊緣節點的建設,因為這就相當于是要去做觀眾端不同點的建設,還要考慮什么樣的觀眾端適合從我們的QUIC節點來拉流。另外,就是我們的新業務拓展,包括一些交友類、K歌類的業務,我們認為技術是服務于業務的,新的業務拓展代表新的技術挑戰。在交友類的APP中,我們考慮音視頻通話之間用WebRTC的P2P方式來進行傳輸,而我們通過在K歌的調研發現可以采用在WebRTC加RMTP的方式來做端上合流、推流,以此來開展一些新的業務,當然這都是我們的一些嘗試。最后,我們認為更好的基礎網絡是新業務推廣的基石,到了5G時代,直播形式會更加豐富,會有更多的更精彩的節目展現給大家。
精品文章推薦
技術干貨:
舞臺現場直播技術實踐
快手QoE指標設計的分析初探
P2P技術如何拯救一家直播網站
使用級聯SFU改善媒體質量和規模
展曉凱:短視頻APP架構設計與實現
從直播答題看背后的移動音視頻開發
VP9如何給Twitch的電競直播帶來價值?
用WebRTC在Firefox上實現YouTube直播
總結
以上是生活随笔為你收集整理的基于WebRTC的互动直播实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音视频技术开发周刊 82期
- 下一篇: LiveVideoStack线上交流分享