You need to enable JavaScript to run this app.
导航

接入预加载

最近更新时间2023.10.11 18:55:48

首次发布时间2021.02.23 10:42:42

预加载是指在开始播放之前,提前下载即将播放视频的头部数据,播放时达到快速起播,大幅优化播放体验。预加载在各播放场景都可以使用,接入成本低,效果明显。

预加载策略

预加载使用原则是不影响当前视频播放,选择合理精细的预加载时机,可以有效的提高预加载命中率,提升首帧体验。如果粗放不合理的预加载时机,会出现浪费流量的现象,导致成本增加。

如下介绍 3 个常见场景中使用预加载策略的效果和推荐简单使用规则。

alt

短视频(竖屏类抖音)

场景特点:类似抖音场景,一屏只展示一个竖版视频,一次滑动只能滑动一个视频。

说明

我们推荐您使用最佳策略,能够快速实现零首帧体验的短视频播放效果。详情请见最佳实践:Android 短视频场景

  • 预加载时机:当前视频缓冲时长超过 20秒或全部缓冲完成,可以开始向下进行预加载。
  • 预加载数量:推荐预加载视频数量设置为 3个。用户停留在当前视频位置观看视频,当前位置记为 index,向下预加载 n 个视频,预加载范围:[index + 1,index+n]。
  • 预加载大小:建议预加载的大小设置 800K。
  • 取消:滑动切换播放视频时,取消全部预加载,避免对当前播放视频带宽产生争抢,影响当前视频的首帧。

中视频(横屏类西瓜)

场景特点: Feed 一屏中同时存在 2个以上视频。Feed 流可以快速滑动,一次滑动可能划过多个视频。

  • 预加载时机: 当前视频缓冲时长超过 20秒或全部缓冲完成,可以开始向下进行预加载。
  • 预加载数量: 推荐预加载视频数量设置为 5个。用户停留在当前视频位置观看视频,当前位置记为 index,向下预加载 n 个视频,预加载范围:[index + 1, index + n]。
  • 预加载大小: 建议预加载的大小设置 800K。
  • 取消: 滑动切换播放视频时,取消全部预加载,避免对当前播放视频带宽产生争抢,影响当前视频的首帧。

长视频

场景特点:沉浸式的全屏播放场景和播放页播放场景,例如影视、综艺等长视频的播放场景。

可根据具体场景,例如影视综艺,可以在当前剧集将要播放完成,预加载下一剧集。

接入预加载

在开始添加任务之前,需要明确 SDK 启动配置信息是否符合预期。

注意

预加载为高级版 SDK 功能,若您目前使用的是基础版 SDK,请先在控制台中购买高级版 License,在高级版 SDK中进行接入。

接入方式

接入预加载的方式有 2种:URL 方式接入、Vid 方式接入。

  • 构造播放源
预加载与播放使用相同的播放源结构。为保证播放能命中预加载缓存,需确保预加载与播放构造的播放源 vid、url、cacheKey 一致。代码示例如下所示。
public static DirectUrlSource createDirectUrlSource() {
    final String vid = "video id"; // 视频源与 vid 必须一一对应
    final String url = "http://www.example.com/h264.mp4";
    // cacheKey 用作磁盘缓存的文件名,建议采用 url 中能标识视频文件的部分的 MD5 值
    final String cacheKey = TTVideoEngine.computeMD5(url); 
    DirectUrlSource directUrlSource = new DirectUrlSource.Builder()
            .setVid(vid)
            .addItem(new DirectUrlSource.UrlItem.Builder()
                    .setUrl(url)
                    .setCacheKey(cacheKey)
                    .build())
            .build();
    return directUrlSource;
}
    
  • 添加预加载任务
