You need to enable JavaScript to run this app.
导航
进阶功能
最近更新时间:2025.03.06 15:58:45首次发布时间:2024.10.17 11:29:26
我的收藏
有用
有用
无用
无用

本文为您介绍如何使用 Flutter 点播 SDK 的进阶功能。

短视频场景预加载和预渲染策略

为了帮助您快速搭建“抖音”同款短视频场景,点播 SDK 基于抖音亿级日活跃用户的真实反馈和大规模实践经验,提供两大最佳策略:预加载策略预渲染策略。详细功能介绍,请见抖音同款短视频最佳实践

注意

该功能仅高级版或企业版支持。请确保您已购买高级版或企业版的 License,详见 License 包管理

接入预加载策略

// 方法定义见 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})
    
// 关闭全部策略
TTVideoEngineStrategy.clearAllEngineStrategy();

接入预渲染策略

// 方法定义见 TTVideoEngineStrategy
// 开启预渲染策略,建议在进入短视频页面开启
TTVideoEngineStrategy.enableEngineStrategy(
          strategyType: TTVideoEngineStrategyType.preRender, scene: TTVideoEngineStrategyScene.smallVideo);
          
// 设置和更新预渲染列表和预加载列表。仅需设置一次

// (可选)监听预渲染播放器完成回调,在回调内对预渲染播放器进行起播前配置(如 HLS 选档、硬解配置等),示例如下:
TTVideoEngineStrategy.init();
TTVideoEngineStrategy.onCreatePreRenderEngine = ((source) async {
        VodPlayerFlutter player = VodPlayerFlutter();
        String coreHashHex = await player.createPlayer(vid: source.getVid, preCreated: true);
        player.setUrlSource(source as TTVideoEngineUrlSource);
        player.setHLSMultiBitrateConfig(
          selectHlsVideoStream: () {
            return 800 * 1024;
          },
          selectHlsRendition: (variantIndex) {
            return 0;
          },
        );
        player.setHardwareDecode(GlobalConfiguration.isHardwareDecode);
        player.setTrackVolumeEnabled(GlobalConfiguration.isTrackVolume);
        player.setCustomHeader('x-tt-flutter-test-demo', '1');
        return player;
});

自定义预加载

预加载是指在开始播放之前提前下载即将播放视频的头部数据,以实现快速起播,从而显著优化播放体验。详细功能介绍,请见 Android 自定义预加载

注意

该功能仅高级版或企业版支持。请确保您已购买高级版或企业版的 License,详见 License 包管理

实现自定义预加载的步骤如下:

  1. 构造播放源并添加预加载任务。Vid 模式和 DirectUrl 模式的示例代码具体如下:

    // 使用vid和playAuthToken初始化vid source, resolution为期望预加载的档位
       TTVideoEngineVidSource source = TTVideoEngineVidSource.init(
               vid: <vid>,
               playAuthToken: <playAuthToken>,
               resolution: <TTVideoEngineResolutionType>);
       
       // 使用sourcec和preloadSize初始化PreloaderVidItem, 预加载字节数preloadSize默认800K 
       TTVideoEnginePreloaderVidItem item = TTVideoEnginePreloaderVidItem.vidItemWithVideoSource(source, 800 * 1024);
       
       // 添加预加载任务
       TTVideoEnginePreload.addTaskWithVidItem(item);
    
  2. 取消预加载任务:

    // 取消全部预加载任务
    TTVideoEnginePreload.cancelAllTask();
    
    // 根据key取消一个预加载任务,key为创建预加载任务使用的cacheKey
    TTVideoEnginePreload.cancelTaskByKey(Key);
    
  3. 监听预加载任务状态:

    // 对已添加的预加载任务PreloaderURLItem,监听item的cancel和end回调
    // 预加载任务取消
    item.onPreloadCancel = () {
        print('TTF --  预加载cancel 回调到dart');
    };
     
    // 预加载任务完成
    // taskInfo - 预加载任务的文件信息和下载信息
    // error - 预加载任务的error信息
    item.onPreloadEnd = (TTVideoEngineLocalServerTaskInfo? taskInfo, TTError? error) {
        Map<dynamic, dynamic>? map = taskInfo?.toJson();
        String errorStr = error.toString();
        print('TTF --  预加载end 回调到dart end = $map error = $errorStr');
    };
    

master.m3u8 档位切换

注意

该功能仅 Android 支持。

起播前档位选择

// 方法定义在 VodPlayerFlutter
/* 
  master-m3u8 起播前档位选择
  getHlsStreamInfos - 档位回调
  selectHlsVideoStream - 视频档位选择, 返回视频stream的bandwidth
  selectHlsRendition - 音轨选择,返回音频rendition的infoId
  switchHlsVideoBitrate - 档位选择回调, 如发生档位切换,回调选择档位的bandwidth
 */
