You need to enable JavaScript to run this app.
视频点播

视频点播

复制全文
进阶功能
多路流管理
复制全文
多路流管理

对于包含多种清晰度、多语言音轨或多语种字幕的视频,播放器 SDK 支持在播放的各个阶段进行精确的管理和切换。本文详细介绍多路流的实现方案,并指导您如何完成集成,以及如何优化切换体验。

方案概览

播放器 SDK 支持自研协议标准协议两大类多路流方案,您可以根据业务场景和媒资来源灵活选择。

协议类型

播放模式

核心原理

优点

缺点

适用场景

自研协议

Vid 模式

客户端通过 Vid 请求,由视频点播服务端智能下发包含所有可用清晰度的 VideoModel。

接入最简单,且安全性强。客户端逻辑清晰,服务端自动处理降级和媒资关联,支持帧对齐平滑切换。

依赖视频点播服务,对音轨/字幕的底层控制能力有限。

适用于媒资全部托管在火山引擎视频点播服务的场景。

VideoModel 模式

由您的业务服务端自行构造或从点播服务获取完整的 VideoModel,并下发给客户端。

性能最优,减少了一次客户端到点播服务的网络请求,首帧更快。对多路流的管理方式与 Vid 模式一致。

需自行实现构造 VideoModel 的逻辑,复杂度稍高。

对首帧性能有极致要求的场景,例如短视频信息流。

标准协议

HLS (Master M3U8)

客户端直接播放标准的 Master M3U8 文件。SDK 解析文件后,通过底层回调和 Option 设置,允许您对视频流、音轨、字幕进行精细化控制。

兼容性最强,适用于任意来源的 HLS 视频流。提供了最底层的控制能力,灵活性最高。

客户端实现逻辑最复杂,需要自行处理流信息的遍历、决策和切换。

需要播放第三方 HLS 视频流,或需要对音轨、字幕进行精细化管理的场景。

DASH

建设中,敬请期待

Vid/VideoModel 模式

对于客户端的多清晰度管理,Vid 模式和 VideoModel 模式共享一套简单、直观的 API。

前置准备

在进行多路流相关开发前,请确保已完成以下准备工作:

  1. 生成多清晰度视频且确保业务服务端正确下发视频播放信息:
    • 对于 Vid 模式:
      • 您必须通过视频点播媒体处理服务转码生成多种清晰度的视频流,详见音视频转码
      • 您的业务服务端在为客户端签发 PlayAuthToken 时,可不指定 Definition 参数。视频点播服务在响应播放请求时,将默认返回该视频所有可用清晰度的播放地址。
    • 对于 VideoModel 模式:视频数据来自火山引擎视频点播服务,也可以来自第三方服务或自定义数据。详见构造 VideoModel 播放源
  2. 完成 SDK 基础集成:请确保您已参考集成 SDK快速开始文档,完成了 SDK 的初始化、创建播放器实例、设置播放源等基础步骤。

获取可用清晰度列表

在播放器 SDK 通过 videoEngine:fetchedVideoModel: 代理回调返回视频信息后,通过 supportedResolutionTypes 属性获取所有可用的清晰度。

// 实现 TTVideoEngineDelegate 的代理方法
- (void)videoEngine:(TTVideoEngine *)videoEngine fetchedVideoModel:(TTVideoEngineModel *)videoModel {
    // 获取清晰度枚举的 NSNumber 数组,用于构建 UI 上的选择列表
    NSArray<NSNumber *> *allResolutions = [self.engine supportedResolutionTypes];
    
    // 可以在此处根据 allResolutions 更新您的清晰度选择 UI
}

设置起播清晰度

在调用 play 方法前设置 configResolution:,即可指定视频的起播清晰度。如果您设置的清晰度在 supportedResolutionTypes 列表中不存在,SDK 会自动选择一个当前已支持的、不高于您设定值的最接近档位进行播放。

说明

如果您同时使用了起播选档功能,SDK 会自动选择最佳码率起播,您无需再手动调用 configResolution 设置起播清晰度。

[self.engine configResolution:TTVideoEngineResolutionTypeFullHD];

播放中切换清晰度

当用户在 UI 上选择新的清晰度后,调用 configResolution:withCompletion: 进行切换,并在 completion 回调中处理切换结果。

// 假设 allResolutions 是您在 fetchedVideoModel 回调中获取的可用清晰度列表
// 假设用户点击了列表中的第一项作为目标清晰度
TTVideoEngineResolutionType targetResolution = [[allResolutions objectAtIndex:0] integerValue]; 

// 调用接口发起切换,并设置回调 block
[self.engine configResolution:targetResolution withCompletion:^(BOOL success, NSError * _Nullable err, TTVideoEngineResolutionType completeResolution) {
    
    // 注意:该回调可能在非主线程触发,任何UI更新操作都需要 dispatch 到主线程
    dispatch_async(dispatch_get_main_queue(), ^{
        if (success) {
            // 切换成功,completeResolution 即为当前实际播放的清晰度
            NSLog(@"清晰度切换成功,当前清晰度: %ld", (long)completeResolution);
            // 可以在此更新 UI 状态
        } else {
            // 切换失败,可以从 NSError 对象中获取详细信息
            // err.code 为 -1 表示因播放器状态异常导致切换请求未被执行
            // 其他错误码含义请参考官网文档
            NSLog(@"清晰度切换失败,错误码:%ld, 错误信息: %@", (long)err.code, err.localizedDescription);
        }
    });
}];

