前言
KTVHTTPCache
是唱吧開源的一套音視頻緩存框架冈欢。因目前所做的項目有視頻播放的需求,因此在某個版本的迭代中,接入了KTVHTTPCache
潮饱,體驗不錯。
對于視頻播放緩存的方案诫给,常用的有Local HTTP Server
和AVAssetResourceLoader
兩種香拉。本質(zhì)上都是截獲請求加載的url
,再加入具體的視頻緩存邏輯中狂。有一個區(qū)別點在于AVAssetResourceLoader
只能配合AVPlayer
使用凫碌。
KTVHTTPCache的結(jié)構(gòu)設(shè)計
KTVHTTPCache
由 HTTP Server
和 Data Storage
兩大模塊組成。前者負(fù)責(zé)與Client
交互吃型,后者負(fù)責(zé)資源加載及緩存處理证鸥。
HTTP Server
和 Data Storage
是 KTVHTTPCache
兩大重要組成部分, HTTP Server
主要負(fù)責(zé)與用戶交互勤晚,也就是最頂層枉层,最直接與用戶交互(比如下載數(shù)據(jù)),而 Data Storage
則在后面為 HTTP Server
提供數(shù)據(jù)赐写,數(shù)據(jù)主要從 DataSourcer
中獲取鸟蜡,如果本地有數(shù)據(jù),它會從 KTVHCDataFileSource
中獲取挺邀,反之會從 KTVHCDataNetworkSource
中讀取數(shù)據(jù)揉忘,這里會走下載邏輯(KTVHCDownload)
跳座。
工作流程如下:
1.Client
發(fā)出的請求被 HTTP Srever
接收到,HTTP Server
通過分析 HTTP Request
創(chuàng)建用于訪問 Data Storage
的 Data Request
對象泣矛。
2.HTTP Server
使用 Data Request
創(chuàng)建 Data Reader
疲眷,并以此作為從Data Storage
獲取數(shù)據(jù)的通道。
3.Data Reader
分析 Data Request
中的 Range
創(chuàng)建對應(yīng)的網(wǎng)絡(luò)數(shù)據(jù)源 Data Network Source
和文件數(shù)據(jù)源 Data File Source
您朽,并通過 Data Sourcer
進(jìn)行管理狂丝。
4.Data Sourcer
開始加載數(shù)據(jù)。
5.Data Reader
從 Data Sourcer
讀取數(shù)據(jù)并通過 HTTP Server
回傳給 Client
哗总。
HttpServer
這層設(shè)計比較簡單几颜,主要是用了 CocoaHTTPServer 來作為本地的 HttpServer
。HttpServer
說白了就是一個手機(jī)端的服務(wù)器讯屈,用來與用戶(作者說的 client
)交互蛋哭,用戶提出數(shù)據(jù)加載需求后,它會從不同的地方來獲取數(shù)據(jù)源涮母,如果本地沒有會從網(wǎng)絡(luò)中下載數(shù)據(jù)谆趾。它主要的作用是 hook
播放器的網(wǎng)絡(luò)請求,進(jìn)行數(shù)據(jù)的加載哈蝇。它主要的類如圖:
- KTVHCHTTPServer:是一個單例棺妓,用來管理 HttpServer 服務(wù),負(fù)責(zé)開啟或關(guān)閉服務(wù)炮赦;
- KTVHCHTTPConnection:它繼承于 HTTPConnection怜跑,表示一個連接,它主要為 HttpServer 提供 Response吠勘。
- KTVHCHTTPRequest:一個請求性芬,也就是一個數(shù)據(jù)模型;
- KTVHCHTTPResponse:一個 Response剧防;
- KTVHCHTTPResponsePing:主要用來 ping 時的 Response植锉;
- KTVHCHTTPURL:主要用來處理 URL,比如把原 Url 生成 proxy url峭拘;
DataStroage
主要用來緩存數(shù)據(jù)俊庇,加載數(shù)據(jù),也就是提供數(shù)據(jù)給 HttpServer
鸡挠。上面代碼中關(guān)鍵的一句代碼 [KTVHCHTTPResponse responseWithConnection:self dataRequest:dataRequest]
辉饱,它會在這個方法的內(nèi)部使用KTVHCDataStorage
生成一個 KTVHCDataReader
,負(fù)責(zé)讀取數(shù)據(jù)拣展。生成 KTVHCDataReader
后通過 [self.reader prepare]
來準(zhǔn)備數(shù)據(jù)源 KTVHCDataSourcer
彭沼,這里主要有兩個數(shù)據(jù)源,KTVHCDataFileSource
和 KTVHCDataNetworkSource
备埃,它實現(xiàn)了協(xié)議 KTVHCDataSourceProtocol
姓惑。KTVHCDataNetworkSource
會通過 KTVHCDownload
下載數(shù)據(jù)褐奴。
-
KTVHCDataStorage
: 是一個單例,它負(fù)責(zé)管理整個緩存于毙,比如讀取敦冬、保存和合并緩存; -
KTVHCDataReader
:主要用來讀取數(shù)據(jù)望众; -
KTVHCDataRequest
:用來請求數(shù)據(jù)匪补,表示一個請求; -
KTVHCDataResponse
:一個數(shù)據(jù)響應(yīng)烂翰; -
KTVHCDataReader
:讀取數(shù)據(jù); -
KTVHCDataCacheItem
:緩存數(shù)據(jù)模型蚤氏,表一個緩存項甘耿; -
KTVHCDataCacheItemZone
:緩存區(qū),一個緩存項中會有多個緩存區(qū)竿滨,比如0-99佳恬,100-299 等; -
KTVHCDataSourcer
:數(shù)據(jù)源中心于游,負(fù)責(zé)處理不同數(shù)據(jù)源毁葱,它包含有一個數(shù)據(jù)隊列KTVHCDataSourceQueue
; -
KTVHCDataSourceQueue
:數(shù)據(jù)隊列贰剥; -
KTVHCDataSourceProtocol
:一個協(xié)議倾剿,作為數(shù)據(jù)源時需要實現(xiàn)這個協(xié)議; -
KTVHCDataFileSource
:本地數(shù)據(jù)源蚌成,實現(xiàn)了KTVHCDataSourceProtocol
協(xié)議前痘; -
KTVHCDataNetworkSource
:網(wǎng)絡(luò)數(shù)據(jù)源,實現(xiàn)了KTVHCDataSourceProtocol
協(xié)議担忧; -
KTVHCDataUnit
:數(shù)據(jù)單元芹缔,相當(dāng)于一個緩存目錄,比如一個視頻的緩存瓶盛; -
KTVHCDataUnitItem
:數(shù)據(jù)單元項最欠,緩存目錄下不同片段的緩存; -
KTVHCDataUnitPool
:數(shù)據(jù)單元池惩猫,它是一個單例芝硬,含有一個KTVHCDataUnitQueue
; -
KTVHCDataUnitQueue
:數(shù)據(jù)單元隊列帆锋,保存了多個KTVHCDataUnit
吵取,它會以archive
的方式緩存到本地;
接入緩存
- (void)initCache {
NSError *error = nil;
[KTVHTTPCache proxyStart:&error];
if (error) {
NSLog(@"Proxy Start Failure, %@", error);
}
// 設(shè)置緩存最大容量
long long maxLength = 300 * 1024 * 1024;
[KTVHTTPCache cacheSetMaxCacheLength:maxLength];
}
- (void)useCacheUrl {
NSString *proxyURLString = [KTVHTTPCache proxyURLStringWithOriginalURLString:URLString];
[AVPlayer playerWithURL:[NSURL URLWithString: proxyURLString]];
KTVHTTPCache
的接入特別簡單锯厢,幾乎零成本皮官,可以配置最大緩存容量脯倒。需要注意的是,播放使用的url
是從KTVHTTPCache
取出來的url
捺氢。
實現(xiàn)預(yù)加載
當(dāng)播放視屏列表時藻丢,最好在播放當(dāng)前視頻時,能夠預(yù)加載下幾個即將要播放的視頻摄乒。
可以使用NSOperationQueue
操作隊列在實現(xiàn)在后臺提前預(yù)加載待播放的視頻悠反。在當(dāng)前視頻的鏈接配置完畢時,可以根據(jù)業(yè)務(wù)實際需要馍佑,將下一個或下幾個視頻url用NSOperation
加到NSOperationQueue
中斋否,在后臺進(jìn)行預(yù)加載,這樣當(dāng)用戶滑動視頻拭荤,下一個視頻就已經(jīng)是提前預(yù)加載好的了茵臭。當(dāng)然,這里只是簡單提供思路舅世,項目中使用NSOperationQueue
也是很方便就能實現(xiàn)的旦委,可以控制最大并發(fā)數(shù)量,是預(yù)加載當(dāng)前index
前面的視頻還是后面的視頻雏亚,弱網(wǎng)是否執(zhí)行預(yù)加載缨硝,具體的預(yù)加載邏輯還是要結(jié)合業(yè)務(wù)來操作。