所有在線內(nèi)容播放,都面臨一些共同的問題:?jiǎn)⒉ヂ瑂eek慢,碼率切換慢。而隨著互聯(lián)網(wǎng)的發(fā)展,用戶對(duì)這些方面的要求越來越高,對(duì)慢的容忍度越來越差,如何解決這些問題,就成了MXPlayer 在線業(yè)務(wù)初期優(yōu)化的重點(diǎn)。
本次分享將分為四個(gè)部分:第一部分介紹MXPlayer 如何解決起播慢,seek慢;第二部分介紹如何解決碼率切換慢的問題;第三部分介紹緩存面臨的問題,以及緩存是如何為前兩部分服務(wù)的;最后一個(gè)部分介紹在復(fù)雜業(yè)務(wù)下,多播放器實(shí)例是如何管理的,通過以上幾個(gè)部分為大家介紹MXPlayer 對(duì)在線內(nèi)容播放優(yōu)化的經(jīng)驗(yàn)。
大家好,我是趙琳琳,來自MX Player。我的分享主題是:MX Player在線播放優(yōu)化。
首先簡(jiǎn)單介紹一下業(yè)務(wù)背景:MX Player起初是一款比較純粹的本地播放器,其體積小,但功能強(qiáng)大,在全球各個(gè)地區(qū)都有不少的活躍用戶。隨著時(shí)間推移,公司在產(chǎn)品策略上也進(jìn)行升級(jí),引入了在線化的內(nèi)容如影視劇、短視頻、直播等。
雖然全球都有MX Player的用戶,但其中主要用戶來自于印度地區(qū)。印度地區(qū)的用戶比較有特色,第一是語言(有十幾種主流語言);第二是網(wǎng)絡(luò)(4G網(wǎng)絡(luò)占多數(shù),家庭有線寬帶較少);第三是設(shè)備(偏低端機(jī)型,存儲(chǔ)空間?。?。
隨著在線內(nèi)容的引入,也出現(xiàn)了一些問題。例如啟播慢、seek慢、碼率切換慢、緩存命中率低、代碼復(fù)雜度高等。
今天的分享內(nèi)容主要圍繞以上的問題展開,首先介紹秒開、快速seek是如何實(shí)現(xiàn)的;之后是平滑碼率切換的技術(shù)細(xì)節(jié);然后是緩存面臨的挑戰(zhàn);最后是多播放器事例是如何管理的。
-01-
秒開
第一部分,秒開。如何讓用戶盡可能快地看到視頻內(nèi)容,是所有在線播放面臨的難題。有數(shù)據(jù)表明,等待時(shí)間越長(zhǎng),用戶流失越嚴(yán)重。
根據(jù)統(tǒng)計(jì),熱度視頻平均啟播時(shí)長(zhǎng)在2.5秒左右。
經(jīng)過進(jìn)一步的分析,發(fā)現(xiàn)其中絕大多數(shù)時(shí)間用于下載數(shù)據(jù)。
那么如何減少用戶的等待時(shí)間呢?我們分析了幾個(gè)優(yōu)化方向,首先解碼占用時(shí)間是較少的,優(yōu)化空間有限;啟播緩沖區(qū)大概需要2秒等待時(shí)間,我們認(rèn)為這個(gè)時(shí)間已經(jīng)很短了,所以不選擇減小以優(yōu)化;最終我們經(jīng)過分析對(duì)比選擇了預(yù)加載方案。
預(yù)加載的流程是:首先服務(wù)端根據(jù)一些策略判定哪些視頻需要預(yù)加載,并且把信息告訴客戶端??蛻舳耸盏秸?qǐng)求后,會(huì)啟動(dòng)預(yù)加載程序。預(yù)加載程序會(huì)在視頻沒有播放的情況下啟動(dòng)預(yù)加載,把需要加載的視頻頭2秒放到緩存內(nèi)。
策略上線后,熱度視頻的平均啟播時(shí)長(zhǎng)由2.5秒降到1.8秒。如果預(yù)加載的緩存命中,啟播時(shí)長(zhǎng)可以達(dá)到0.5秒,收益非??捎^。
那么如何決策哪些視頻需要預(yù)加載?服務(wù)端會(huì)根據(jù)視頻的標(biāo)簽(新劇/推廣/熱度)等進(jìn)行打分,最終做出決策并告知客戶端,啟動(dòng)預(yù)加載程序。
-02-
快速seek
接下來介紹快速seek。和啟播一樣,等待時(shí)間越長(zhǎng),用戶流失越嚴(yán)重。
我們先看一下優(yōu)化之前的seek過程。假設(shè)用戶要seek到A點(diǎn),播放器首先會(huì)進(jìn)入暫停狀態(tài),并緩沖接下來6秒的數(shù)據(jù),完成之后開始播放。
經(jīng)過分析,發(fā)現(xiàn)用戶seek平均等待時(shí)間是3.4秒
那如何減少seek時(shí)間呢?
前文有提到預(yù)加載方案,是否適用于seek呢?答案是No,因?yàn)椴⒉恢烙脩粢猻eek到什么位置,除非緩存整個(gè)視頻,顯然這是不合適的。
另外一個(gè)方案是減小緩沖區(qū),例如從6秒調(diào)整到4秒或更短。但這種方法比較簡(jiǎn)單粗暴,無法預(yù)知其是否有負(fù)面的用戶體驗(yàn)影響,所以這個(gè)方案也被否定。
那么如何解決呢?經(jīng)過分析和觀察,我們發(fā)現(xiàn)當(dāng)播放器當(dāng)前的下載速度大于播放速度,不論緩沖區(qū)有多少數(shù)據(jù),播放都是流暢的。
根據(jù)以上結(jié)論,我們得出一個(gè)快速seek方案:用戶seek到A點(diǎn),播放器暫停并緩沖1秒,得出當(dāng)前下載速度D和常量播放速度P,如果D》=P,則直接開始播放;如果D《P,就會(huì)執(zhí)行緩沖6秒數(shù)據(jù)再開始播放。
策略上線后,數(shù)據(jù)統(tǒng)計(jì)分析顯示平均等待時(shí)長(zhǎng)由原先的3.4秒降為2.5秒。
-03-
平滑碼率切換
接下來講平滑碼率切換,首先看一下優(yōu)化前的流程。
箭頭所指為當(dāng)前播放器進(jìn)度,藍(lán)色為已緩沖內(nèi)容。如果開始切換,播放器會(huì)暫停,并丟棄當(dāng)前的緩沖區(qū),接著緩沖對(duì)應(yīng)碼率的6秒數(shù)據(jù),再開始播放。
經(jīng)過數(shù)據(jù)統(tǒng)計(jì),碼率切換平均等待時(shí)間為2.8秒。
如何減小切換等待時(shí)間呢?同樣的,減小緩沖區(qū)的方案比較簡(jiǎn)單粗暴,直接pass。
可以注意到,圖中紅色的丟棄緩沖區(qū),原本是可以正常播放的,只是因?yàn)橛脩粜枰袚Q碼率,所以丟棄。那么是否可以重用該緩沖區(qū)呢?答案是肯定的。
如圖是優(yōu)化后的平滑碼率切換方案:當(dāng)播放器進(jìn)行碼率切換時(shí),并不會(huì)進(jìn)入暫停,而是繼續(xù)播放當(dāng)前碼率上已經(jīng)緩沖好的數(shù)據(jù),并開辟一個(gè)新的緩沖區(qū)來緩沖對(duì)應(yīng)碼流的6秒數(shù)據(jù),同時(shí)當(dāng)舊緩沖區(qū)數(shù)據(jù)播放完,進(jìn)行緩沖區(qū)切換。
業(yè)務(wù)上線后經(jīng)數(shù)據(jù)統(tǒng)計(jì),優(yōu)化后的碼率切換平均等待時(shí)間由原來的2.8秒降為0.4秒。
-04-
緩存面臨的挑戰(zhàn)
接下來介紹緩存面臨的挑戰(zhàn)以及對(duì)應(yīng)的解決方法。
前述提到MX Player在線用戶主要分布在印度,他們的設(shè)備偏低端,內(nèi)存空間普遍都非常小。在業(yè)務(wù)上線之初,我們給緩存空間定了一個(gè)上限為2G。上線后,后臺(tái)收到了大量的用戶反饋,說App占用空間過大。經(jīng)過我們的討論和決策,把緩存下調(diào)到500M,這帶來了一個(gè)直接的問題:命中率降低。
如圖是優(yōu)化前的緩存布局,在容量不變的情況下,分片越小,個(gè)數(shù)越多,命中率就會(huì)越高。
基于上述結(jié)論,我們得出一個(gè)方案:兩段緩存。
我們把一個(gè)完整的分片拆為頭尾兩部分,頭部?jī)?yōu)先級(jí)高,尾部?jī)?yōu)先級(jí)低,并放入緩存空間。當(dāng)空間滿了之后,會(huì)先清理掉所有尾部數(shù)據(jù)。
這是優(yōu)化后的緩存布局。左圖為裝滿6個(gè)分為頭尾的分片數(shù)據(jù),當(dāng)用戶繼續(xù)使用一段時(shí)間后,緩存空間布局就會(huì)變成右圖的樣子,只留下了各個(gè)分片的頭部數(shù)據(jù)。
這時(shí)如果播放器需要播放內(nèi)容,到緩沖區(qū)查找數(shù)據(jù),就會(huì)發(fā)現(xiàn)右圖的命中率一定是比左圖布局要高的。
這時(shí)回顧一下預(yù)加載和快速seek:預(yù)加載方案是緩存視頻頭2秒,和兩段緩存中的頭部分片數(shù)據(jù)是吻合的。在快速seek中,如果在1秒緩沖內(nèi)可以命中緩存的頭部數(shù)據(jù),并且下載速度大于播放速度,就可以直接啟播。
兩段緩存方案在后臺(tái)默默地為其他功能進(jìn)行支持,這些方案是相輔相成的關(guān)系。
-05-
多播放器如何管理
接下來介紹多播放器如何管理。
隨著業(yè)務(wù)發(fā)展,播放場(chǎng)景也越來越多。這些播放場(chǎng)景之間并不是彼此孤立的,如PIP播放和音樂播放就是互斥關(guān)系。當(dāng)PIP正在播放,用戶需要切換音樂播放,就需要暫停PIP,反之亦然。
另外,feed流播放需要和PIP播放以及音樂播放共存。因?yàn)閒eed流播放是無聲和自動(dòng)播放,我們并不希望這種播放打擾用戶行為。
隨著在線業(yè)務(wù)高速發(fā)展,隨之而來的是一系列問題。
經(jīng)過討論決定,我們選擇重構(gòu)部分代碼以解決問題,同時(shí)定下幾條重構(gòu)原則:
第一,業(yè)務(wù)代碼彼此獨(dú)立:業(yè)務(wù)之間無需互相知道;增加新業(yè)務(wù)無需修改其他業(yè)務(wù);啟動(dòng)播放無需判斷是否有其他播放。
第二,環(huán)境變化自我感知:當(dāng)App失去聲音焦點(diǎn),自動(dòng)暫停;程序進(jìn)入后臺(tái),播放器按需暫停;進(jìn)入音樂播放后,自動(dòng)暫停PIP。
基于以上原則,我們重構(gòu)了代碼,結(jié)構(gòu)如圖所示。Player代表底層播放器,并抽象出來PlayerContext的概念。每一個(gè)Player必須和Context進(jìn)行attach,才能播放。Context有一個(gè)屬性為ready,只有在ready情況下,才能夠讓播放器啟動(dòng),否則會(huì)暫停。
Context有幾個(gè)具體的實(shí)例,首先是Activity,它是一個(gè)安卓標(biāo)準(zhǔn)組件,只有在unReceived的時(shí)候才是ready狀態(tài);Fragment和Activity類似,只有unReceived才是ready狀態(tài);Screen在鎖屏?xí)r為非ready狀態(tài),其他時(shí)候都為ready;Global永遠(yuǎn)都是ready狀態(tài)。
Activity和Fragment主要用于詳情頁播放和feed流播放;Screen用于PIP播放;Global用于后臺(tái)播放。
Player和PlayerContext之間不直接交互,而是通過PlayerManager進(jìn)行管理。它會(huì)監(jiān)聽和維護(hù)所有PlayerContext的狀態(tài),并根據(jù)其狀態(tài)改變來控制播放器的生命周期變化。同時(shí),Manager會(huì)維護(hù)Player和Context之間的映射關(guān)系。
經(jīng)過這樣的結(jié)構(gòu)重構(gòu),我們的業(yè)務(wù)代碼基本實(shí)現(xiàn)了解耦,新增業(yè)務(wù)不需要改動(dòng)已有業(yè)務(wù),并且樣本代碼不需要出現(xiàn)在具體業(yè)務(wù)中,PlayerManager可以感知并通知Player進(jìn)行操作。 以上就是我的全部分享,謝謝大家!
-
播放器
+關(guān)注
關(guān)注
5文章
392瀏覽量
37325 -
視頻
+關(guān)注
關(guān)注
6文章
1925瀏覽量
72719 -
互聯(lián)網(wǎng)
+關(guān)注
關(guān)注
54文章
11038瀏覽量
102445
原文標(biāo)題:MX Player在線播放優(yōu)化
文章出處:【微信號(hào):livevideostack,微信公眾號(hào):LiveVideoStack】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論