本章节为您介绍拉流基础功能的接入方法,根据文档提供的操作步骤进行配置,您可接入直播拉流播放控制能力。
已集成并初始化 iOS 拉流 SDK。详见集成 iOS 拉流 SDK 和初始化 iOS 拉流 SDK。
真机调试:由于 SDK 使用了大量 iOS 系统的音视频接口,这些接口在模拟器下可能会出现异常,推荐您使用真机进行代码调试。
本节为您详细介绍如何通过拉流 SDK 实现直播拉流播放控制的能力,包括但不限于创建播放器、初始化配置、事件监听、配置渲染 View、配置播放地址。
iOS 拉流 SDK 的播放器类为 TVLManager。您可以参考以下代码创建播放器。
// 创建播放器 TVLManager *livePlayer = [[TVLManager alloc] init];
说明
VeLivePlayerTypeOwn:自研播放器。调用 init 时,SDK 将创建该类型的播放器。您也可以调用 initWithType: 并传入 VeLivePlayerTypeOwn。画中画仅支持该类型,详见画中画。VeLivePlayerTypeSystem:系统播放器。如需使用该类型,必须调用 initWithType: 并传入 VeLivePlayerTypeSystem。播放 DRM 加密流时需使用该类型,详见 DRM 加密流播放。该类型仅支持 M3U8 格式的拉流地址。使用该类型初始化播放器后,不支持以下功能接入:
您可以通过 VeLivePlayerConfiguration 配置播放器的初始化参数,并调用 setConfig: 接口应用配置。请在调用 play 接口前完成播放器初始化配置。详细参数说明如下表所示。
| 参数 | 类型 | 说明 |
|---|---|---|
| enableSei | BOOL | 是否开启字符串 SEI 消息的解析。默认值为 NO。 |
| enableBinarySei | BOOL | 是否开启二进制 SEI 消息的解析。默认值为 NO。开启后,播放器将接收二进制 SEI 消息,且不再触发字符串 SEI 消息回调。 |
| enableHardwareDecode | BOOL | 是否开启硬件解码功能。默认值为 YES。开启后,如果出现硬件解码启动失败或硬件解码失败的情况,播放器会自动切换为软解码。 |
| networkTimeoutMs | NSInteger | 网络超时时间,单位为 ms。默认值为 5000。播放器发起网络请求后,如果在该时间内未收到服务器响应,则认为网络请求失败。 |
| retryIntervalTimeMs | NSInteger | 重试时间间隔,单位为 ms。默认值为 5000。在播放直播时,如果出现网络异常等导致播放中断,播放器会尝试进行重试。 |
| retryMaxCount | NSInteger | 在网络连接错误的情况下,播放器的最大重试次数。默认值为 5。如果取值为 0,播放器将关闭内部重试。 |
| stallRetryTimeout | NSInteger | 卡顿超时停止重试阈值。当卡顿时长超过该阈值时,播放器将不再进行重试。单位为 ms。默认值为 10000,即 10 秒。 |
enableLiveDNS | BOOL | 是否开启本地 DNS 预解析。默认值为 警告 如果本地 DNS 预解析出现异常,可能会影响播放器的正常使用。 |
| enableStatisticsCallback | BOOL | 是否开启播放信息周期性回调。默认值为 NO。 |
| statisticsCallbackInterval | NSInteger | 播放信息周期性回调的时间间隔,单位为 s。默认值为 5。 |
您可以参考以下代码示例进行初始化配置。
// 创建配置 VeLivePlayerConfiguration *config = [[VeLivePlayerConfiguration alloc] init]; // 打开周期性回调 config.enableStatisticsCallback = YES; // 打开 Local DNS 预解析 config.enableLiveDNS = YES; // 初始化播放器 [self.livePlayer setConfig:config];
您可以调用 setObserver: 接口设置播放器回调,并通过 VeLivePlayerObserver 监听播放器状态、错误信息、音视频首帧事件以及周期性统计数据等。请在调用 play 接口前完成配置。代码示例如下所示。
@interface VeLivePullViewController () <VeLivePlayerObserver> @end // 配置播放器回调 [self.livePlayer setObserver:self];
- (void)onError:(TVLManager *)player error:(VeLivePlayerError *)error { // 错误回调 } - (void)onInfo:(TVLManager *)player info:(VeLivePlayerError *)info { // 播放器信息回调 } - (void)onFirstVideoFrameRender:(TVLManager *)player isFirstFrame:(BOOL)isFirstFrame { // 视频首帧回调 } - (void)onFirstAudioFrameRender:(TVLManager *)player isFirstFrame:(BOOL)isFirstFrame { // 音频首帧回调 } - (void)onStallStart:(TVLManager *)player { // 卡顿开始回调 } - (void)onStallEnd:(TVLManager *)player { // 卡顿结束回调 } - (void)onVideoRenderStall:(TVLManager *)player stallTime:(int64_t)stallTime { // 视频卡顿回调 } - (void)onAudioRenderStall:(TVLManager *)player stallTime:(int64_t)stallTime { // 音频卡顿回调 } - (void)onResolutionSwitch:(TVLManager *)player resolution:(VeLivePlayerResolution)resolution error:(VeLivePlayerError *)error reason:(VeLivePlayerResolutionSwitchReason)reason { // 播放档位变化回调 } - (void)onVideoSizeChanged:(TVLManager *)player width:(int)width height:(int)height { // 分辨率变化回调 } - (void)onReceiveSeiMessage:(TVLManager *)player message:(NSString *)message { // 字符串 SEI 消息回调 } - (void)onReceiveBinarySeiMessage:(TVLManager *)player message:(NSData *)message { // 二进制 SEI 消息回调。需先开启 enableBinarySei,开启后字符串 SEI 消息回调不再触发 } - (void)onMainBackupSwitch:(TVLManager *)player streamType:(VeLivePlayerStreamType)streamType error:(VeLivePlayerError *)error { // 主备切换回调 } - (void)onStreamFormatSwitch:(TVLManager *)player fromStreamFormat:(VeLivePlayerFormat)fromStreamType toStreamFormat:(VeLivePlayerFormat)toStreamType error:(VeLivePlayerError *)error extraInfo:(NSDictionary *)extraInfo { // 流格式切换回调 } - (void)onPlayerStatusUpdate:(TVLManager *)player status:(VeLivePlayerStatus)status { // 播放器状态变化回调 } - (void)onPlayerStatusUpdate:(TVLManager *)player status:(VeLivePlayerStatus)status extraInfo:(NSDictionary *)extraInfo { // 播放器状态变化回调,包含当前播放流的补充信息 } - (void)onStatistics:(TVLManager *)player statistics:(VeLivePlayerStatistics *)statistics { // 周期性回调 } - (void)onSnapshotComplete:(TVLManager *)player image:(UIImage *)image { // 截图回调 } - (void)onRenderVideoFrame:(TVLManager *)player videoFrame:(VeLivePlayerVideoFrame *)videoFrame { // 视频帧订阅回调 } - (void)onRenderAudioFrame:(TVLManager *)player audioFrame:(VeLivePlayerAudioFrame *)audioFrame { // 音频帧订阅回调 } - (void)onStreamFailedOpenSuperResolution:(TVLManager *)player error:(VeLivePlayerError *)error { // 超分开启失败回调 }
播放器的视图以 UIView 的形式呈现,内部会创建一个 playerView,视频播放时会在该 playerView 上进行渲染。使用时,只需将 playerView 添加到您的自定义 UIView 上即可。
// 配置 Metal 渲染 self.livePlayer.playerViewRenderType = TVLPlayerViewRenderTypeMetal; // 配置 playerView 尺寸 self.livePlayer.playerView.frame = UIScreen.mainScreen.bounds; // 将 playerView 添加到您的自定义 view 上 [self.view addSubview:self.livePlayer.playerView];
通过 setPlayUrl: 接口配置单一播放地址,支持 RTMP、FLV、HLS 等直播协议地址。调用该接口时,请将示例地址替换为实际的直播播放地址,并在调用 play 接口前完成配置。代码示例如下所示。
NSString *playUrl = @"http://pull.example.com/live/stream.flv"; [self.livePlayer setPlayUrl:playUrl]; // 配置播放地址
说明
如果您需要配置多路组合播放地址,可使用 setPlayStreamData: 接口,该接口支持 RTM、QUIC、主备流切换、多档位、ABR 等功能。请在调用 play 接口前完成配置。详细的代码示例和接入方法请参考进阶功能接入。
您可以通过以下接口调整播放画面的填充模式、镜像和旋转角度,以获得更好的观看体验。
通过播放器的 setRenderFillMode: 接口可以配置播放画面的填充模式,播放器支持以下 3 种填充模式。
| 填充模式 | 说明 |
|---|---|
| VeLivePlayerFillModeAspectFit | 显示完整的视频帧。视频帧等比缩放,直至视频帧恰好在画布上全部显示。如果视频帧长宽比例与画布不同,视窗上未被视频帧填满区域将填充为黑色。 |
| VeLivePlayerFillModeFullFill | 视频帧自适应画布。视频帧非等比缩放,直至填满画布。在此过程中,视频帧的长宽比例可能会发生变化。 |
| VeLivePlayerFillModeAspectFill | 视频填满画布。视频帧等比缩放,直至填满画布,超出屏幕的部分将被裁剪,画面可能不完整。 |
您可以参考以下代码示例配置填充模式。
// 配置填充模式 [self.livePlayer setRenderFillMode:VeLivePlayerFillModeAspectFill];
通过播放器的 setRenderMirror: 接口可以配置播放画面的镜像模式,播放器支持以下 3 种镜像模式。
| 镜像 | 说明 |
|---|---|
| VeLivePlayerMirrorNone | 关闭镜像 |
| VeLivePlayerMirrorHorizontal | 水平镜像 |
| VeLivePlayerMirrorVertical | 垂直镜像 |
您可以参考以下代码示例配置镜像。
// 配置水平镜像 [self.livePlayer setRenderMirror:VeLivePlayerMirrorHorizontal];
通过播放器的 setRenderRotation: 接口可以配置播放画面的旋转角度,播放器支持以下 4 种旋转角度。
| 旋转 | 说明 |
|---|---|
| VeLivePlayerRotation0 | 关闭旋转 |
| VeLivePlayerRotation90 | 顺时针旋转 90 度 |
| VeLivePlayerRotation180 | 顺时针旋转 180 度 |
| VeLivePlayerRotation270 | 顺时针旋转 270 度 |
您可以参考以下代码示例配置旋转角度。
// 配置画面旋转 90 度 [self.livePlayer setRenderRotation:VeLivePlayerRotation90];
调用播放器的 play 接口开始播放。代码示例如下所示。
[self.livePlayer play]; // 开始播放
调用播放器的 isPlaying 接口可以获取当前的播放状态。代码示例如下所示。
BOOL isPlaying = [self.livePlayer isPlaying]; // 获取播放状态
调用播放器的 stop 接口停止播放。调用该接口不会销毁播放器。代码示例如下所示。
[self.livePlayer stop]; // 停止播放
停止播放后,如不再使用播放器,调用 destroy 接口销毁播放器并释放内存。代码示例如下所示。
[self.livePlayer destroy]; // 销毁播放器并释放相关内存
应用进入后台后,播放器默认会继续播放音频。如不希望音频在后台继续播放,请在应用进入后台时停止播放,并在应用回到前台时恢复播放。代码示例如下所示。
// 应用回到前台通知 [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; // 应用进入后台通知 [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; - (void)applicationDidBecomeActive:(NSNotification *)notification { [self.livePlayer play]; // 应用回到前台,继续播放 } // 退到后台处理 - (void)applicationWillResignActive:(NSNotification *)notification { [self.livePlayer stop]; // 应用进入后台,停止播放 }
调用播放器的 setMute: 接口可以控制是否静音播放。代码示例如下所示。
[self.livePlayer setMute:YES]; // 配置静音播放
调用播放器的 isMute 接口可以获取当前是否为静音状态。代码示例如下所示。
BOOL isMute = [self.livePlayer isMute]; // 获取静音状态
设置播放器的 volume 属性可以控制播放音量。该属性的默认值为 1.0,取值范围为 [0.0, 1.0]。代码示例如下所示。
[self.livePlayer setVolume:0.5]; // 配置播放音量
您可以通过调用 setLogLevel: 设置打印到控制台的日志级别,代码示例如下:
// 输出 INFO、WARNING 和 ERROR 级别的日志 [TVLManager setLogLevel:VeLivePlayerLogLevelInfo];