Future<void> setHLSMultiBitrateConfig(
    {void Function(TTMasterPlaylist playlist)? getHlsStreamInfos,
    int? Function()? selectHlsVideoStream,
    int? Function(int variantIndex)? selectHlsRendition,
    void Function(int bitrate)? switchHlsVideoBitrate})
      
// 示例代码 (以随机档位为例,仅做参考)
_player?.setHLSMultiBitrateConfig(
    getHlsStreamInfos: (TTMasterPlaylist playlist) {
      _playlist = playlist;
      print('HLS档位回调:${playlist.toJson()}');
    },
    selectHlsVideoStream: () {
      // 示例选择档位随机
      if (_playlist!.variantStreams!.isNotEmpty) {
        int index = Random().nextInt(_playlist!.variantStreams!.length);
        TTMasterVariantStream stream = _playlist!.variantStreams![index];
        print('HLS视频起播档位选择, 随机index=$index, resolution-${stream.resolution} bandwidth-${stream.bandwidth}');
        return stream.bandwidth;
      }
      return -1;
    },
    selectHlsRendition: (int variantIndex) {
      // 示例选择音轨 'en'
      for (TTMasterRendition rendition in _playlist!.renditions!) {
        if (rendition.variantIndex != variantIndex) {
          continue;
        }
        if (rendition.language == 'en') {
          print('HLS音频起播档位选择, rendition.language=${rendition.language}, rendition.infoId-${rendition.infoId}');
          return rendition.infoId;
        }
      }
      return -1;
    },
    switchHlsVideoBitrate: (int bitrate) {
      print("HLS选择档位完成 最终bitrate = $bitrate");
    },
);

播放中档位选择

// 播放中切换 hls 视频档位,如传入的bitrate档位不存在,选择最接近的档位
Future<void> switchHlsVideoBitrate({required int bitrate})

// 播放中切换 hls 音轨,如传入的 audioInfoId 不存在,不切换
Future<void> switchHlsAudioRendition({required audioInfoId})

预加载档位选择

// 方法定义在 TTVideoEnginePreload
/* 
  master-m3u8起播前档位选择
  getHlsStreamInfos - 档位回调
  selectHlsVideoStream - 视频档位选择, 返回视频stream的bandwidth
  selectHlsRendition - 音轨选择,返回音频rendition的infoId
  switchHlsVideoBitrate - 档位选择回调, 如发生档位切换,回调选择档位的bandwidth
 */
Future<void> setHLSMultiBitrateConfig(
    {void Function(TTMasterPlaylist playlist)? getHlsStreamInfos,
    int? Function()? selectHlsVideoStream,
    int? Function(int variantIndex)? selectHlsRendition,
    void Function(int bitrate)? switchHlsVideoBitrate})
      
      
// 示例代码 (以随机档位为例,仅做参考)
TTVideoEnginePreload.setMasterPlaylistPreloaderCallback(
    onMasterM3U8PlaylistSelectPreloadUrls: (TTMasterPlaylist playlist) {
  if (playlist.variantStreams!.isEmpty) {
    return null;
  }
  List<TTMasterPreloadURLInfo> urlInfos = [];

  // 预加载视频流
  int index = Random().nextInt(playlist.variantStreams!.length);
  TTMasterVariantStream stream = playlist.variantStreams![index];
  TTMasterPreloadURLInfo urlInfo = TTMasterPreloadURLInfo(uri: stream.uri, preloadSize: 800 * 1024);
  urlInfos.add(urlInfo);
  print('预加载playlist 随机视频流uri=${stream.uri}, resolution=${stream.resolution} bandwidth=${stream.bandwidth}');

  // 预加载音频流
  if (playlist.renditions == null) {
    return urlInfos;
  }

  for (TTMasterRendition rendition in playlist.renditions!) {
    if (rendition.groupId == stream.audioGroupId) {
      TTMasterPreloadURLInfo urlInfo = TTMasterPreloadURLInfo(uri: rendition.uri, preloadSize: 500 * 1024);
      urlInfos.add(urlInfo);
      print('预加载playlist音频流uri=${rendition.uri}');
    }
  }
  return urlInfos;
});

外挂字幕

外挂字幕是指字幕文件与视频文件分开存储,用户在播放视频时按需导入字幕文件。点播 SDK 当前支持添加 WebVTT (Web Video Text Tracks) 格式的字幕文件。这种方式的优势在于其灵活性,用户可以根据实际需求选择是否导入字幕文件,或者选择加载不同语言的字幕。更重要的是,您无需进行额外的视频转码,只需要在播放端进行适当设置,便可显示字幕。本文为您介绍使用点播 SDK 时如何添加外挂字幕。

