本文为您介绍如何使用 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 包管理。
实现自定义预加载的步骤如下:
构造播放源并添加预加载任务。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);
取消预加载任务:
// 取消全部预加载任务 TTVideoEnginePreload.cancelAllTask(); // 根据key取消一个预加载任务,key为创建预加载任务使用的cacheKey TTVideoEnginePreload.cancelTaskByKey(Key);
监听预加载任务状态:
// 对已添加的预加载任务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'); };
注意
该功能仅 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; });