You need to enable JavaScript to run this app.
导航
进阶功能
最近更新时间:2024.10.17 11:29:26首次发布时间:2024.10.17 11:29:26

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

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

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

注意

该功能仅 Android 支持。

注意

该功能仅高级版或企业版支持。请确保您已购买高级版或企业版的 License 并添加高级版 SDK 依赖,详见 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 并添加高级版 SDK 依赖,详见 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 - 音轨选择,返回音频renition的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 renition in _playlist!.renditions!) {
          if (renition.variantIndex != variantIndex) {
            continue;
          }
          if (renition.language == 'en') {
            print('HLS音频起播档位选择, renition.language=${renition.language}, renition.infoId-${renition.infoId}');
            return renition.infoId;
          }
        }
        return -1;
      },
      switchHlsVideoBitrate: (int bitrate) {
        print("HLS选择档位完成 最终bitrate = $bitrate");
      },
    );

播放中档位选择

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

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

预加载档位选择

// 方法定义在 TTVideoEnginePreload
  /* 
    master-m3u8起播前档位选择
    getHlsStreamInfos - 档位回调
    selectHlsVideoStream - 视频档位选择, 返回视频stream的bandwidth
    selectHlsRendition - 音轨选择,返回音频renition的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;
    });