获取当前清晰度

在播放过程中的任何时刻,您都可以通过访问 currentResolution 属性来获取当前正在播放的清晰度。

// 同步获取当前正在播放的清晰度
TTVideoEngineResolutionType currentType = self.engine.currentResolution;
NSLog(@"当前播放清晰度为: %ld", (long)currentType);

外挂多语言字幕(仅 Vid 模式)

Vid 模式下,您可以通过外挂的方式为视频添加和管理多语言字幕。字幕文件与视频 Vid 在视频点播服务端进行绑定。客户端通过 VidPlayAuthToken 请求播放,再通过 SubtitleToken 请求字幕信息。实现流程如下:

  1. 将字幕上传到视频点播服务并绑定到 Vid,或直接通过视频点播服务生成字幕。详细操作步骤,请见视频字幕
  2. 服务端为客户端签发 PlayAuthTokenSubtitleToken
  3. 客户端使用 Vid 和 Token 播放,SDK 内部会自动拉取与该 Vid 关联的所有字幕信息列表。

详细集成步骤请参见添加外挂字幕

HLS Master M3U8 模式

对于标准的 Master M3U8 播放源,播放器 SDK 提供了精细的控制能力,允许开发者在播放生命周期的不同阶段介入,精确选择要使用的视频流(清晰度)和音频流(音轨)。

起播时选择清晰度与音轨

通过设置 masterPlaylistDelegate,您可以在播放器 SDK 解析完 M3U8 文件后、开始下载媒体数据前,通过代理方法返回您期望的视频流和音轨的索引,从而控制起播。具体工作流程如下:

  1. 设置代理:为播放器实例设置 masterPlaylistDelegate 并遵循 TTVideoEngineMasterPlaylistDelegate 协议。

  2. 接收流信息:当 M3U8 解析完成后,SDK 触发 onMasterPlaylist 回调。您可以在此获取并保存包含所有视频流 variantStreams 和音频流 renditionsmasterPlaylist 对象。

    // 遵循 TTVideoEngineMasterPlaylistDelegate 协议
    // @interface YourViewController () <TTVideoEngineMasterPlaylistDelegate>
    
    // 设置代理
    self.videoEngine.masterPlaylistDelegate = self;
    
    #pragma mark - TTVideoEngineMasterPlaylistDelegate
    /**
     * M3U8 解析完成的回调。
     * 在此处保存 masterPlaylist 对象,以便在播放中切换清晰度或音轨时使用。
     */
    - (void)videoEngine:(TTVideoEngine *)videoEngine onMasterPlaylist:(TTVideoEngineMasterPlaylist *)masterPlaylist {
        self.masterPlaylist = masterPlaylist; 
        NSLog(@"M3U8 解析完成,可用视频流为:%ld", (long)masterPlaylist.variantStreams.count);
    }
    
  3. 返回决策索引:通过 indexOfVariantOnPlayMasterPlaylistindexOfRenditionOnPlayMasterPlaylist 返回您选定的视频流和音频流的索引。以下示例代码展示了以 720p 分辨率和英文音轨起播:

    // 返回起播的视频流的序号,-1 表示自动选择
    - (int)videoEngine:(TTVideoEngine *)videoEngine indexOfVariantOnPlayMasterPlaylist:(TTVideoEngineMasterPlaylist *)masterPlaylist {
        if (self.masterPlaylistPlayTargetIndex >= -1 && self.masterPlaylistPlayTargetIndex < (int)masterPlaylist.variantStreams.count) {
            return self.masterPlaylistPlayTargetIndex;
        }
        NSLog(@"清晰度选择错误:当前视频支持: -1 ~ %d,将播放默认清晰度", (int)(masterPlaylist.variantStreams.count - 1));
        return -1;
    }
    
    // 返回起播的音频流的 streamId,-1 表示自动选择
    - (int)videoEngine:(TTVideoEngine *)videoEngine indexOfRenditionOnPlayMasterPlaylist:(TTVideoEngineMasterPlaylist *)masterPlaylist {
        if (self.masterPlaylistAudioTrackIndex == -1) {
            return -1;
        }
        
        if (self.masterPlaylistAudioTrackIndex >= 0 && self.masterPlaylistAudioTrackIndex < (int)masterPlaylist.renditions.count) {
            return [[self.masterPlaylist.renditions objectAtIndex:self.masterPlaylistAudioTrackIndex].inStreamId intValue];;
        }
        NSLog(@"清晰度选择错误(rendition):当前视频支持: -1 ~ %d,将播放默认 rendition", (int)(masterPlaylist.renditions.count - 1));
        return -1;
    }
    

