本篇文章內容來自2016年TOP100summit QQ空間客戶端研發總監王輝的案例分享。
編輯:Cynthia算法
王輝:騰訊SNG社交平臺部研發總監、騰訊QQ空間移動客戶端技術負責人高級工程師。09年起負責QQ空間技術研發,經歷從Web時代到移動客戶端技術的轉變,在Web、移動終端上都有不錯的技術積累。 緩存
導讀:移動互聯網飛速發展,2016年,社交網絡對視頻技術的應用獲得爆發式的增加,短視頻、視頻直播、視頻濾鏡、視頻人臉動效、音樂、K歌、變聲、連麥等功能陸續在產品中上線,如何在快速上線功能的同時,保證穩定流暢的體驗,成爲挑戰。
主要面臨的挑戰以下:
一、複雜的網絡環境下,如何保證視頻播放的成功率,如何保證直播的流暢度,減小卡頓?
二、體驗上,如何保證快速流暢的播放體驗,如何實現直播秒開,即點即播?
三、性能上,直播中濾鏡、美容、人臉動效,效果全開,如何保證主播端的性能?
四、億級海量併發用戶狀況下,如何更好的保障質量,柔性帶寬的策略如何作到極致?
本案例圍繞上述挑戰進行,揭祕騰訊QQ空間團隊在挑戰中的一些優化嘗試。性能優化
1、案例介紹服務器
QQ空間目前是國內最大的SNS社區,日高峯上傳5億張圖片,播放10億個視頻,6.3億用戶在這裏分享生活,留住感動,其中主流人羣正是95後的年輕人。
也正由於是年輕人,且年輕人是生活方式轉變的主要推進力,不知足於如今圖片+視頻傳統的分享方式,他們但願經過直播的方式讓你「如今、馬上、立刻」看到我。這就是內容消費的升級,同時伴隨着手機硬件的升級、流量費用的降低,因而手機直播變爲可能。
而咱們的直播產品定位也是基於目標用戶生活的內容,外加社交的傳播力量,有別於如今主流的網絡+遊戲直播的模式。
帶來的好處是:用戶創造的內容更多元化,更貼近生活,更能在好友間產生共鳴和傳播;
帶來的問題是:咱們要兼容的移動終端也是海量的,性能問題是咱們重點關注的內容。微信
在以上背景下,咱們開始作直播了。目標是一個月內構建直播的閉環能力,也就是快速上線。須要實現發起直播、觀看直播(1人發起,多人觀看)、回看直播(回放)、直播互動(直播間中的評論、送禮等)、直播沉澱(Feeds沉澱、分享直播等)等功能(可參考圖1);且同時支持Android、iOS、Html5三大平臺(即方案成熟),而且支持空間以及手機QQ內的空間。網絡
首先咱們就面臨項目工期緊張、團隊直播技術積累不夠的問題。雖然如此,但咱們仍然硬着頭皮繼續與各大相關技術提供商進行交流,根據咱們的標準以及提供商的建議進行技術選型,咱們的標準以下:
● 專業度好(直播低時延遲,支持全平臺、基礎服務建設好);
● 開放源代碼;
● 支持度高,有問題能夠隨時溝通解決;
● 支持動態擴容。架構
最後根據標準選擇了騰訊雲提供的ILVB直播解決方案,尤爲音視頻相關組在這塊有多年技術積累,而且同部門可合做雙贏。
這其中值得一提的是咱們的閉環研發模式也促使咱們以及合做夥伴不斷提高產品質量。首先快速上線(完成產品需求,並完善監控),再在上線後查看監控數據(分析數據),接着應用到優化工做(跟進數據、專項優化),最後進行灰度驗證(灰度一部分用戶驗證優化效果),根據效果再決定是否正式應用到產品中(如圖2)。併發
最後,咱們如願實現了1個月上線,同時支持QQ空間和手機QQ(結合版QQ空間),到目前爲止已經迭代12+版本。觀看量也從5月份的百萬級到8月份的千萬級、到如今的億級,成爲用戶參與的大衆化全民直播。產品數據也跟隨用戶的需求一直在飆升,隨之而來的是各類各樣的問題反饋,尤爲是性能問題,這也是本文要重點討論的話題。運維
2、直播架構性能
在介紹直播架構前,我想有必要給你們再複習一下H264編碼,目前市面上直播的視頻編碼基本都是H.264。H264有三種幀類型:完整編碼的幀叫I幀、參考以前的I幀生成的只包含差別部分編碼的幀叫P幀、還有一種參考先後的幀編碼的幀叫B幀。H264的壓縮流程爲分組(把幾幀數據分爲一個GOP,一個幀序列)、定義幀類型、預測幀(以I幀作爲基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀)、數據傳輸。
用簡單的例子來解釋視頻模型,若是把一個GOP(Group of pictures)當作一列拉貨的火車,那一段視頻就是N輛火車組成的貨運車隊(圖3)。
直播就是視頻數據的流動,邊拍攝、邊傳輸、邊播放的數據流動過程。數據由主播生產裝車,通過網絡(鐵路),再到觀衆端卸貨並進行播放消費。
火車須要調度,視頻流也同樣,這就是視頻流協議,即經過協議控制視頻有序的傳輸給觀衆。
常見協議如圖4:
咱們採用的是騰訊雲基於UDP開發的QAVSDK協議。
前面講了協議相關的內容,下面講講咱們的直播模型,如圖5:
視頻房間(視頻流)以及業務房間(相關業務邏輯互動)大體結構差很少,差異在於數據流動(注意圖5中箭頭)。
視頻房間數據由主播經過視頻流協議流向視頻服務器,而視頻服務器也經過視頻流協議把數據下發給觀衆,觀衆端解碼並播放。主播只上傳,觀衆只下載。而業務房間任何人都須要給服務器發送相關的業務請求(如評論,固然客戶端會屏蔽一些特殊邏輯,如主播不可送禮給本身)。更詳細的結構如圖6:
注:iOS手Q觀衆採用RTMP協議不是由於不支持QAVSDK,而是由於手Q有減包壓力,而QAVSDK相關的SDK佔用空間較大。
3、技術優化
接下來進入本文的重頭戲:技術優化。技術優化分爲四個方面:秒開優化(耗時類優化實踐)、性能優化(性能優化實踐)、卡頓優化(問題分析類實踐)、回放優化(成本類優化實踐)。
在優化以前,咱們的必要工做是監控統計先行,咱們會對咱們關心的數據點進行前期的統計,並作相關報表和告警,以輔助優化分析。
監控分爲如下五部分:
● 成功率,發起直播成功率、觀看直播成功率、錯誤佔比列表;
● 耗時,發起直播耗時、進入直播耗時;
● 直播質量,卡幀率、0幀率;
● 問題定位,各步驟流水、直播2s流水、客戶端日誌;
● 實時告警,短信、微信等方式。
經過這些,咱們實現了數據的查看、分析定位、以及實時的告警,從而更方便地解決問題。
4、秒開優化
幾乎全部人都在吐槽「爲何直播打開很慢,競品比咱們快多了!!!」,咱們本身也以爲不能忍。咱們要讓觀看直播達到秒開(從點擊直播到看到畫面,耗時在1秒之內),而統計到的外網平均打開耗時爲4.27秒,離秒開還有必定的差距。
因而咱們梳理從點開到渲染第一幀畫面這一段時間的時序關係,同時統計各階段的耗時。流程圖和耗時大體如圖7 :
經過流程分析和數據分析發現兩個耗時緣由是:獲取首幀數據耗時太長、核心邏輯串行。接下來咱們針對這兩個問題進行優化。
首幀耗時太長。核心問題在於加速首個GOP到達觀衆的時間。
咱們的優化方案是:讓接口機緩存首幀數據,同時對播放器進行改造,解析到I幀就開始播放。這樣大大加快了觀衆看到首幀的時間。
核心邏輯串行。這部分咱們主要經過如下流程:
● 預加載,提早準備環境和數據,如在feeds中提早預拉起直播進程,提早獲取接口機IP數據;
● 延遲加載,對UI、評論等其餘邏輯進行延遲加載,讓出系統資源給首幀;
● 緩存,如緩存接口機IP數據,一段時間內複用;
● 串行變並行,同時拉取數據,節省時間;
● 對單步驟耗時邏輯進行優化和梳理,減小單步耗時。
優化後的流程和耗時大體如圖8所示,耗時下降到680ms,目標達成!
5、性能優化
產品不斷迭代,直播的玩法也愈來愈豐富了,同時一些性能問題也不斷暴露出來。尤爲咱們後來增長了動效貼紙、濾鏡、變聲等功能,大量用戶反饋直播很卡。
經過統計發現:主播短幀率很低,畫面不連續,主觀感受卡;另外,用戶使用設備中也有大量的低端機。如圖9所示。
經過分析發現幀率低的主要緣由是單幀圖像處理耗時過長致使,而編碼所佔因素較低。通常總耗時=處理工做量*單幀耗時。因而咱們逐漸對這兩方面進行優化。
減小圖像處理工做量
● 採集分辨率與處理分辨率一致,好比編碼爲960×540,因爲有些手機可能不支持這個採集分辨率,採集通常都是1280*1024,以前處理是先處理再縮放,如今先縮放再處理,減小圖像在濾鏡、動效貼紙中的處理耗時。如圖10
● 處理幀前丟幀。雖然咱們對系統相機設置了採集幀率,可是不少機型並不生效,因而咱們經過策略對額外的幀進行丟棄,減小圖像處理的幀數。好比咱們設置採集幀率爲15,但實際有25,這多餘的10幀處理了在編碼的時候也會浪費,以前就丟棄,可減小資源消耗。
● 機型分檔位,不一樣的機型根據不一樣的硬件能力採用不用的採集幀率和編碼幀率,保證流暢;同時在過熱的時候以及迴歸正常時動態調整幀率去調整資源消耗。
● 人臉識別採集優化,每幀識別改成兩幀識別一次人臉,既不會產生人臉漂移也能夠減小處理耗時。
減小單幀耗時
● 採集流程改造,減小了大約33%的沒必要要耗時,如圖11.
● 動效貼紙多GL線程渲染,貼紙渲染放在另一個OffScreenThread進行渲染,徹底不佔用整個美化處理過程的時間,效果如圖12:
● 動效貼紙採用OpenGL混合模式;
● 圖像處理算法優化,如ShareBuffer優化(實如今GPU與內存之間快速拷貝數據,排除CPU介入,節省紋理轉RGBA時間;耗時幾乎下降一半,FPS也至少提高2-3幀左右),濾鏡LUT優化,如圖13.
除了以上兩個大的優化點,咱們還推進更多的機器採用硬件編碼。首先編碼穩定,幀率不會波動;其次,佔用CPU會有必定下降。
以上是咱們大體的一些優化點,優化以後,用戶直播投訴大量減小。
6、卡頓優化
咱們先看一些相關的定義:
卡頓用戶定義:(卡頓時長/總時長)>5%定義爲卡頓用戶,卡頓率=卡頓用戶/總用戶。
主播卡頓點定義:上行大畫面編碼後幀率<5的點數。
觀衆卡頓點定義:解碼後幀率<5的點數。
咱們的目標就是讓卡頓率達到50%如下。
固然上行發生卡頓時,會形成全部用戶卡頓,而下行卡頓時,只有單個觀衆纔會卡頓。
咱們看看會形成卡頓的緣由,見圖14 :
大概有主播端、網絡、觀衆端三個大的模塊可能會致使卡頓問題,而主播端的性能優化基本解決了,那就看下網絡以及觀衆端的。
從統計數據發現網絡質量影響佔比達到50%左右,這明顯要優化。因而網絡上行優化咱們作了圖15的事情,減小單幀中的數據以及減小幀數,用火車的例子就是減小貨物以及控制火車數量。
而用戶端下行優化則是囤積貨物,丟掉貨物,如圖16 。
如圖17,咱們來看優化後的效果,與競品相比優點十分明顯:
同時,主播卡頓率也降低到30%,觀衆卡頓率降低到40%,目標算是達成了。
7、回放優化
如圖18,咱們先來看看直播回看(回放)的大體流程:
回放一樣也存在一些問題,主要體如今兩個方面:
● 回放直播質量:服務器器端保存,回看視頻質量受主播短網絡影響較大
● 服務器成本:服務器除了須要推一個私有協議流,另外還須要對私有流進行轉碼成HLS和MP4以便回放使用
在方案選擇上,MP4具備播放方案成熟、速度快、用戶體驗佳等優勢;而HLS系統支持差、用戶等待時間也長。那是否意味着咱們要直接選擇MP4方案呢?
其實回看採用HLS以及MP4都是能夠的,可是直播觀看時因爲數據是在變化的,HTML5只能使用HLS,若是咱們回看的時候使用MP4,那就等於服務器須要對私有協議流分別轉碼成MP4和HLS,那這明顯不經濟。這就導致咱們選擇HLS,服務器只須要轉碼一次流爲HLS便可。
既然選擇HLS,咱們就要針對性地解決HLS存在的問題。
在Android平臺上,Android 3.0開始支持HLS,後來由於Google官方想推DASH取代HLS,對HLS的支持便慢慢減弱了,在官方文檔上甚至找不到一點兒關於HLS的說明。經實踐發現Android原生播放器對HLS的支持程度僅僅是能播,徹底沒有任何優化。這樣不只會有多餘的m3u8文件請求,並且啓動播放後整個流程是串行的,很是影響視頻畫面的首幀可見耗時(平均耗時4.5s左右)。
咱們能夠經過本地代理提早下載來解決這個問題,接入下載代理後,在代理層能夠對m3u8文件的內容進行掃描,並觸發對ts分片的並行下載,把ts數據緩存起來。通過這樣的處理後,雖然播放器的層面仍是串行下載,因爲咱們已經提早準備好了數據,數據會很快返回給播放器,這樣就實現了咱們下降首幀耗時的效果,經實驗接入後平均首幀可見耗時下降到了2s左右。
優化先後流程圖見圖19:
緩存策略上,HLS的緩存業界目前尚未成熟方案。咱們實現了對圖20中三種模式的自動偵測與支持,使用方徹底不須要關心底層的緩存與下載邏輯。
最後,服務器成本方面節省了50%的轉碼計算和存儲成本;另外,回放的加載速度也變快了。
8、案例總結
經過以前的案例和相關優化分析,總結出三種大體的問題模式,以及相應的優化思路。
● 速度類:理清時序,統計各階段耗時,各個擊破;
● 性能類:經過Trace,明確性能損耗點,各個擊破;
問題解決類:創建模型,初步分析,統計上報,確認問題,各個擊破。
總結成一個套路就是圖21 :
在案例中也體現瞭如下一些參考點:
● 快速迭代,小步快跑
● 監控驅動優化
● 創建模型,抽象問題直觀分析
● 產品定位決定優化的方向
● 海量服務,以小省大
最後,以一張空間直播的拓補圖做爲結束本文(圖22)。
TOP100全球軟件案例研究峯會已舉辦六屆,甄選全球軟件研發優秀案例,每一年參會者達2000人次。包含產品、團隊、架構、運維、大數據、人工智能等多個技術專場,現場學習谷歌、微軟、騰訊、阿里、百度等一線互聯網企業的最新研發實踐。大會開幕式單天體驗票申請入口