前言
KTVHTTPCache
是唱吧开源的一套音视频缓存框架。因目前所做的项目有视频播放的需求,因此在某个版本的迭代中,接入了KTVHTTPCache
,体验不错。
对于视频播放缓存的方案,常用的有Local HTTP Server
和AVAssetResourceLoader
两种。本质上都是截获请求加载的url
,再加入具体的视频缓存逻辑。有一个区别点在于AVAssetResourceLoader
只能配合AVPlayer
使用。
KTVHTTPCache的结构设计
KTVHTTPCache
由 HTTP Server
和 Data Storage
两大模块组成。前者负责与Client
交互,后者负责资源加载及缓存处理。
HTTP Server
和 Data Storage
是 KTVHTTPCache
两大重要组成部分, HTTP Server
主要负责与用户交互,也就是最顶层,最直接与用户交互(比如下载数据),而 Data Storage
则在后面为 HTTP Server
提供数据,数据主要从 DataSourcer
中获取,如果本地有数据,它会从 KTVHCDataFileSource
中获取,反之会从 KTVHCDataNetworkSource
中读取数据,这里会走下载逻辑(KTVHCDownload)
。
工作流程如下:
1.Client
发出的请求被 HTTP Srever
接收到,HTTP Server
通过分析 HTTP Request
创建用于访问 Data Storage
的 Data Request
对象。
2.HTTP Server
使用 Data Request
创建 Data Reader
,并以此作为从Data Storage
获取数据的通道。
3.Data Reader
分析 Data Request
中的 Range
创建对应的网络数据源 Data Network Source
和文件数据源 Data File Source
,并通过 Data Sourcer
进行管理。
4.Data Sourcer
开始加载数据。
5.Data Reader
从 Data Sourcer
读取数据并通过 HTTP Server
回传给 Client
。
HttpServer
这层设计比较简单,主要是用了 CocoaHTTPServer 来作为本地的 HttpServer
。HttpServer
说白了就是一个手机端的服务器,用来与用户(作者说的 client
)交互,用户提出数据加载需求后,它会从不同的地方来获取数据源,如果本地没有会从网络中下载数据。它主要的作用是 hook
播放器的网络请求,进行数据的加载。它主要的类如图:
- KTVHCHTTPServer:是一个单例,用来管理 HttpServer 服务,负责开启或关闭服务;
- KTVHCHTTPConnection:它继承于 HTTPConnection,表示一个连接,它主要为 HttpServer 提供 Response。
- KTVHCHTTPRequest:一个请求,也就是一个数据模型;
- KTVHCHTTPResponse:一个 Response;
- KTVHCHTTPResponsePing:主要用来 ping 时的 Response;
- KTVHCHTTPURL:主要用来处理 URL,比如把原 Url 生成 proxy url;
DataStroage
主要用来缓存数据,加载数据,也就是提供数据给 HttpServer
。上面代码中关键的一句代码 [KTVHCHTTPResponse responseWithConnection:self dataRequest:dataRequest]
,它会在这个方法的内部使用KTVHCDataStorage
生成一个 KTVHCDataReader
,负责读取数据。生成 KTVHCDataReader
后通过 [self.reader prepare]
来准备数据源 KTVHCDataSourcer
,这里主要有两个数据源,KTVHCDataFileSource
和 KTVHCDataNetworkSource
,它实现了协议 KTVHCDataSourceProtocol
。KTVHCDataNetworkSource
会通过 KTVHCDownload
下载数据。
-
KTVHCDataStorage
: 是一个单例,它负责管理整个缓存,比如读取、保存和合并缓存; -
KTVHCDataReader
:主要用来读取数据; -
KTVHCDataRequest
:用来请求数据,表示一个请求; -
KTVHCDataResponse
:一个数据响应; -
KTVHCDataReader
:读取数据; -
KTVHCDataCacheItem
:缓存数据模型,表一个缓存项; -
KTVHCDataCacheItemZone
:缓存区,一个缓存项中会有多个缓存区,比如0-99,100-299 等; -
KTVHCDataSourcer
:数据源中心,负责处理不同数据源,它包含有一个数据队列KTVHCDataSourceQueue
; -
KTVHCDataSourceQueue
:数据队列; -
KTVHCDataSourceProtocol
:一个协议,作为数据源时需要实现这个协议; -
KTVHCDataFileSource
:本地数据源,实现了KTVHCDataSourceProtocol
协议; -
KTVHCDataNetworkSource
:网络数据源,实现了KTVHCDataSourceProtocol
协议; -
KTVHCDataUnit
:数据单元,相当于一个缓存目录,比如一个视频的缓存; -
KTVHCDataUnitItem
:数据单元项,缓存目录下不同片段的缓存; -
KTVHCDataUnitPool
:数据单元池,它是一个单例,含有一个KTVHCDataUnitQueue
; -
KTVHCDataUnitQueue
:数据单元队列,保存了多个KTVHCDataUnit
,它会以archive
的方式缓存到本地;
接入缓存
- (void)initCache {
NSError *error = nil;
[KTVHTTPCache proxyStart:&error];
if (error) {
NSLog(@"Proxy Start Failure, %@", error);
}
// 设置缓存最大容量
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
。
实现预加载
当播放视屏列表时,最好在播放当前视频时,能够预加载下几个即将要播放的视频。
可以使用NSOperationQueue
操作队列在实现在后台提前预加载待播放的视频。在当前视频的链接配置完毕时,可以根据业务实际需要,将下一个或下几个视频url用NSOperation
加到NSOperationQueue
中,在后台进行预加载,这样当用户滑动视频,下一个视频就已经是提前预加载好的了。当然,这里只是简单提供思路,项目中使用NSOperationQueue
也是很方便就能实现的,可以控制最大并发数量,是预加载当前index
前面的视频还是后面的视频,弱网是否执行预加载,具体的预加载逻辑还是要结合业务来操作。