播放中切换清晰度与音轨

切换视频流(按 Bandwidth)

要切换视频清晰度,您需要获取目标流的带宽值,并调用 setIntOption 方法,将 PLAYER_OPTION_SET_MASTER_M3U8_VIDEO_BANDWIDTH 作为键,带宽值作为值传入。

NSString* inputBitrate = [_inputBitrateTextView.text stringByTrim];
// 通过 setOptionForKey 切换视频流
[self.player.videoEngine setOptionForKey:VEKKeySetMasterm3u8VideoBandwidth_NSInteger value:@(inputBitrate.intValue)];

切换音频流(按 Info ID)

要切换音轨,您需要获取目标音轨的 InfoId,并调用 setOptionForKey:value: 方法,将 VEKKeyPlayerSwitchAudioInfoId_NSInteger 作为键,InfoId 作为值传入。

NSString* inputStreamId = [_inputStreamIdTextView.text stringByTrim];
// 通过 setOptionForKey 切换音频流
[self.player.videoEngine setOptionForKey:VEKKeyPlayerSwitchAudioInfoId_NSInteger value:@(inputStreamId.intValue)];

预加载时选择清晰度与音轨

如果您使用 SDK 提供的预加载策略,同样可以介入并指定预加载哪些流。通过设置 TTVideoEnginePreloadDelegate,您可以在预加载任务解析完 M3U8 后,通过代理方法返回要预加载的流的索引。

// 设置预加载代理
// @interface YourAppDelegate () <TTVideoEnginePreloadDelegate>
[TTVideoEngine ls_setPreloadDelegate:self];

#pragma mark - TTVideoEnginePreloadDelegate

// 返回预加载的视频流的序号,-1 表示自动选择
- (int)indexOfVariantOnPreloadMasterPlaylist:(TTVideoEngineMasterPlaylist *)masterPlaylist {
    if (self.masterPlaylistPreloadTargetIndex >= -1 && self.masterPlaylistPreloadTargetIndex < (int)masterPlaylist.variantStreams.count) {
        return self.masterPlaylistPreloadTargetIndex;
    }
    NSLog(@"清晰度选择错误:当前视频支持: -1 ~ %d,将预加载默认清晰度", (int)(masterPlaylist.variantStreams.count - 1));
    return -1;
}

// 返回预加载的音频流的序号,-1 表示自动选择
- (int)indexOfRendtionOnPreloadMasterPlaylist:(TTVideoEngineMasterPlaylist *)masterPlaylist {
    if (masterPlaylist.renditions.count == 0) {
        return -1;
    }
    
    if (self.masterPlaylistPreloadTargetIndex >= -1 && self.masterPlaylistPreloadTargetIndex < (int)masterPlaylist.renditions.count) {
        return self.masterPlaylistPreloadTargetIndex;
    }    
  NSLog(@"清晰度选择错误(rendition):当前视频支持: -1 ~ %d,将预加载默认 rendition", (int)(masterPlaylist.renditions.count - 1));
    return -1;
}

清晰度切换优化:平滑切换

清晰度平滑切换(或称无缝切换)是指播放器在不同清晰度之间切换时,画面过渡平滑、无黑屏、无明显卡顿的技术。

前置准备

该功能依赖于视频源本身是帧对齐的

  • 对于火山引擎视频点播服务转码生成的 MP4 和 HLS 视频,默认已支持帧对齐。
  • 对于第三方视频源,您需要确保您的媒资也经过了帧对齐处理。

说明

如需了解如何转码生成帧对齐视频以及在 DirectUrl 模式下开启平滑切换功能,可提交工单联系火山引擎技术支持。

开启平滑切换

通过 setIntOption 方法开启相应的平滑切换开关。

// HLS 播放源平滑切换
[self.videoEngine setOptionForKey:VEKKeyPlayerHLSSeamlessSwitchEnable_BOOL value:@(YES)];
[self.videoEngine setOptionForKey:VEKKeyMasterm3u8OptimizeEnable_BOOL value:@(YES)];

// MP4 播放源平滑切换
[self.videoEngine setOptionForKey:VEKKeyPlayerBashEnabled_BOOL value:@(YES)];
[self.videoEngine setOptionForKey:VEKeyPlayerSegmentFormatFlag value:@(TTVideoEngineDashSegmentFlagFormatMp4 | TTVideoEngineDashSegmentFlagFormatFMP4)];

参考信息

清晰度枚举 TTVideoEngineResolutionType

枚举值

对应清晰度

视频描述

TTVideoEngineResolutionTypeSD

360P

标清

TTVideoEngineResolutionTypeHD

480P

高清

TTVideoEngineResolutionTypeFullHD

720P

超清

TTVideoEngineResolutionType1080P

1080P

1080P

TTVideoEngineResolutionType2K

2K

2K

TTVideoEngineResolutionType4K

4K

4K

TTVideoEngineResolutionTypeAuto

自动

自动选择

最近更新时间:2025.12.01 10:40:07
这个页面对您有帮助吗?
有用
有用
无用
无用