You need to enable JavaScript to run this app.
文档中心
文档控制台
注册
视频点播

视频点播

复制全文
下载 pdf
进阶功能
播放源自动刷新
复制全文
下载 pdf
播放源自动刷新

说明

适用版本:ve_vod Flutter SDK ≥ 1.50.16
平台:iOS / Android
能力简介:当签名播放 URL 过期、或 HLS 分片请求报错时,SDK 自动回调业务层换取新的播放地址,实现无感续播,无需重建播放器或重新起播。

能力概述

播放源自动刷新用于解决签名播放地址有时效的问题。火山引擎 VOD 的播放 URL 通常带有签名鉴权参数(如 auth_key、过期时间戳),长视频播放、后台挂起后恢复、HLS 长拉流等场景下,URL 可能在播放过程中过期,导致拉流失败、卡住或报错。

开启本能力后,SDK 在检测到地址过期或分片错误时,会主动回调到业务层索取新的播放地址并热替换,播放过程无感知、不中断

典型适用场景

  • 长视频 / 直播回放等单次播放时长可能超过 URL 有效期的场景
  • App 切后台、锁屏后长时间恢复继续播放
  • 短剧、点播列表等需要长时间连续播放的业务
  • HLS(m3u8)分片在播放中途因签名过期返回 4xx/403 的情况

快速接入

三步即可接入:实现回调 → 注册回调 → 起播前开启策略

import 'package:ve_vod/ve_vod.dart';

// 1. 实现业务刷新回调
class MyUrlRefreshCallback implements TTVideoEngineUrlRefreshCallback {
  @override
  Future<dynamic> refreshUrl(TTVideoEngineUrlRequest request) async {
    // request.url / request.cacheKey / request.vid
    // 向业务服务端换取新的播放信息(可返回 GetPlayInfo 的 PlayInfoList)
    final playInfoList = await fetchNewPlayInfoList(request.vid);
    return playInfoList;
    // 也可直接返回 TTVideoEngineUrlResult(url: newUrl, expireTimeInMS: ts);
  }

  @override
  void cancel() {
    // 取消正在进行的网络请求
  }
}

// 2. 注册回调(建议在 App 启动或进入播放页时)
TTVideoEngineSourceRefreshStrategy.setUrlRefreshCallback(
  MyUrlRefreshCallback(),
);

// 3. 起播前开启策略,然后再设置播放源
await player.enableSourceRefreshStrategy(enableHlsSegError: true);
await player.setMediaSource(mediaSource);

说明

调用顺序很重要:必须先 setUrlRefreshCallback() 注册回调,并在 setMediaSource() 之前调用 enableSourceRefreshStrategy(),策略才会对本次播放源生效。

接口说明

业务需实现的回调接口

abstract class TTVideoEngineUrlRefreshCallback {
  /// 刷新过期的 URL。可返回 TTVideoEngineUrlResult,
  /// 或返回包含全部播放地址的 MediaSource / Map / List,由 SDK 自动匹配。
  Future<dynamic> refreshUrl(TTVideoEngineUrlRequest request);

  /// 取消正在进行的刷新操作
  void cancel();
}

请求与结果模型

