播放器 SDK 支持下载功能。用户可在有网络的条件下将视频下载至本地,随后在无网络的环境下观看。播放器 SDK 支持下载 DirectUrl 视频源和 Vid 视频源,并提供开始、暂停、恢复、删除等控制下载任务的方法。本文介绍如何接入播放器 SDK 的下载功能,包含功能介绍、前提条件、集成步骤等内容。
注意
如需下载 HLS 视频,请集成 iOS 播放器 SDK 1.37.1.7 或以上版本。
使用下载功能前,您需要先在播放器 SDK 初始化过程中对下载功能进行一些必要的配置,例如是否开启下载 HLS 视频的能力、设置下载路径。此外您还可以设置最大并发数和空闲磁盘空间大小的限制等。
注意
需要特别注意的是,初始化代码的时序对下载功能是否能正常工作有直接影响:
HLSProxyModule,从而开启 HLS 下载功能。此方法必须在 [TTSDKManager startWithConfiguration:] 方法之前调用。[TTSDKManager startWithConfiguration:] 方法之前调用。[TTSDKManager startWithConfiguration:] 方法之后调用。示例代码如下:
#import <TTSDKFramework/TTVideoEngine+Preload.h> #import <TTSDKFramework/TTVideoEngine+Options.h> #import <TTSDKFramework/TTVideoEngineDownloader.h> - (void)initTTSDK { // 开启 HLS 下载功能。可选,如业务中无需下载 HLS 视频,可跳过。 [[TTVideoEngine ls_localServerConfigure] setOptionForKey:@(VEKKeyHLSProxyProtocolEnable_BOOL) value:@YES]; // 必填,设置下载文件存储路径 // 注意:必须是沙盒可写存储路径,并且是绝对路径 // 以下为存储路径示例,您也可以根据实际情况填写其他 app 可写路径 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *cacheDir = [paths firstObject]; [TTVideoEngine ls_localServerConfigure].downloadDirectory = [cacheDir stringByAppendingPathComponent:@"VideoDownload"]; // 初始化播放器 SDK [TTSDKManager startWithConfiguration:configuration]; // 选填,设置最大并发下载数,默认值为 1 [TTVideoEngineDownloader shareLoader].maxDownloadOperationCount = 3; // 选填,设置空闲磁盘空间大小的限制,默认值 1 GB // 当前设为 1G,如果剩余磁盘大小不足 1G,则返回 TTVideoEngineErrorNotEnoughDiskSpace 错误 [TTVideoEngineDownloader shareLoader].limitFreeDiskSize = 1024 * 1024 * 1024; // iOS 播放器 SDK 默认支持缓存最多 50 个视频,如业务超出此限制,需进行以下设置 [TTVideoEngine setGlobalForKey:VEGSKeyPlayerVideoModelMaxCache_NSInteger value:@(500)]; }
播放器 SDK 支持播放 DirectUrl 视频源和 Vid 视频源。与之对应,播放器 SDK 也提供了不同数据源的下载能力。创建新的下载任务之前,建议您调用 getAllTasksWithCompletionHandler 方法获取已有下载任务。播放器 SDK 会自动保存未完成的下载任务,在对应业务启动时调用可以获取先前被中断的下载任务。您可以在 getAllTasksWithCompletionHandler 的 block 中创建下载任务,以保证调用顺序。
说明
getAllTasksWithCompletionHandler 需要在主线程调用。[[TTVideoEngineDownloader shareLoader] getAllTasksWithCompletionHandler:^(NSArray<__kindof TTVideoEngineDownloadTask *> * _Nonnull tasks) { TTVideoEngineDownloadURLTask *urlTask = [[TTVideoEngineDownloader shareLoader] urlTask:@[urlString] key:key videoId:nil]; [urlTask resume]; }];
[[TTVideoEngineDownloader shareLoader] getAllTasksWithCompletionHandler:^(NSArray<__kindof TTVideoEngineDownloadTask *> * _Nonnull tasks) { TTVideoEngineDownloadVidTask *vidTask = [[TTVideoEngineDownloader shareLoader] vidTask:videoID playAuthToken:token resolution:TTVideoEngineResolutionTypeSD]; [vidTask resume]; }];
通过以下方法控制单个下载任务:
// 开始/恢复单个下载任务。 // 支持断点续传。 [task resume]; // 暂停单个下载任务,支持断点续传。 // 此方法需要在主线程调用。 [task suspend]; // 删除单个下载任务。 // 下载任务被删除后,任务会停止,同时 TTVideoEngineDownloader 将不再管理这个任务。 // 此接口为异步操作,您需要在 `getAllTasksWithCompletionHandler` 的回调中检查是否被删除。 [task invalidateAndCancel];
通过以下方法控制所有下载任务:
// 暂停所有下载任务。 // 此方法必须在 `getAllTasksWithCompletionHandler` 之后调用。 - (void)suspendAllTasks; // 开始/恢复所有下载任务。 // 此方法必须在 `getAllTasksWithCompletionHandler` 之后调用。 - (void)resumeAllTasks; // 删除所有下载任务。 // 此方法必须在 `getAllTasksWithCompletionHandler` 之后调用。 - (void)removeAllTasks;
注意
下载任务删除后,该任务对应的视频文件也会被删除。
下载任务的完成情况、进度和状态等信息都需要通过实现 TTVideoEngineDownloaderDelegate 中的方法来获取,示例代码如下:
// 设置回调接收 [TTVideoEngineDownloader shareLoader].delegate = self;
/** * 下载任务完成回调。 * @param downloadTask 当前下载任务。 * @param error 错误。error 为 null 则为下载任务成功,否则为下载任务失败。详细信息,请见[错误码文档](https://www.volcengine.com/docs/4/66441)。 * - TTVideoEngineErrorNetworkNotAvailable = -9960,//网络不可用 * - TTVideoEngineErrorSaveTaskItem = -9949, * - TTVideoEngineErrorWriteFile = -9948, * - TTVideoEngineErrorNotEnoughDiskSpace = -9947, * - TTVideoEngineErrorURLUnavailable = -9945, * - TTVideoEngineErrorServiceInaccessible = -9944, * - TTVideoEngineErrorExistedTask = -9943, */ - (void)VideoEngineDownloader:(TTVideoEngineDownloader *)downloader downloadTask:(TTVideoEngineDownloadTask *)downloadTask didCompleteWithError:(nullable NSError *)error; /** * 下载任务进度更新回调。 * @param downloadTask 当前下载任务。 * - downloadTask.countOfBytesReceived 当前下载任务已下载的数据总量(HLS 不适用,见下方注意点) * - downloadTask.countOfBytesExpectedToReceive 当前下载任务需要下载的总数据量(HLS 不适用,见下方注意点) * - downloadTask.progress 当前下载任务进度 0.0~1.0 * @param bytesWritten 本次回调新增下载的数据量,单位为 Byte。 * @param timeMS 当前时间。 */ - (void)VideoEngineDownloader:(TTVideoEngineDownloader *)downloader downloadTask:(TTVideoEngineDownloadTask *)downloadTask writeData:(int64_t)bytesWritten timeInterval:(double)timeMS; /** * 下载任务开始/恢复回调。 * @param downloadTask 当前下载任务。 * @param fileOffset 已下载的数据量。 * @param expectedTotalBytes 该任务要下载的总数据量。 */ - (void)VideoEngineDownloader:(TTVideoEngineDownloader *)downloader downloadTask:(TTVideoEngineDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes; /** * 下载任务状态变更回调。 * @param downloadTask 当前下载任务。 * @param downloadState 当前下载任务状态: * - TTVideoEngineDownloadStateInit(0): 初始化。 * - TTVideoEngineDownloadStateWaiting(1): 等待中。 * - TTVideoEngineDownloadStateRunning(2): 运行中。 * - TTVideoEngineDownloadStateSuspended(3): 暂停。 * - TTVideoEngineDownloadStateCanceling(4): 正在取消。 * - TTVideoEngineDownloadStateCompleted(5): 完成。 */ - (void)VideoEngineDownloader:(TTVideoEngineDownloader *)downloader downloadTask:(TTVideoEngineDownloadTask *)downloadTask stateChanged:(TTVideoEngineDownloadState)downloadState;
注意
如果下载的媒体类型为 HLS(M3U8),SDK 无法知道整个视频的文件大小,回调中的 countOfBytesReceived 和 countOfBytesExpectedToReceive 数值并不准确。因此,对于 HLS(M3U8)您仅可以通过 - [TTVideoEngineDownloadTask progress] 获取下载的进度。
SDK 内部已经处理了下载缓存与播放的关联关系。SDK 会优先播放已经下载的视频,即使它们尚未完全下载完成,因此您播放时无需额外设置。
参考以下示例代码播放 DirectUrl 视频源:
// 播放已下载的 HLS 视频前必须设置以下 option [self.videoEngine setOptionForKey:VEKKeyIsAllowAllExtensions value:@1]; // 注意 cacheKey 与下载时使用的 cacheKey 一致 TTVideoEngineUrlSource *urlSource = [[TTVideoEngineUrlSource alloc] initWithUrl:videoUrl cacheKey:cacheKey]; [self.videoEngine setVideoEngineVideoSource:urlSource]; [self.videoEngine play];
参考以下示例代码播放 Vid 视频源:
// 离线播放已下载的视频前必须设置以下 option [self.videoEngine setOptionForKey:VEKKeyModelCacheVideoInfoEnable_BOOL value:@(YES)]; [self.videoEngine setOptionForKey:VEKKeyPlayerVideoModelPriority_ENUM value:@(TTVideoEngineVideoModelUseLocal)]; // 播放已下载的 HLS 视频前必须设置以下 option [self.videoEngine setOptionForKey:VEKKeyIsAllowAllExtensions value:@1]; // 注意 resolution 与下载时使用的 resolution 一致 TTVideoEngineVidSource *vidSource = [[TTVideoEngineVidSource alloc] initWithVid:vid playAuthToken:playAuthToken resolution:resolution]; [self.videoEngine setVideoEngineVideoSource:vidSource]; [self.videoEngine play];
resume() 方法尝试恢复下载,会出现报错,错误码为 -9943。该错误码的含义是“任务已存在”。URL。vid 和 playAuthToken。[task invalidateAndCancel] 方法删除当前任务。SDK 会触发 VideoEngineDownloader:downloadTask:didCompleteWithError 的回调。didCompleteWithError 回调中,通过判断 error.code == TTVideoEngineErrorUserCancel 来确认任务是由用户(或代码逻辑)主动取消的。确认后,即可使用第一步中保存的任务信息,重新创建一个新的下载任务并开始下载。