You need to enable JavaScript to run this app.
导航
自研协议 ABR 播放
最近更新时间:2025.09.12 15:52:09首次发布时间:2025.09.03 17:56:16
复制全文
我的收藏
有用
有用
无用
无用

自适应码流(Adaptive Bitrate Streaming, ABR)播放是指在播放过程中根据用户的网络状况动态地、无缝地切换到最合适的清晰度,从而在保障视频流畅播放的同时,为用户提供最佳的观看体验。播放器 SDK 支持以下两种视频源的 ABR 播放:

  • Vid 模式:适用于播放火山引擎点播服务生成的自研协议 DASH 和 HLS 视频。
  • DirectUrl 模式:适用于播放标准协议的 HLS Master M3U8 视频。URL 可来自火山引擎或第三方服务。

本文指导您以 Vid 播放模式实现火山引擎自研协议 DASH 和 HLS 视频的 ABR 播放。

前提条件

在集成 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"
    
  • 完成基础的 SDK 初始化:参考集成 SDK快速开始文档完成项目的基本配置和 SDK 初始化。

  • 完成自适应码流转码:请确保您已通过火山引擎视频点播的自适应码流转码功能生成了 DASH 或 HLS 格式的视频流。详细信息,请参见自适应码流转码

核心接入流程

步骤 1:初始化 ABR 策略

Application 中,除了 SDK 的常规初始化外,还需要初始化 ABR 策略。

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        initVodSDK();
    }
}


public static void initVodSDK() {
    // 1. 初始化 SDK
    Env.init(/*省略*/);
    // 2. 初始化 ABR 全局配置
    TTVideoABRStrategy.init();
    // 3. (可选)初始化预加载策略。若您使用自定义预加载,则无需调用
    initPreloadStrategy();
    // 4. 初始化预渲染策略
    initPreRenderStrategy();
}

步骤 2:配置 ABR 策略

为播放器实例 TTVideoEngine 设置 ABR 配置 TTVideoABRConfig。具体步骤如下:

  1. 创建一个 TTVideoABRConfig 对象定义 ABR 的行为。您可以根据不同的业务场景(如短视频、中视频、全屏播放)和网络条件(Wi-Fi、移动网络)来配置不同的显示尺寸和清晰度上限。

    public static TTVideoABRConfig createABRConfig() {
        TTVideoABRConfig abrConfig = new TTVideoABRConfig();
        // 设置当前设备屏幕宽高,用于 ABR 算法计算最佳清晰度
        abrConfig.screenWidth = screenWidth;
        abrConfig.screenHeight = screenHeight;
        // 设置默认清晰度,在无网络测速信息时使用
        abrConfig.defaultResolution = Resolution.High; // 480P
        // 设置 Wi-Fi 网络下的最高清晰度
        abrConfig.wifiMaxResolution = Resolution.ExtremelyHigh; // 1080P
        // 设置移动网络下的最高清晰度
        abrConfig.mobileMaxResolution = Resolution.SuperHigh; // 720P
        
        // 根据业务场景设置视频的显示尺寸,以下为短视频场景示例
        abrConfig.displayWidth = Math.min(screenWidth, screenHeight);
        abrConfig.displayHeight = (int) (abrConfig.displayWidth / 9f * 16);
        
        /*
        // 示例:中视频场景
        abrConfig.displayWidth = Math.min(screenWidth, screenHeight);
        abrConfig.displayHeight = (int) (displaySizeConfig.displayWidth / 16f * 9);
        
        // 示例:横版全屏播放场景
        abrConfig.displayHeight = Math.min(screenWidth, screenHeight);
        abrConfig.displayWidth = (int) (abrConfig.displayHeight / 9f * 16);
        */
        return abrConfig;
    }
    
  2. 将 ABR 配置应用到播放器:在创建 TTVideoEngine 实例并设置 Vid 播放源后、首次调用 play() 方法前,调用 TTVideoABRStrategy.initEngine() 方法将 ABR 配置应用到播放器。

    if (mVideoEngine == null) {
        mVideoEngine = new TTVideoEngine(context);
        mVideoEngine.setIntOption(PLAYER_OPTION_USE_VIDEOMODEL_CACHE, 1);
        // 设置播放源,必须为 VidPlayAuthTokenSource
        mVideoEngine.setStrategySource(source);
        TTVideoABRStrategy.initEngine(mVideoEngine, createABRConfig());
    }
    mVideoEngine.play();
    

步骤 3:设置起播清晰度

为了在视频开始播放时选择最合适的清晰度,您需要实现一套逻辑来决定起播清晰度。以下是一个起播清晰度的决策逻辑示例:

  • 优先使用用户选择:如果用户之前手动选择过清晰度,则优先使用该选择。
  • 支持 ABR 则自动档:如果视频支持 ABR(即视频是 BASH 或 HLS 格式),则使用 Resolution.Auto,让 ABR 策略自动选择。
  • 不支持 ABR 则使用默认值:如果视频不支持 ABR,则根据预设的默认值 DEFAULT_RESOLUTION 选择一个最接近的可用清晰度。
