首頁>技術>

出處:https://juejin.cn/post/6927857717105311758

背景介紹

首幀時間,是指使用者從點選開始播放到影片首幀畫面展現出來的時間。「零首幀」並不是真的0毫秒啟播,而是使用者幾乎感知不到有首幀時間的存在,在我們的播放質量埋點中對應小於100ms以內的首幀時間。 在我們的播放器中,在各環節提供了極致的首幀最佳化方法,在條件允許符合時,可以將首幀時間壓縮到100ms以下,使用者感知到的就是完全平滑播放,沒有首屏的頓感。 當然在現實業務中,有些場景是無法使用所有的最佳化條件的,比如在隨機播放的場景不能進行預載入、某些場景不適合使用播放器複用技術等。結合實際業務場景,儘量多的使用我們提供的最佳化能力,就可以使大部分使用者體驗為零首幀情況。

首幀的構成

首幀的概念,首幀對於影片播放體驗的影響

首幀時間,是影片類應用的一個重要核心指標,也是影響使用者觀看體驗的核心因素之一。舉個例子,如果一個影片需要花好幾秒時間才加載出首幀,大部分使用者都等不到首幀加載出來就放棄播放了。因此,最佳化影片播放的首幀時間是極其重要的。

上面這幅圖是一個影片點選播放的整個流程,可以看出首幀時間主要包含這麼幾個部分: 獲取影片播放連結,網路建連,下載影片頭部資料,音影片解碼和渲染。 本文將從影片播放的整個過程出發,介紹首幀最佳化的一些通用方案。同時在本文最後,會以長影片場景播放和帶歷史進度的起播為例,介紹面向場景的首幀最佳化。

通用的首幀最佳化方法獲取播放地址

播放地址隨feed下發

影片播放的第一步就是獲取影片資源的播放連結,通常而言,影片資源會有唯一標識video id, 在點播的服務端會有一個根據video id資訊獲取播放連結的服務,如果app server端能夠呼叫vod服務生成播放地址,然後將播放地址隨feed流一起下發,則省去了客戶端的一次網路請求耗時。

網路建連

DNS預解析,預連線、連線複用,https TLS 1.3 false start, session複用 0RTT

在拿到播放地址之後,播放器會去與cdn建連,首先會進行DNS解析。而為了防止DNS劫持,大部分客戶端會採取HTTPDNS的方式做DNS解析,這又會涉及到一個網路請求的耗時。我們可以採取DNS預解析的策略,比如app啟動時,服務端就可以提前下發app可能用到的域名,客戶端則可以對這幾個域名提前做DNS解析,並做快取。 在HTTP 1.1中支援連線複用,因此我們可以預先建立幾個與CDN的socket連線,然後在播放時直接複用連線即可。 另外,為了應對內容劫持,在部分地區播放開啟了https,而https相比於http多了TLS握手的過程,這個握手過程會給影片首幀多引入2個RTT。透過TLS False Start加上session複用,可以做到0RTT握手。

音影片首包

減少probe、moov位置

在播放器與CDN完成建連後,播放器就開始下載影片檔案, 首先播放器會嘗試探測影片檔案的格式、編碼等資訊。如果影片源經過服務端統一轉碼,那麼就可以省去這個探測的過程。同時,值得一提的是,常見的mp4影片檔案,有一個moov box,這裡面會儲存音影片流track資訊比如解碼資訊、以及音影片幀與檔案對應的關係(用於seek),因此通常播放器都會先下載moov的資料。而moov的位置則會對起播造成一定的影響。舉個例子,如果moov在檔案尾部,當下載了影片前面部分資料,發現moov沒找到,就去尾部查詢moov,這樣就又多了兩次網路請求。對於這個問題,我們可以透過轉碼將moov挪到影片檔案的頭部,從而縮短首幀耗時。

音影片解碼

解碼器非同步初始化、解碼器複用

通常情況下,在播放器讀取到影片資料,拿到影片的解碼資訊後就可以開始建立解碼器解碼了。不過解碼器建立這個過程,尤其是在Android平臺上MediaCodec的建立是一個比較耗時的操作。這裡我主要介紹兩個最佳化: 解碼器非同步初始化和複用。如果app server提前把影片的解碼資訊傳遞給播放器,那麼播放器就可以在建連的同時去非同步初始化解碼器,這樣就可以減小硬解建立耗時的影響。而解碼器複用則可以完全消除這個耗時,順這這個思路,我們可以做播放器執行緒的複用甚至整個播放器的複用,這些方法都可以大幅最佳化首幀耗時。

