自适应码流(Adaptive Bitrate Streaming, ABR)播放是指在播放过程中根据用户的网络状况动态地、无缝地切换到最合适的清晰度,从而在保障视频流畅播放的同时,为用户提供最佳的观看体验。播放器 SDK 支持以下两种视频源的 ABR 播放:
本文指导您以 DirectUrl 模式播放标准协议的 HLS Master M3U8 视频。
在集成 ABR 播放功能前,请确保您已完成以下操作:
获取 License:ABR 播放为增值功能。请确保您的 License 已包含 ABR 播放功能,详细步骤请见 License 管理。
集成高级版 SDK 和 ABR 模块:参考集成 SDK 文档集成 1.47.2.8 或之后版本的高级版 SDK。
def ttsdk_version = "1.47.3.6" implementation "com.bytedanceapi:ttsdk-player_premium:$ttsdk_version" implementation "com.bytedanceapi:ttsdk-ttabr:$ttsdk_version"
检查 Master M3U8 文件:请务必确保您的 Master M3U8 文件中,每个 #EXT-X-STREAM-INF 标签内都包含 "AVERAGE-BANDWIDTH" 属性。SDK 的 ABR 策略强依赖此属性来评估网络与码率的匹配度并执行自动切换。缺少此属性将导致 ABR 功能失效。示例:
#EXT-X-STREAM-INF:BANDWIDTH=2628000,AVERAGE-BANDWIDTH=2500000,RESOLUTION=... /path/to/1080p.m3u8
在创建播放器实例后、调用 play() 之前,您需要开启网络速度探测,并设置一系列 Option 来启用 Master M3U8 的 ABR 功能。
// 1. 初始化网络速度探测器,为 ABR 决策提供数据支持 TTVideoEngine.setIntValue( DataLoaderHelper.DATALOADER_KEY_INT_NEED_SPEED_TEST_BY_TIMEINTERNAL, 1); TTVideoEngine.startSpeedPredictor(TTVideoEngine.TESTSPEED_HECNET, 500, 1, 100); // 2. 为播放器实例开启 Master M3U8 ABR 相关配置 // 开启 Master M3U8 ABR 功能 videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_MASTER_M3U8_ABR, 1); // 开启针对 Master M3U8 的优化 videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_MASTER_M3U8_OPTIMIZE, 1); // 关闭旧版 ABR 策略,避免冲突 videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_GEAR_STRATEGY, 0); // 3. (可选) 设置显示尺寸以优化选档 // 设置这些参数可以帮助 ABR 策略在码率相近时,优先选择清晰度更匹配当前显示区域的流 videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_PLAYER_DISPLAY_WIDTH, displayWidth); videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_PLAYER_DISPLAY_HEIGHT, displayHeight); videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_DEVICE_SCREEN_WIDTH, screenWidth); videoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_DEVICE_SCREEN_HEIGHT, screenHeight);
播放 Master M3U8 视频时,您需要实现 TTVideoEnginePlayHLSChooseStreamCallback 接口,通过一个回调机制来决定起播时使用的码率。
private int mVideoStartupResolution = 720; // 期望的起播清晰度高度 private TTVideoEngineMasterPlaylist mMasterPlaylist; // 用于存储 M3U8 解析后的清晰度信息 private int mHlsVideoVariantIndex = -1; // 存储我们选择的起播清晰度索引 videoEngine.setPlayerHLSChooseStreamCallback(new TTVideoEnginePlayHLSChooseStreamCallback() { /** * 当播放器成功解析 Master M3U8 文件后,会通过此回调返回所有可用的流信息。 */ @Override public void streamInfos(TTVideoEngineMasterPlaylist ttVideoEngineMasterPlaylist) { if (ttVideoEngineMasterPlaylist == null || ttVideoEngineMasterPlaylist.variantStreams == null) { return; } mMasterPlaylist = ttVideoEngineMasterPlaylist; // 示例:遍历所有清晰度,查找清晰度最接近 720p 的流作为起播清晰度 for (int i = 0; i < mMasterPlaylist.variantStreams.length; i++) { TTVideoEngineVariantStream videoVariant = mMasterPlaylist.variantStreams[i]; // 清晰度格式通常为 "1280x720" if (videoVariant.resolution != null && videoVariant.resolution.contains(String.valueOf(mVideoStartupResolution))) { mHlsVideoVariantIndex = i; break; // 找到后即退出 } } // 如果没有找到匹配的,默认使用第一个(通常是码率最低的)以保证快速起播 if (mHlsVideoVariantIndex == -1) { mHlsVideoVariantIndex = 0; } } /** * 在 streamInfos 回调之后,播放器会调用此方法,询问您最终决定使用哪个清晰度起播。 * 您需要返回在 streamInfos 中选定的清晰度的 bandwidth。 */ @Override public int chooseVariantBandWidth() { if (mMasterPlaylist == null || mMasterPlaylist.variantStreams == null || mHlsVideoVariantIndex < 0 || mHlsVideoVariantIndex >= mMasterPlaylist.variantStreams.length) { return -1; // 返回 -1 表示出现异常,播放器将使用默认策略(通常是码率最高的) } TTVideoEngineVariantStream selectedStream = mMasterPlaylist.variantStreams[mHlsVideoVariantIndex]; if (selectedStream == null) { return -1; } // 返回选定清晰度的 bandwidth,播放器将使用此码率对应的流进行起播 return selectedStream.bandwidth; } });
完成以上所有配置后,将 Master M3U8 URL 设置为播放源并调用 play()。
// 1. 准备您的播放信息 final String masterM3u8Url = "http://example.com/path/to/master.m3u8"; // 为此 URL 源提供一个唯一的 Vid。此 Vid 将作为该播放源在 SDK 内部(如预加载、缓存、数据统计等模块)的唯一标识,即使播放源是 URL,提供稳定唯一的 vid 也有助于 SDK 更好地管理播放会话和优化性能。 // 可以是您自己的视频管理系统中的唯一标识,也可以在 App 层自行生成一个 ID final String vid = "your_unique_video_id_for_this_url"; // 使用 URL 的 MD5 值作为缓存 Key,确保唯一性。 final String cacheKey = TTVideoEngine.computeMD5(masterM3u8Url); // 2. 构建 DirectUrlSource 播放源对象 StrategySource directUrlSource = new DirectUrlSource.Builder() .setVid(vid) .addItem(new DirectUrlSource.UrlItem.Builder() .setUrl(masterM3u8Url) .setCacheKey(cacheKey) .build()) .build(); // 3. 为播放器设置播放源 videoEngine.setStrategySource(directUrlSource); // 4. 开始播放 videoEngine.play();