// 定义默认的起播清晰度
public static final Resolution DEFAULT_RESOLUTION = Resolution.SuperHigh; // 720P

public static Resolution getStartPlayResolution(IVideoModel videoModel) {
    // 1. 优先使用用户已选择的清晰度
    Resolution userSelectedResolution = getUserSelectedResolution();
    if (userSelectedResolution == null) {
        if (videoModel != null && (videoModel.isSupportBash() || videoModel.isSupportHLSSeamlessSwitch())) {
            // 2. 如果视频支持 ABR,则设置为自动挡
            return Resolution.Auto;
        } else {
            // 3. 如果视频不支持 ABR,则根据默认值选择最接近的清晰度
            return BestResolution.findDefaultResolution(videoModel, DEFAULT_RESOLUTION);
        }
    }
    return userSelectedResolution;
}

步骤 4:应用起播清晰度

在播放器 onFetchedVideoInfo 回调中,调用步骤 3 中的方法获取起播清晰度,并配置给播放器。

// 在 onFetchedVideoInfo 回调中设置起播清晰度
if (mVideoEngine == null) {
    // ...  
    mVideoEngine.setVideoInfoListener(new VideoInfoListener() {
        @Override
        public boolean onFetchedVideoInfo(VideoModel videoModel) {
            Resolution startResolution = getStartPlayResolution(videoModel);
            mVideoEngine.configResolution(startResolution);
            return false;
        }
    });
}
mVideoEngine.play();

播放中的交互与监听

在播放过程中,您需要向用户展示可用的清晰度列表,并处理用户的手动切换操作。同时,您也可以在特定场景下(如全屏切换)动态更新 ABR 的配置。

更新 ABR 配置

如果播放过程中场景发生变化(例如,从列表页进入全屏播放),您可能需要更新 ABR 的配置以适应新的 View 大小或调整清晰度策略。调用 TTVideoABRStrategy.setABRConfig() 方法可以动态更新配置。

// 当播放场景变化时(如全屏切换),更新 ABR 配置
TTVideoABRStrategy.setABRConfig(mVideoEngine, newABRConfig);

获取并展示清晰度列表

在播放器 onFetchedVideoInfo 回调中获取到 VideoModel 之后,您可以获取当前视频支持的所有清晰度,并在 UI 上展示给用户。如果视频支持 ABR,建议在列表的开头添加“自动”选项。

List<Resolution> mResolutions = new ArrayList<>();

// 在 onFetchedVideoInfo 回调之后,获取支持的清晰度列表
Resolution[] supportedResolutions = mVideoEngine.supportedResolutionTypes();
if (supportedResolutions != null && supportedResolutions.length > 0) {
    VideoModel videoModel = mVideoEngine.getVideoModel();
    // 如果支持 ABR,在列表首位添加“自动”选项
    if (videoModel != null && (videoModel.isSupportBash() || videoModel.isSupportHLSSeamlessSwitch())) {
        mResolutions.add(Resolution.Auto);
    }
    for (Resolution r : supportedResolutions) {
        mResolutions.add(r);
    }
}
// 更新 UI 以展示清晰度列表

处理用户手动切换清晰度

当用户从清晰度列表中选择一个选项时,调用 mVideoEngine.configResolution() 方法来切换清晰度。同时,建议将用户的选择持久化存储,以便下次播放时使用。

public void setResolution(Resolution resolution) {
    if (mCurrentSelectedResolution == resolution) return;
    
    mCurrentSelectedResolution = resolution;
    mVideoEngine.configResolution(resolution);
    // 持久化用户选择,以便下次播放时使用
    setUserSelectedResolution(resolution);
}

监听清晰度变化

通过 VideoEngineCallbackonVideoStreamBitrateChanged 回调监听清晰度变化,包括 ABR 自动切换和用户手动切换两种情况。

// 记录用户选择的清晰度(手动选择或自动)
Resolution mCurrentSelectedResolution;

mVideoEngine.setVideoEngineCallback(new VideoEngineCallback() {
    @Override
    public void onVideoStreamBitrateChanged(Resolution newResolution, int bitrate) {
        if (mCurrentSelectedResolution == Resolution.Auto) {
            // 在自动模式下,ABR 会根据网络状况自动切换清晰度
            Log.d("VideoPlay", "[ABR] onVideoStreamBitrateChanged: auto switch to " + newResolution);
        } else {
            // 用户手动切换清晰度完成
            Log.d("VideoPlay", "[ABR] onVideoStreamBitrateChanged: user switch to " + newResolution);
        }
    }
});

获取当前播放清晰度