类型字段说明
TTVideoEngineUrlRequesturl(String)已过期的旧播放地址
cacheKey(String)该地址对应的缓存 key
vid(String?)视频 ID(设置播放源时绑定,可能为空)
TTVideoEngineUrlResulturl(String)刷新后的新播放地址
expireTimeInMS(int)新地址过期时间(毫秒时间戳,详见 expireTimeInMS 时间单位

策略管理类 TTVideoEngineSourceRefreshStrategy(静态)

方法说明
init()初始化 channel handler(首次调用其他方法时会自动初始化,一般无需手动调用)
setUrlRefreshCallback(cb)注册 URL 刷新回调(必需
clearUrlRefreshCallback()清除 URL 刷新回调
setGenerateFileKeyCallback(cb)注册 HLS cacheKey 生成回调(可选,详见 HLS CacheKey 生成
clearGenerateFileKeyCallback()清除 HLS cacheKey 生成回调

播放器实例开关 VodPlayerFlutter

/// 启用源过期自动刷新
/// [enableHlsSegError] 是否启用 HLS 分片错误处理,默认 true
/// 建议在 setMediaSource() 之前调用
Future<void> enableSourceRefreshStrategy({bool enableHlsSegError = true});

/// 禁用源过期自动刷新
Future<void> disableSourceRefreshStrategy();
  • enableHlsSegError:开启后,HLS(m3u8)分片因签名过期返回错误时也会触发刷新;纯 MP4 等非 HLS 源可关闭。

刷新结果(refreshUrl 返回值)

refreshUrl() 的返回值非常灵活,SDK 会自动归一化为一条 {url, expireTimeInMS}。支持以下几种返回形式:

返回类型行为
TTVideoEngineUrlResult直接使用该 url 与过期时间
Map(含 url + expireTimeInMS/expireInMS直接取该地址
TTVideoEngineMediaSource / Map(完整播放信息)SDK 按旧 URL 的 path 匹配出对应档位的新地址
List(如 PlayInfoList)遍历每一项做 path 匹配,取第一个命中的地址

推荐做法

业务侧直接把服务端 GetPlayInfo 返回的 PlayInfoList(或整个响应)原样返回即可,无需自己挑选档位——SDK 会用旧地址的 path 自动匹配回同一清晰度的新地址。

自动匹配逻辑

  • 以旧 URL 的 path(去掉签名 query)为基准,在新播放信息中查找 path 相同的地址;
  • 兼容多种字段命名:urls / MainPlayUrl / BackupPlayUrlexpires / urlExpiredTimes / MainUrlExpire / BackupUrlExpireplayInfoList / PlayInfoList,以及 Result 包裹层;
  • 主备地址优先级:依据旧 URL 的 a=0 查询参数判断优先匹配主地址(MainPlayUrl)还是备地址(BackupPlayUrl)。

expireTimeInMS 时间单位

过期时间同时兼容秒级与毫秒级时间戳:小于 100000000000 的值会被视为并自动 ×1000 转为毫秒。因此服务端无论返回秒级(如 1875780093)还是毫秒级时间戳都能正确解析。

注意

当返回 TTVideoEngineUrlResultMap 形式时,expireTimeInMS必填,缺失会抛出 TTError。返回完整 PlayInfoList 时由 SDK 从 MainUrlExpire 等字段读取。

HLS CacheKey 生成(可选)

HLS 场景下,TS 分片的缓存 key 默认由完整 URL 推导。当签名参数变化时,同一分片可能因 URL 不同而被认为是不同文件,影响缓存命中。可选地注册 generateFileKey 回调,剥离签名参数后生成稳定 cacheKey,保证签名变化时缓存仍唯一且可复用。

typedef GenerateFileKeyCallback = String Function(
    String url, String fileKey, Map<String, String> extraInfo);

String myGenerateFileKey(
    String url, String fileKey, Map<String, String> extraInfo) {
  final uri = Uri.parse(url);
  final params = Map<String, String>.from(uri.queryParameters)
    ..removeWhere((k, v) =>
        k.toLowerCase().contains('token') ||
        k.toLowerCase().contains('sign') ||
        k.toLowerCase().contains('auth'));
  final cleanUrl = uri.replace(queryParameters: params).toString();
  return cleanUrl.hashCode.toString(); // 实际应使用 MD5 等稳定哈希
}

// 注册(可选)
TTVideoEngineSourceRefreshStrategy.setGenerateFileKeyCallback(myGenerateFileKey);

说明

该回调为可选项:不注册时使用 SDK 默认 cacheKey 生成方式。若业务的签名参数名固定且明确,建议实现以提升缓存命中率。

注意事项与 FAQ

问题说明 / 排查
回调一直没被触发?确认:① 已 setUrlRefreshCallback();② 在 setMediaSource() 前调用了 enableSourceRefreshStrategy();③ 地址确实触发了过期/分片错误。可过滤日志 TAG Flutter_SourceRefresh 查看流程。
报 “Invalid refreshUrl result”?返回值类型不被支持,或返回的播放信息中找不到与旧 URL path 匹配的地址。请确认返回的新地址 path 与旧地址一致(同一档位)。
报 “expireTimeInMS is required”?返回 TTVideoEngineUrlResult/Map 时必须带过期时间;或改为返回完整 PlayInfoList 让 SDK 自行读取。
纯 MP4 源需要开 HLS 分片处理吗?不需要,可将 enableHlsSegError 设为 false
如何关闭?调用 player.disableSourceRefreshStrategy();如不再使用回调,可 clearUrlRefreshCallback()
最近更新时间:2026.07.15 21:56:37
这个页面对您有帮助吗?
有用
有用
无用
无用