预加载是指在视频正式播放前,提前下载视频的头部数据,从而缩短视频的起播时间。这是提升首帧播放体验的关键手段之一。本文将指导您如何通过播放器 SDK 实现自定义预加载功能。
本节介绍不同播放场景中预加载的规则和效果。通过选择合理精细的预加载时机和设置,可以提高预加载命中率,从而提升首帧体验。需要注意的是,过度粗放或不合理的预加载时机可能会导致流量浪费,增加成本。
说明
针对短视频场景,播放器 SDK 基于抖音亿级日活跃用户的真实反馈和大规模实践经验,封装了两大最佳策略:预加载策略和预渲染策略,帮助您快速搭建“抖音”同款短视频场景,实现“零首帧”的播放效果。详情请见抖音同款短视频最佳实践。
版本要求:本功能仅高级版和企业版支持。请确保您已购买相应版本的 License 并集成了正确的 SDK 依赖。详情请参见 License 管理。
自定义预加载的核心流程分为三步:
首先,您需要创建一个 TTVideoEngineUrlSource 对象,既用于预加载,也用于后续的播放。DirectUrl 模式适用于播放来自火山引擎或第三方 CDN 的视频 URL 地址。通过传入视频的直接播放地址来指定播放内容。除了 url,您还必须提供以下参数:
cacheKey:视频的缓存索引 Key。为确保唯一性,推荐使用 URL 的 MD5 值。为确保播放器缓存和下载功能的稳定性,强烈建议您遵循以下规范来设置 cacheKey:
cacheKey 的取值应仅包含字母 (a-z, A-Z) 和数字 (0-9)。cacheKey 中使用任何特殊符号,例如 _、-、/、?、& 等。注意
为保证播放能命中预加载缓存,需确保预加载与播放构造的播放源 url、cacheKey 一致。
- (TTVideoEngineUrlSource *)createUrlSource { NSString *url = @"http://www.example.com/h264.mp4"; // cacheKey 是预加载缓存的唯一标识,必须与播放时使用的 cacheKey 完全一致。 // 强烈建议使用 URL 中不变部分的 MD5 值,以确保播放时能命中缓存。 // 例如 URL 中如果有时间戳等每次请求会变的部分要去除掉,这样才可以保证每次播放的时候命中本地缓存,避免预加载数据不生效导致流量浪费。 NSString *cacheKey = [url md5String]; // 如果需要指定 URL source 的 encodetype 和解密 key 或标明是否为 HDR 播放源可以使用其他重载的接口. 见: TTVideoEngineUrlSource.h TTVideoEngineUrlSource *source = [[TTVideoEngineUrlSource alloc] initWithUrl:url cacheKey:cacheKey]; return source; }
然后,使用这个 source 和您期望的预加载大小来创建一个 TTVideoEnginePreloaderURLItem 任务。
- (void)addPreloadTask { // preloadSize: 预加载大小,例如 800 KB TTVideoEnginePreloaderURLItem * urlItem = [TTVideoEnginePreloaderURLItem urlItemWithVideoSource:[self createUrlSource] preloadSize:800 * 1024]; urlItem.preloadProgress = ^(TTVideoEngineLoadProgress * _Nonnull progress) { // preload progress }; urlItem.preloadEnd = ^(TTVideoEngineLocalServerTaskInfo * _Nullable info, NSError * _Nullable error) { // preload end }; [TTVideoEngine ls_addTaskWithURLItem:urlItem]; }
取消任务,对没开始执行的任务和正在下载的任务有影响,对已经完成的任务没有影响。
// 取消单个预加载任务 // cacheKey 为添加任务时对应的 key. [TTVideoEngine ls_cancelTaskByKey:cacheKey]; // 取消全部预加载任务 [TTVideoEngine ls_cancelAllTasks];
预加载与播放使用相同的播放源结构。为保证播放能命中预加载缓存,需确保预加载与播放构造的播放源 vid、playAuthToken、encodeType、resolution 一致。
resolution, SDK 内部在预加载和播放时,将使用 TTVideoEngineResolutionTypeSD 作为默认值。encodeType,SDK 内部在预加载和播放时,将使用TTVideoEngineH264 作为默认值。- (TTVideoEngineVidSource *)createVidSource { // appServer 下发 NSString *vid = @"your video id"; // appServer 下发 NSString *playAuthToken = @"your video id's play auth token"; // 指定为 H.264 编码格式 TTVideoEngineEncodeType encodeType = TTVideoEngineH264; // 指定为 720 分辨率 TTVideoEngineResolutionType resolution = TTVideoEngineResolutionTypeFullHD; TTVideoEngineVidSource *vidSource = [[TTVideoEngineVidSource alloc] initWithVid:vid playAuthToken:playAuthToken resolution:resolution encodeType:encodeType isDash:NO isHLS:NO]; return vidSource; }
- (void)addVidPreloadTask { // preloadSize: 预加载大小,单位为字节;例如 800 KB 传入 800 * 1024 TTVideoEnginePreloaderVidItem *item = [TTVideoEnginePreloaderVidItem vidItemWithVideoSource:[self createVidSource] preloadSize:(800 * 1024)]; item.fetchDataEnd = ^(TTVideoEngineModel * _Nullable model, NSError * _Nullable error) { // get video model end }; item.preloadProgress = ^(TTVideoEngineLoadProgress * _Nonnull progress) { // preload progress }; item.preloadEnd = ^(TTVideoEngineLocalServerTaskInfo * _Nullable info, NSError * _Nullable error) { // preload end }; [TTVideoEngine ls_addTaskWithVidItem:item]; }
播放时确保播放和预加载数据源设置分辨率信息一致,代码示例如下所示。
- (void)play { // 播放和预加载数据源保持一致 TTVideoEngineVidSource *vidSource = [self createVidSource]; [self.videoEngine setVideoEngineVideoSource:vidSource]; [self.videoEngine play]; }
取消任务,对没开始执行的任务和正在下载的任务有影响,对已经完成的任务没有影响。
// 取消单个预加载任务,需要指定视频 vid [TTVideoEngine ls_cancelTaskByVideoId:vid]; // 取消全部预加载任务 [TTVideoEngine ls_cancelAllTasks];
“命中预加载”指的是,当您调用 play 方法播放一个视频时,播放器 SDK 发现这个视频的部分数据(即您之前通过预加载任务下载的头部数据)已经存在于本地缓存中,于是直接从本地读取这部分数据来开始播放,而无需等待从网络下载。可在视频首次播放时,通过播放器的代理回调 videoEngine:mdlKey:hitCacheSze: 来验证。
说明
测试技巧:为准确测试预加载的命中率(而非播放缓存),建议在首次安装应用或清除应用缓存后进行测试。因为播放器默认支持边下载边播放,在播放过程中也会产生缓存,第二次播放同一个视频通常会命中“播放缓存”,这与“预加载缓存”是不同的机制。
// engine 实例的代理方法 - (void)videoEngine:(TTVideoEngine *)videoEngine mdlKey:(NSString *)key hitCacheSze:(NSInteger)cacheSize { if (cacheSize > 0) { // 命中缓存成功,cacheSize 是命中的字节数。 } else { // 未命中缓存。 // 请检查以下关键点: // 1. 预加载任务是否已在播放开始前成功完成 // 2. 播放时使用的 Source 参数 (cacheKey/vid/resolution/encodeType等) 是否与预加载时完全一致 } }
您可以配置同时进行的预加载任务数量,默认为 2。
// 设置预加载任务的并发数,默认值为 2 // 如下设置为 1,串行执行预加载任务 [TTVideoEngine ls_localServerConfigure].preloadParallelNum = 1;