调用 mVideoEngine.getCurrentResolution() 可以获取当前正在播放的视频流的实际清晰度。注意,此方法不会返回 Resolution.Auto

// 获取当前正在播放的实际清晰度(非 Resolution.Auto)
Resolution currentResolution = mVideoEngine.getCurrentResolution();

进阶使用

结合自定义预加载

如果您使用的是自定义预加载逻辑,可以在创建预加载任务时,让 ABR 策略参与选择预加载的清晰度。

final PreloaderVidItem item = new PreloaderVidItem(vidSource, preloadSize);
item.setFetchEndListener((videoModel, error) -> {
    if (videoModel == null) {
        return;
    }
    Resolution resolution = getStartPlayResolution(videoModel);
    if (resolution == Resolution.Auto) {
        resolution = TTVideoABRStrategy.preloadSelect(videoModel, createABRConfig());
    }
    item.mResolution = resolution;
});

结合预加载策略

如果您使用 SDK 提供的预加载策略,可以通过设置 PreloadTaskFactory 来让 ABR 参与决策。

public static void initPreloadStrategy() { 
    // 1. 全局开启预加载策略,需要在主线程调用 
    TTVideoEngine.enableEngineStrategy(StrategyManager.STRATEGY_TYPE_PRELOAD, StrategyManager.STRATEGY_SCENE_SMALL_VIDEO); 

    // 2. 设置 PreloadTaskFactory,使用 ABR 选档结果作为预加载清晰度 
    StrategyManager.instance().setPreloadTaskFactory(new PreloadTaskFactory() { 
    
        @Override 
        public PreloaderVidItem createVidItem(VidPlayAuthTokenSource source, long preloadSize) { 
            final PreloaderVidItem item = PreloadTaskFactory.super.createVidItem(source, preloadSize); 
            // 同自定义预加载 VidPlayAuthTokenSource 的逻辑 
            item.setFetchEndListener((videoModel, error) -> { 
                if (videoModel == null) { 
                    return; 
                } 
                Resolution resolution = getStartPlayResolution(videoModel); 
                if (resolution == Resolution.Auto) { 
                    resolution = TTVideoABRStrategy.preloadSelect(videoModel, createABRConfig()); 
                } 
                item.mResolution = resolution; 
            }); 
            return item; 
        } 
    }); 
} 

结合预渲染策略

如果您使用 SDK 提供的预渲染策略,在创建用于预渲染的 TTVideoEngine 实例时,也需要像正常播放一样,为其初始化 ABR 配置。这样,当预渲染的播放器转为实际播放时,ABR 功能才能无缝衔接。

public static void initPreRenderStrategy() {
    // 开启预渲染策略
    TTVideoEngine.enableEngineStrategy(STRATEGY_TYPE_PRE_RENDER, STRATEGY_SCENE_SMALL_VIDEO);
    StrategyManager.instance().enableReleasePreRenderEngineInstanceByLRU(true);

    // 设置 EngineStrategyListener,在创建预渲染引擎时进行 ABR 初始化
    TTVideoEngine.setEngineStrategyListener(new EngineStrategyListener() {
        @Override
        public TTVideoEngine createPreRenderEngine(StrategySource strategySource) {
            TTVideoEngine videoEngine = new TTVideoEngine(context);
            videoEngine.setIntOption(PLAYER_OPTION_USE_VIDEOMODEL_CACHE, 1);
            videoEngine.setStrategySource(strategySource);
            
            // 关键步骤:为预渲染的播放器实例初始化 ABR
            TTVideoABRStrategy.initEngine(videoEngine, createABRConfig());
            
            // 设置起播清晰度,逻辑与正常播放时一致
            videoEngine.setVideoInfoListener(new VideoInfoListener() {
                @Override
                public boolean onFetchedVideoInfo(VideoModel videoModel) {
                    Resolution resolution = getStartPlayResolution(videoModel);
                    videoEngine.configResolution(resolution);
                    return false;
                }
            });
            
            return videoEngine;
        }
    });
}

当命中预渲染并转为正式播放时,需要正确同步清晰度状态。

public void play() {
    if (mVideoEngine == null) {
        TTVideoEngine preRenderEngine = TTVideoEngine.removePreRenderEngine(vid);
        if (preRenderEngine != null) {
            // 命中预渲染,预渲染的播放器已经设置清晰度,并且当前清晰度已经回调
            // 所以这里需要给 mCurrentSelectedResolution 和 mCurrentResolution 赋值。
            mVideoEngine = preRenderEngine;
            // 同步清晰度相关状态
            mCurrentSelectedResolution = getStartPlayResolution(mVideoEngine.getVideoModel());
            mCurrentResolution = mVideoEngine.getCurrentResolution();
        } else {
            // 未命中预渲染,按常规流程创建播放器
            // ...
        }
    }
    // ...
    mVideoEngine.play();
}