You need to enable JavaScript to run this app.
视频点播

视频点播

复制全文
进阶功能
短视频场景开启预加载和预渲染策略
复制全文
短视频场景开启预加载和预渲染策略

为了帮助您快速搭建“抖音”同款短视频场景,解决用户滑动切换视频时首帧加载慢、资源消耗高的问题,播放器 SDK 基于抖音亿级日活跃用户的真实反馈和大规模实践经验,提供两大最佳策略:预加载策略(提前缓存视频数据,提升起播速度)和预渲染策略(提前创建播放器实例,优化切换体验)。本文将指导您如何开启和配置这两项策略,帮助您在性能与体验之间达到平衡。详细功能介绍,请见抖音同款短视频最佳实践

注意

该功能仅高级版支持。请确保您已购买高级版的 License,详见播放器 License

预加载策略

注意

预加载策略支持 Vid、 DirectUrl 和 VideoModel 三种形式的播放源。为了确保预加载的缓存能够被成功命中,在设置预加载列表时需要注意以下几点:

  • 当播放源为 Vid 或 VideoModel 类型时:​您必须在构建播放源时明确指定 resolution 字段,用以确定需要预加载哪一个清晰度的视频。后续实际播放该视频时,通过 setMediaSource 设置的播放源,其 resolution 字段也必须与预加载时设置的 resolution 保持一致,否则将无法命中缓存。
  • 当播放源为 DirectURL 类型时:您必须在构建播放源时明确指定 cacheKey 字段,该 cacheKey 只需保证其全局唯一即可。后续实际播放该视频时,通过 setMediaSource 设置的播放源,其 cacheKey 字段也必须与预加载时设置的 cacheKey 保持一致,否则将无法命中缓存。
// 方法定义见 TTVideoEngineStrategy
// 开启预加载策略,建议在进入短视频页面开启
TTVideoEngineStrategy.enableEngineStrategy(
          strategyType: TTVideoEngineStrategyType.preload, scene: TTVideoEngineStrategyScene.smallVideo);
          
// 设置预加载列表
static Future<void> setStrategyVideoSources({required List<TTVideoEngineMediaSource> videoSources})

// 更新预加载列表
static Future<void> addStrategyVideoSources({required List<TTVideoEngineMediaSource> videoSources})

// 指定预加载列表的起始位置。setStrategyVideoSources 后,可通过此方法立即启动预加载任务。
// 若未设置 index,用户进入 feed 后,默认从第二个视频开始加载 N 个;若设置了 index,则从所设 index 位置开始加载 N 个。 
static Future<void> startPreloadWithIndex({required int index})
          
// 关闭全部策略
TTVideoEngineStrategy.clearAllEngineStrategy();

监听命中预加载缓存:预加载成功后,播放器播放对应的播放源时,会优先使用预加载的缓存起播,从而加快起播速度。要验证预加载是否生效,您可监听播放器实例的 onMediaCacheChange 回调。当播放器开始播放一个视频时,如果该视频成功命中了预加载的缓存,此回调便会被触发,且 cacheSize 会大于 0。

// Media cache change callback (MDL hit cache info).
  // - key: MDL task key
  // - cacheSize: hit cache size (bytes)
  void Function(String key, int cacheSize)? onMediaCacheChange;

预渲染策略

在类抖音(TikTok)的 Feed 流场景中,为了加快用户上下滑动切换视频时的首帧速度,除了采用预加载提前缓存视频数据外,另一种常见的手段是提前创建下一个视频的播放器实例。当用户滑动到下一个视频时,播放器已准备就绪,从而节省了创建实例的时间,加快视频首帧展示。然而,手动管理多实例存在诸多弊端:

  • 资源消耗:不加限制地创建多实例会显著增加 CPU 和内存消耗,可能导致应用卡顿。
  • 资源竞态:在视频起播的关键时刻创建播放器,可能会因任务繁忙或资源竞争,反而拖慢首帧。

预渲染策略正是为了解决上述问题而设计的。它是一种更智能的多实例管理方案,能够在播放任务较为空闲的时机,自动提前为您创建并准备好下一个播放器实例,从而在性能与体验之间达到平衡。

核心实现步骤

步骤 1:开启预渲染策略

在您的短视频播放页面(例如 Feed 流页面)初始化时,开启预渲染策略。

// 方法定义见 TTVideoEngineStrategy
// 开启预渲染策略,建议在进入播放页面开启
TTVideoEngineStrategy.enableEngineStrategy(
  strategyType: TTVideoEngineStrategyType.preRender,
  scene: TTVideoEngineStrategyScene.smallVideo,
);

步骤 2:设置播放源列表

与预加载策略一样,预渲染策略也需要您提供一个视频源列表,以便 SDK 知道接下来可能要播放哪些视频。

// 设置、更新预渲染列表的方法与预加载策略完全一致,只需设置一次即可
TTVideoEngineStrategy.setStrategyVideoSources({
  required List<TTVideoEngineMediaSource> videoSources,
});