起播水位

理論上,要做到極致首幀,可以當影片首幀解碼完成就直接播放。但是實踐發現,這樣做會導致影片播放的卡頓增多,尤其是影片起播後1~3s的卡頓增加。經過大量的實驗,我們發現,如果對影片起播做一定限制,比如讓起播之前快取一定的資料,這樣可以大幅減少卡頓,同時對首幀的影響不大,並且可以顯著提升使用者的觀看時長和觀看vv。

預載入

預載入是一種常見的首幀最佳化措施,我們可以提前下載影片資料的一部分以達到快速起播的目的。但是什麼時候去預載入、預載入多少、並行預載入數量等都是實際需要考慮的問題。 首先是預載入時機的問題,對於15s的短影片而言,完全可以等到當前影片載入完成之後再啟動預載入,這樣預載入就不會和當前影片的播放搶佔頻寬。但是如果一個影片時長超過1min,我們就得重新考慮預載入時機的問題了,具體來說,我們需要考慮當前播放影片的可用快取、當前網路的下載速度、當前影片的位元速率以及即將預載入影片的位元速率、並行預載入數量,透過這些資料我們能夠構建一個模型去預測接下來影片播放的卡頓狀況,如果大機率是不會發生卡頓,則可以開啟預載入,反之則不啟用或者暫停預載入。

另外一個問題,預載入多少,直觀認識,至少得保證首幀能加載出來。一個粗略的估算方法是moov大小加上影片的平均位元速率 * 預載入時長,這樣就可以透過服務端下發moov頭大小及影片的平均位元速率,然後在app端上透過實驗去調整預載入時長引數,進而調整預載入大小。

預渲染

原理介紹

預載入只能夠將網路請求的耗時消除掉,但播放器還是需要經歷解複用、解碼、渲染的步驟,在中低端機器有200ms以上的耗時。如果能夠將影片的首幀提前渲染好而不播放,將會縮減掉這部分的耗時。而預渲染則是提前將影片的首幀渲染出來的技術。具體來說,預渲染會提前解碼出影片首幀,並且將首幀渲染出來,但是這個過程中音訊不會播放出來。 舉個例子,在小影片場景上,當滑動影片卡片時,就已經開始啟動預渲染,在卡片滑動過程中,影片的首幀很可能就已經透過預渲染加載出來,這樣當卡片滑到中央時,則直接啟動播放,這時候使用者基本上感受不到影片的載入。

結合使用場景的最佳化

前面提到各種首幀最佳化的手段都是比較通用的策略,而面向場景的最佳化也是極為重要的,在本文接下來的部分會介紹兩種場景下的起播最佳化: 1.長影片場景的播放最佳化 2.帶歷史進度的起播最佳化。

長影片場景最佳化

mp4格式介紹,moov大小與時長關係

短影片通常採用mp4這種影片格式,前面也提到過moov的下載是mp4影片起播的重要條件,而moov的大小則與影片時長正相關,粗略統計moov的大小約為40KB/min。這樣1h的長影片moov頭就有2.4MB,如果平均網速1MB/s,則需要2.4秒的載入時間,這對於弱網使用者而言是極差的體驗。而fmp4這種影片格式則能很好解決這個問題,fmp4將一個完整的影片拆分成若干個小的片段,而每個片段的索引則存在於sidx box中,這樣起播所需要的資料量就大幅下降,從而縮短了首幀耗時。

另外,長影片往往有前貼廣告,我們也可以在前貼廣告播放器期間,結合預渲染提前載入正片首幀。

帶歷史進度的起播

關鍵幀起播

在中長影片中有一個功能是記住歷史進度播放,通常的實現方式是seek到歷史進度前面最近的一個關鍵幀,然後把影片幀塞給解碼器,在解碼器中做丟幀處理,直到pts到了指定的歷史進度。假設這個影片的位元速率是4Mbps,影片的GOP大小為5s,那麼這種場景的起播最壞情況需要額外下載4 * 5=20Mb的資料。如果我們限制只在關鍵幀位置起播,則可以避免這些額外資料的下載,從而顯著縮短首幀的耗時。

總結

本文主要按照首幀的各個階段分別介紹了對應的最佳化方案,也簡單介紹了預載入和預渲染這兩個最佳化首幀的利器,在文章最後針對長影片以及歷史進度起播這兩種場景,介紹了對應的最佳化手段。

出處:https://juejin.cn/post/6927857717105311758

13
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Ansible模組學習之file模組