注意

该功能仅高级版或企业版支持。请确保您已购买高级版或企业版的 License,详见 License 包管理

前提条件

如果您通过 Vid 方式播放视频,需要准备字幕文件:

  • 如果您已有单独的字幕文件,可选择在视频点播控制台指定空间内的视频管理 > 视频详情页面上传字幕文件,如下图所示:
    Image
  • 如果您没有单独的字幕文件,可通过视频点播媒体处理服务生成字幕文件,具体请见生成和使用字幕

开启外挂字幕功能

参考以下示例代码开启外挂字幕功能:

// 开启外挂字幕
Future<void> setSubtitleEnabled(bool enabled) // prepare 之前调用

设置字幕源

点播 SDK 支持以下两种方式设置字幕源。您需根据实际情况选择。

使用 Vid + SubtitleToken 方式

使用 Vid + SubtitleToken 方式设置字幕源的示例代码如下:

说明

您可在应用服务端通过视频点播服务端 SDK 签发字幕鉴权 Token

// 设置  Vid 字幕源
Future<void> setSubtitleAuthToken(String subtitleAuthToken)

使用 DirectURL 方式

使用 DirectURL 方式设置字幕源的示例代码如下:

// 设置  DirectURL 字幕源
// createPlayer 之后,prepare 之前调用
Future<void> setSubtitles(List<TTSubtitle> subtitles)

控制字幕

开启/关闭字幕输出

参考以下示例代码在起播时或者播放过程中控制开启或者关闭字幕输出:

// 开启或者关闭字幕
// createPlayer 之后调用
Future<void> setSubtitleShow(bool enabled)

切换字幕

参考以下示例代码在起播时或者播放过程中切换字幕:

// 切换字幕
// createPlayer 之后调用
Future<void> setSelectedSubtitle(int subtitleId); 

设置字幕回调

参考以下示例代码接收字幕回调。设置字幕回调前需要先调用 setSubtitleShow(true) 开启字幕显示。

// vid + subTitleToken 播放,字幕列表信息回调
Future<void> Function(bool success, List<TTSubtitle>? subtitles, TTError? error)? onSubtitlesFetched;

// 字幕文件加载结果回调
Future<void> Function(bool success)? onSubtitleFileLoadResult;

// 字幕语言切换回调
Future<void> Function(bool success, int subtitleId)? onSubtitleSelected;

// 字幕信息回调
Future<void> Function(String? content, double pts, double duration)? onSubtitleShow;

下载视频

SDK 支持下载功能。用户可在有网络的条件下将视频下载至本地,随后在无网络的环境下观看。SDK 支持下载 DirectUrl 视频源和 Vid 视频源,并提供开始、暂停、恢复、删除等控制下载任务的方法。

初始化下载功能

说明

需要特别注意的是,初始化代码的时序对下载功能是否能正常工作有直接影响:

  • 如果您需要下载 HLS 视频,需要在初始化 SDK 前额外开启 HLS 下载功能。此方法必须在 startWithConfiguration(<sdkConfig>) 方法之前调用。
  • 设置下载文件存储路径,需要在 startWithConfiguration(<sdkConfig>) 方法之前调用。
  • 其他下载配置则需要在 startWithConfiguration(<sdkConfig>) 方法之后调用。

示例代码如下:

// 开启 HLS 下载功能。可选,如业务中无需下载 HLS 视频,可跳过。
TTVideoEngineDownloadTaskManager.enableHlsProxy(true);

// 必填,设置下载文件存储路径    
String platformDir;
if (Platform.isIOS) {
    platformDir = (await getApplicationDocumentsDirectory()).path;
} else {
    platformDir = (await getDownloadsDirectory())!.path;
}
platformDir = "$platformDir/xxxx";
TTVideoEngineDownloadTaskManager.setDownloadDirectory(docDir);

// 初始化 SDK    
FlutterTTSDKManager.startWithConfiguration(sdkConfig);

// 选填,设置最大并发下载数,默认值为 1        
TTVideoEngineDownloadTaskManager.setMaxDownloadOperationCount(3); 

// 选填,设置空闲磁盘空间大小的限制,默认值 1G
TTVideoEngineDownloadTaskManager.setLimitFreeDiskSize(1024 * 1024 * 1024); 

// 默认支持缓存最多 50 个视频。如业务超出此限制,需进行以下设置
TTVideoEngineDownloadTaskManager.setLimitFreeDiskCount(500);

// 加载所有预加载任务
TTVideoEngineDownloadTaskManager.loadAllTask();

创建下载任务

SDK 支持播放 DirectUrl 视频源和 Vid 视频源。与之对应,SDK 也提供了不同数据源的下载能力。