预渲染策略通过播放源的唯一 vid 来匹配和复用提前创建的播放器实例。因此,为每个播放源设置一个稳定且唯一的 vid 至关重要。对于 DirectURL 播放源,请务必在构造时传入 vid

  • 1.49.10 及之后的版本,使用 TTVideoEngineUrlSource.initWithURLVidCacheKey 工厂函数快速创建:
// 1.49.10+ 推荐
final urlSource = TTVideoEngineUrlSource.initWithURLVidCacheKey(
  url: mainPlayUrl,
  vid: widget.episode.vid, // 必须传入唯一的 vid
  cacheKey: cacheKey,
);
  • 1.49.10 之前的版本,可以使用默认构造函数:
final urlSource = TTVideoEngineUrlSource(
  urls: [url],
  cacheKey: cacheKey,
  vid: widget.episode.vid, // 同样需要传入唯一的 vid
);

步骤 3:设置预渲染回调

由于 Android 和 iOS 底层的预渲染实现存在差异,Flutter SDK 提供了两个平台专属的回调,用于在预渲染的播放器创建完成后,进行一些必要的起播前配置。

  • Android:您需要监听 onCreatePreRenderEngine 回调。在该回调中,您需要手动创建播放器实例、设置播放源,并可以进行其他自定义配置(如开启硬解)。
// 初始化策略模块,以便设置回调
TTVideoEngineStrategy.init();

TTVideoEngineStrategy.onCreatePreRenderEngine = ((source) async {
  // 该回调仅在 Android 端生效
  VodPlayerFlutter player = VodPlayerFlutter();

  // 1. 创建播放器,必须传入 source.getVid 和 preCreated: true
  String coreHashHex = await player.createPlayer(vid: source.getVid, preCreated: true);

  // 2. [必须] 为预渲染的播放器设置播放源
  await player.setMediaSource(source);

  // 3. [可选] 根据需求自定义设置,如是否开启硬解等
  player.setHardwareDecode(<enable>);
  // ...

  // 4. 注意:createPlayer 和 setMediaSource 必须 await 执行完毕后再返回 player
  return player;
});
  • iOS:SDK 内部会自动完成播放器的创建和播放源的设置。您只需监听 onPlayerCreated 回调,即可获取到已准备好的播放器实例,并进行起播前的自定义配置。
TTVideoEngineStrategy.onPlayerCreated = ((player) {
  // 该回调仅在 iOS 端生效
  // 不同于 Android,您无需在此处创建播放器或设置播放源
  
  // [可选] 根据需求自定义设置,如是否开启硬解等
  player.setHardwareDecode(<enable>);
});

步骤 4:获取并使用预渲染的播放器

在您的 Feed 流滑动逻辑中,当需要播放下一个视频时,只需在调用 createPlayer 时传入该视频对应的 vid。如果预渲染已成功完成,SDK 将立即返回一个已经提前创建好的播放器实例。

// 在用户滑动到下一页时...
VodPlayerFlutter player = VodPlayerFlutter();

// 传入目标视频的 vid。如果命中预渲染,SDK 会直接返回已创建的实例
await player.createPlayer(vid: source.getVid);

预渲染并不总是成功(例如,在用户快速滑动时,策略可能还未执行)。您可以在 createPlayer 之后,通过播放器的 isPreRender 属性来判断获取到的实例是否是预渲染的。

// 在 createPlayer 调用之后
bool isPreRender = await _player!.isPreRender;
if (isPreRender) {
    // 成功命中了预渲染
} else {
    // 未命中,这是一个新创建的播放器
}

进阶使用

使用预渲染首帧作为封面

您可以将预渲染完成的视频首帧直接用作视频封面。相比于传统的图片封面,这种方式不仅展示速度更快,还能因为复用了视频数据而更节省流量。在创建下一个视频的播放器之前,调用静态方法 VodPlayerFlutter.preRenderFirstFrame

// 方法定义见 VodPlayerFlutter
// vid: 待预渲染首帧视频的 vid
// viewId: 用于展示视频首帧的渲染 View 的 ID
// displayMode: 首帧的填充模式 (TTVideoEngineScalingMode)
String? res = await VodPlayerFlutter.preRenderFirstFrame(
  vid: vid, 
  viewId: viewId, 
  displayMode: displayMode,
);

// 在调用 preRenderFirstFrame 之后,再正常创建播放器并播放
VodPlayerFlutter player = VodPlayerFlutter();
String coreHashHex = await player.createPlayer(vid: vid);
player.setMediaSource(source);
// 注意:这里的 viewId 必须与 preRenderFirstFrame 中使用的 viewId 一致
player.setPlayerContainerView(viewId); 
player.play();
最近更新时间:2026.01.14 15:18:01
这个页面对您有帮助吗?
有用
有用
无用
无用