iOS短視頻播放緩存之道

一套基於AVPLayer短視頻播放緩存庫ShortMediaCache GitHub地址ios

主要特色:git

  • 1.爲短視頻量身設計,接入方便,不侵佔業務
  • 2.邊播變緩存,緩存後直接播放
  • 3.預加載功能,秒播下一條短視頻
  • 4.自動緩存管理

原文地址github

業務背景

公司電商APP接入短視頻模塊也有半年多的時間了,之間一直在忙着完善業務功能,如今是時候沉澱下來總結這一路來的收穫。緩存

視頻播放對於ios開發來講其實並非一個難事兒,簡單幾行代碼就能實現,確實,最初的短視頻播放也是基於此,給定視頻url直接丟給系統播放器(AVPlayer)就能夠播放了。可是隨着短視頻業務發力,短視頻模塊在APP業務中承擔了更多更重要的角色,如何提高短視頻的播放速度變得尤其重要,隨之便提出了短視頻邊播變緩存,短視頻預加載相關功能要求。網絡

業務分析,公司APP主業務是電商,短視頻做爲爲電商引流業務,提升APP活躍度的業務模塊,同時在APP其餘業務功能中也存在視頻播放,例如商品詳情頁面商品介紹,基於此設計之初並不打算將全部的播放業務耦合在一塊兒,由於短視頻的播放機率遠遠大於其餘長視頻,依次業務需求大體分爲2類邏輯,短視頻和在線播放,對於短視頻統一按照短視頻播放模塊來執行邊播變緩存,而其餘的相對比較長一些的視頻則直接在線播放也不緩存,此處也不作過多介紹。app

邊播邊緩存的實現

短視頻播放特色:
一、全屏播放
二、快速播放,爭取每一個短視頻都能秒播
三、內容高度濃縮,無需進度條與拖拽進度
四、精彩的短視頻可能會被重複觀看幾回
五、其餘(聲音控制、流量)ide

基於以上特色,能夠大體將短視頻播放劃分爲2個層級,第1層爲播放器層,第2層爲緩存層,播放器層是基於緩存層的,主要負責播放過程控制和UI展示,好比暫停,繼續,聲音控制,暫停播放顯示控制以及其餘的UI;播放器層對於每一個APP可能會有不一樣的業務需求,實現的功能也大不相同,故將緩衝層與播放器層剝離,而緩存層則主要負責短視頻內容的下載,預加載,緩存管理,這也是ShortMediaCache的主要功能。url

如何從緩存播放

ShortMediaCache緩存播放邏輯大體的實現結構以下圖:spa

結構圖.png

對於AVPlayer鏈接播放器層與緩存層的數據交互是經過自定義實現AVAssetResourceLoaderDelegate協議實現的,在播放器加載的過程當中,播放器會經過AVPlayerItem向AVURLAsset的resourceLoader獲取須要加載數據信息,好比加載的數據偏移,大小等,最終這些數據請求(AVAssetResourceLoadingRequest)會到達其代理(AVAssetResourceLoaderDelegate)對象,代理對象根據請求數據的位置和大小,去讀取相關文件緩存數據,而後回填給請求,以此來響應播放器的數據緩衝請求,與此同時緩存層經過網絡請求將下載下來的數據寫入文件保存。線程

對於AVAssetResourceLoaderDelegate協議主要須要實現如下方法:

- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest;

播放器的數據加載請求會放到loadingRequest裏面,經過其dataRequest對象的requestedOffset和requestedLength能夠知道本次數據請求的區塊,從緩存文件中按需讀取數據填充後執行finishLoading方法便可完成本次數據請求

- (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest;

請求取消回調

下載

對於下載應該放到子線程中去經過NSURLSession來實現,由於視頻文件可能以前已經緩存了部分,須要從已緩存的位置大小處繼續下載緩存,在每次開啓下載前須要去讀取已緩存文件的大小,並設置請求頭部字段Range即可今後處繼續下載後面未下載的部分。

NSString *range = [NSString stringWithFormat:@"bytes=%ld-", (long)cachedSize];
[downloadRequest setValue:range forHTTPHeaderField:@"Range"];

因爲針對短視頻的播放不存在進度拖拽或seek功能,因此每次下載到的數據能夠直接經過緩存管理的相關方法直接append到緩存文件末尾。
由於短視頻的播放首要任務就是保證當前單個視頻的流暢播放,因此在理論上只會存在一個下載任務來獨享全部的下載帶寬,當在空閒狀態的狀況下才適合去作其餘的短視頻資源的預加載。

緩存管理

緩存主要建立了三個目錄管理,分別爲temp、media和trash目錄,緩存分爲臨時緩存和最終緩存,當短視頻資源未下載完時是放在一個目錄下的(temp目錄)、而當視頻資源緩存完時移動到另一個目錄(media),這樣分別存放便能方便讀取和管理兩種狀態的緩存,全部須要刪除的緩存文件都是先移入trash目錄,隨後再刪除以此來保證較高的刪除效率。全部文件命名使用的是視頻資源的url md5值保證惟一性。

緩存應該具備自動管理功能,以防止其無限膨脹,默認配置下ShortMediaCache容許臨時緩存最多保存1天,最大100Mb,而最終緩存則容許最多保存2天最大200Mb,若是業務須要能夠自定義ShortMediaCacheConfig配置實現。

預加載

要實現下一個視頻或者幾個視頻能快速的播放起來,預加載的下載任務應該和正常的邊下邊播任務區分開,由於首先應該保證正在播放的短視頻能順暢的播放,因此邊下邊播任務優先級應該高於預加載任務,在沒有邊下邊播任務時才能執行預加載任務,而且當有新的邊下邊播任務時應當中止當前的預加載任務,首要執行邊下邊播任務。

ShortMediaCache提供了預加載功能實現,經過調用ShortMediaManager如下方法:

- (void)resetPreloadingWithMediaUrls:(NSArray<NSURL *> *)mediaUrls;

使用者能夠屢次調用此方法,來不斷更新須要預加載的資源隊列

ShortMediaCache使用方式

下載源碼文件,將ShortMediaCache文件夾引入工程, 經過ShortMediaResourceLoader來建立AVPlayer須要播放視頻的AVPlayerItem便可

#import "ShortMediaResourceLoader.h"
ShortMediaResourceLoader _resourceLoader = [ShortMediaResourceLoader new];
AVPlayerItem _playerItem = [_resourceLoader playItemWithUrl:videoUrl]; 
AVPlayer _player = [AVPlayer playerWithPlayerItem:_playerItem];

正常狀況下應該持有_resourceLoader對象

預加載視頻

[[ShortMediaManager shareManager] resetPreloadingWithMediaUrls:preloadUrls];

preloadUrls存放須要預加載的視頻url

持續更新

ShortMediaCache大體類調用邏輯圖以下:

類圖.png

更多功能細節和使用方式請前往ShortMediaCacheGitHub地址,下載源碼運行Demo體驗,後續會持續完善此庫和其Demo,若是喜歡歡迎Star,使用問題請Issue.

參考:
https://mp.weixin.qq.com/s/v1...
http://msching.github.io/blog...

相關文章
相關標籤/搜索