代码示例如下所示。
public static void preloadUrlSource() {
    // Step 1: 构造播放源
    final DirectUrlSource source = createDirectUrlSource();
    final long preloadSize = 800 * 1024; // 预加载大小 800K    
    // Step2: 构造预加载 Item
    final PreloaderURLItem preloadItem = new PreloaderURLItem(source, preloadSize);
    preloadItem.setCallBackListener(new IPreLoaderItemCallBackListener() {
        @Override
        public void preloadItemInfo(PreLoaderItemCallBackInfo info) {
            if (info == null) return;
            final int key = info.getKey();
            switch (key) {
                case PreLoaderItemCallBackInfo.KEY_IS_PRELOAD_END_SUCCEED: {
                    // 预加载成功
                    DataLoaderHelper.DataLoaderTaskProgressInfo cacheInfo = info.preloadDataInfo;
                    if (cacheInfo == null) return;
                    String vid = cacheInfo.mVideoId; // 传入的 vid
                    String cacheKey = cacheInfo.mKey; // 预加载的视频文件的 fileHash
                    String cachePath = cacheInfo.mLocalFilePath; // 缓存视频文件路径
                    long mediaSize = cacheInfo.mMediaSize; // 缓存视频文件总大小
                    long cachedSize = cacheInfo.mCacheSizeFromZero; // 已缓存大小
                    Log.d("VideoPlay", "[preload] result success."
                            + " vid = " + vid
                            + ", cacheKey = " + cacheKey
                            + ", mediaSize = " + mediaSize
                            + ", cachedSize = " + cachedSize);
                    break;
                }
                case PreLoaderItemCallBackInfo.KEY_IS_PRELOAD_END_FAIL: {
                    // 预加载失败
                    Log.d("VideoPlay", "[preload] result failed."
                            + " vid = " + source.vid()
                            + ", error = " + info.preloadError);
                    break;
                }
                case PreLoaderItemCallBackInfo.KEY_IS_PRELOAD_END_CANCEL: {
                    // 预加载取消
                    Log.d("VideoPlay", "[preload] result canceled."
                            + " vid = " + source.vid());
                    break;
                }
                default: {
                    break;
                }
            }
        }
    });
    // Step3: 添加预加载任务
    TTVideoEngine.addTask(preloadItem);
}
    
  • 取消预加载任务
  • 说明

    取消任务,对没开始执行的任务和正在下载的任务有影响,对已经完成的任务没有影响。

    代码示例如下所示。
    // 取消单个预加载任务
    // cacheKey 为构造 DirectUrlSource 播放源时传入的 cacheKey
    TTVideoEngine.cancelPreloadTask(cacheKey); 
    
    // 取消全部预加载任务
    TTVideoEngine.cancelAllPreloadTasks();
        

    验证是否命中预加载

    通过播放器监听回调确认是否命中预加载。代码示例如下所示。

    // TTVideoEngine 实例设置监听
    ttVideoEngine.setVideoEngineInfoListener(new VideoEngineInfoListener() {
        @Override
        public void onVideoEngineInfos(VideoEngineInfos videoEngineInfos) {
            if (videoEngineInfos == null) {
                return;
            }
              
            if (videoEngineInfos.getKey().equals(USING_MDL_HIT_CACHE_SIZE)) {
                // 启播命中缓存判断
                String taskKey = videoEngineInfos.getUsingMDLPlayTaskKey();// 使用的 key 信息
                long cacheSize = videoEngineInfos.getUsingMDLHitCacheSize();// 命中缓存文件 size
                
                // cacheSize > 0 , 表示命中缓存
                // cacheSize = 0 , 未命中缓存,请排查预加载任务是否成功,如果是vid方式,请检查播放和预加载的reslution是否一致
            }
        }
    });
    
    

    说明

    1. 播放器默认支持边下载边播放。
    • 如果某个视频是第一次播放,命中的缓存是预加载下载的数据;
    • 第二次播放,可能是第一次播放的缓存。
    1. 如果测试预加载缓存的命中率,前提要保证每个视频都是第一次播放,建议首次安装进行测试。

    设置预加载任务并发数

    // 设置预加载任务的并发数,默认值为 1,串行执行预加载任务
    TTVideoEngine.setIntValue(DataLoaderHelper.DATALOADER_KEY_INT_PARALLEL_NUM, 1);