创建 DirectUrl 视频源下载任务

// 传入 urls、cacheKey、videoId,其中 urls 和 cacheKey 必填,cacheKey 需和视频源一一对应
TTVideoEngineDownloadURLTask task = TTVideoEngineDownloadURLTask(urls: <urls>, cacheKey: <cachekey>, videoId: <videoId>);
task.resume();

创建 Vid 视频源下载任务

// 传入 videoId、playAuthToken 和目标清晰度
TTVideoEngineDownloadVidTask task = TTVideoEngineDownloadVidTask(
                            videoId: <videoId>,
                            playAuthToken: <playAuthToken>,
                            resolution: <resolution>);
task.resume();

控制下载任务

通过以下方法控制单个下载任务:

// 开始/恢复单个下载任务。
// 支持断点续传。
[task resume];

// 暂停单个下载任务,支持断点续传。
[task suspend];

// 删除单个下载任务。
// 下载任务被删除后,任务会停止,同时 TTVideoEngineDownloadTaskManager 将不再管理这个任务。
[task invalidateAndCancel];

通过以下方法控制所有下载任务:

// 开始/恢复所有下载任务
TTVideoEngineDownloadTaskManager.resumeAllTask();

// 暂停所有下载任务
TTVideoEngineDownloadTaskManager.suspendAllTask();

// 删除所有下载任务
TTVideoEngineDownloadTaskManager.removeAllTask();

设置监听

/**
 * 下载任务完成回调。
 * @param task 当前下载任务。
 * @param error 错误。error 为 null 则为下载任务成功,否则为下载任务失败。
 */
TTVideoEngineDownloadTaskManager.onComplete = (TTVideoEngineDownloadTask task, TTError? error) {
  print('Download-onComplete: $task, $error');
};

/**
 * 下载任务进度更新回调。
 * @param task 当前下载任务。
 *             - downloadTask.countOfBytesReceived 当前下载任务已下载的数据总量(HLS 不适用,见下方注意点)
 *             - downloadTask.countOfBytesExpectedToReceive 当前下载任务需要下载的总数据量(HLS 不适用,见下方注意点)
 *             - progress 当前下载任务进度 0.0~1.0
 */
TTVideoEngineDownloadTaskManager.onProgress = (TTVideoEngineDownloadTask task, double progress) {
  print('Download-onProgress: $task, $progress');
};

/**
 * 下载任务开始/恢复回调。
 * @param downloadTask 当前下载任务。
 * @param  fileOffset 已下载的数据量。
 * @param  expectedTotalBytes 该任务要下载的总数据量。
 */
TTVideoEngineDownloadTaskManager.onResume = (TTVideoEngineDownloadTask task, int fileOffset, int expectedTotalBytes) {
  print('Download-onResume: $task, $fileOffset, $expectedTotalBytes');
};

/**
 * 下载任务状态变更回调。
 * @param task 当前下载任务。
 * @param state 当前下载任务状态:
 *              - init(0):初始化。
 *              - waiting(1): 等待中。
 *              - running(2): 运行中。
 *              - suspended(3): 暂停。
 *              - canceling(4): 正在取消。
 *              - completed(5): 完成。
 */ 
TTVideoEngineDownloadTaskManager.onStateChanged = (TTVideoEngineDownloadTask task, TTVideoEngineDownloadState state) {
  print('Download-onStateChanged: $task, $state');
};

说明

如果下载的媒体类型为 HLS(M3U8),SDK 无法获知整个视频的文件大小, 回调中的 countOfBytesReceivedcountOfBytesExpectedToReceive 数值并不准确。 因此,对于 HLS(M3U8) 您仅可以通过 task.progress 获取下载的进度。

播放视频

SDK 内部已处理下载缓存与播放的联动关系。SDK 会优先播放已经下载的视频,即使它们尚未完全下载完成,因此您播放时无需额外设置。

播放 DirectUrl 视频源

参考以下示例代码播放 DirectUrl 视频源:

// 设置source前,开启离线播放已下载视频
player.enablePlayCachedSource();

// 注意 cacheKey 与下载时使用的 cacheKey 一致
TTVideoEngineUrlSource source = TTVideoEngineUrlSource.initWithURLS(<urls>, <cacheKey>);
player.setMediaSource(source);

播放 Vid 视频源

参考以下示例代码播放 Vid 视频源:

// 设置 source 前,开启离线播放已下载视频
player.enablePlayCachedSource();

// 注意 resoluton 与下载时使用的 resolution 一致
TTVideoEngineVidSource source =
        TTVideoEngineVidSource.init(vid: <vid>, playAuthToken: <playAuthToken>, resolution: <resolutionType>);
player.setMediaSource(source);