本章节介绍了拉流 SDK 进阶功能的接入方式,支持的进阶功能包括但不限于 RTM 协议拉流、QUIC 协议拉流、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。您可以根据实际业务需求,借助拉流 SDK 实现更复杂的功能。
真机调试:由于 SDK 使用了大量 iOS 系统的音视频接口,这些接口在仿真模拟器下可能会出现异常,推荐您使用真机进行代码调试。
本节为您详细介绍如何使用拉流 SDK 进阶功能的实现。包括但不限于 RTM 协议拉流、QUIC 协议拉流、DRM 加密流播放、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。
视频直播拉流 SDK 支持 RTM 协议拉流,该功能需要配合火山引擎视频直播服务使用。详细信息可参考超低延时直播介绍。
注意
RTM 协议拉流不支持纯音频或纯视频流。
配置 RTM 拉流地址和 FLV 拉流地址进行播放。代码示例如下所示。
// 配置 RTM 地址 VeLivePlayerStream *playStreamRTM = [[VeLivePlayerStream alloc]init]; playStreamRTM.url = "https://pull.example.com/live/stream.sdp"; playStreamRTM.format = VeLivePlayerFormatRTM; // 配置 FLV 地址 VeLivePlayerStream *playStreamFLV = [[VeLivePlayerStream alloc]init]; playStreamFLV.url = "https://pull.example.com/live/stream.flv"; playStreamFLV.format = VeLivePlayerFormatFLV; // 创建 VeLivePlayerStreamData VeLivePlayerStreamData *streamData = [[VeLivePlayerStreamData alloc]init]; NSMutableArray <VeLivePlayerStream *> *mainStreams = [NSMutableArray arrayWithCapacity:1]; // 添加 RTM 流地址 [mainStreams addObject:playStreamRTM]; // 添加 FLV 流地址 [mainStreams addObject:playStreamFLV]; streamData.mainStream = mainStreams; // 配置默认 format 和 protocol streamData.defaultFormat = VeLivePlayerFormatRTM; streamData.defaultProtocol = VeLivePlayerProtocolTLS; // 配置播放源 [self.livePlayer setPlayStreamData:streamData]; // 开始播放 [self.livePlayer play];
视频直播拉流 SDK 支持 QUIC 协议拉流,该功能需要配合火山引擎视频直播服务使用。
如果您使用的是在线集成方式,请在 subspecs 中添加 Quic
,以启用 QUIC 功能。
source 'https://github.com/volcengine/volcengine-specs.git' pod 'TTSDK', '1.37.1.8-premium', :subspecs => ['LivePull' 'Quic']
使用视频直播控制台的地址生成器,生成 FLV 拉流地址。
配置 QUIC 拉流地址进行播放。代码示例如下所示。
// 配置 FLV 地址 VeLivePlayerStream *playStreamFLV = [[VeLivePlayerStream alloc]init]; playStreamFLV.url = "https://pull.example.com/live/stream.flv"; playStreamFLV.format = VeLivePlayerFormatFLV; playStreamFLV.protocol = VeLivePlayerProtocolQUIC; // 创建 VeLivePlayerStreamData VeLivePlayerStreamData *streamData = [[VeLivePlayerStreamData alloc]init]; NSMutableArray <VeLivePlayerStream *> *mainStreams = [NSMutableArray arrayWithCapacity:1]; // 添加 FLV 流地址 [mainStreams addObject:playStreamFLV]; streamData.mainStream = mainStreams; // 配置默认 format 和 protocol streamData.defaultFormat = VeLivePlayerFormatFLV; streamData.defaultProtocol = VeLivePlayerProtocolQUIC; // 协议为 QUIC // 配置播放源 [self.livePlayer setPlayStreamData:streamData]; // 开始播放 [self.livePlayer play];
说明
拉流 SDK 默认开启了 QUIC 协议拉流的失败降级策略,无需额外配置。如果 QUIC 协议拉流失败,SDK 将自动降级为 TCP 协议拉流。
播放器支持 DRM 加密流播放。
参考最佳实践- 直播 DRM 加密获取以下信息:
使用 initWithType
方法初始化播放器,示例代码如下所示。
self.livePlayer = [[TVLManager alloc] initWithType:VeLivePlayerTypeSystem];
说明
使用 initWithType
方法初始化播放器后,将不支持以下功能接入。
配置加密流播放地址。
NSString *playUrl = "http://pull.example.com/live/stream.m3u8"; [self.livePlayer setPlayUrl:playUrl];
注册 observer 后,通过以下回调方法返回 Fairplay 证书文件和 DRM 授权许可 URL。
- (NSData *)getDrmResourceLoaderCertificateData:(TVLManager *)player { // 传入 Fairplay 证书的路径 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testfairplay" ofType:@"cer"]; NSData *certificate = [NSData dataWithContentsOfFile:filePath]; return certificate; } - (NSString *)getDrmResourceLoaderLicenseUrl:(TVLManager *)player { // 返回 DRM 许可证书地址 URL return @"https://drmtest/license"; }
播放器支持通过设置播放域名的 IP 地址进行拉流,以降低播放首帧时间。
请先获取直播播放地址并解析出 IP 地址。
使用播放器的 setUrlHostIP
接口将 IP 地址与域名关联起来,播放器将直接根据 IP 地址进行拉流播放。代码示例如下所示。
// 配置播放 URL [self.livePlayer setPlayUrl:@"https://pull.example.com/live/stream.flv"]; // 添加 IP 地址和域名关联 NSMutableArray<NSString *> *ipList = [[NSMutableArray alloc] initWithCapacity:1]; [ipList addObject:@"xxx.xxx.xxx.xxx"]; // IP 地址 NSMutableDictionary* ipHost = [[NSMutableDictionary alloc] initWithCapacity:1]; [ipHost setObject:ipList forKey:@"pull.example.com"]; // 配置 IP 地址 [self.livePlayer setUrlHostIP:ipHost]; // 开始播放 [self.livePlayer play];
主备流主要用于直播间容灾,通过配置主备两路直播流地址,在推流和分发环节使用主备流进行直播。播放器在接入时配置主备两路拉流地址,当主路地址拉流失败或者播放出错时,播放器会自动切换到备路地址进行播放。同样地,当备路地址播放出错时,播放器会切换回主路地址进行播放。主备地址可以来自同一直播服务商,也可以来自不同的直播服务商。
获取主流地址和备流地址,如果使用火山引擎视频直播服务,您可通过视频直播控制台的地址生成器,生成主备拉流地址。
// 配置主流地址 VeLivePlayerStream *playStreamMain = [[VeLivePlayerStream alloc]init]; playStreamMain.url = @"https://pull.example.com/live/主.flv"; playStreamMain.type = VeLivePlayerStreamTypeMain; // 流类型配置为主路 // 配置备流地址 VeLivePlayerStream *playStreamBackup = [[VeLivePlayerStream alloc]init]; playStreamBackup.url = @"https://pull.example.com/live/备.flv"; playStreamBackup.type = VeLivePlayerStreamTypeBackup; // 流类型配置为备路 // 创建播放源 VeLivePlayerStreamData *streamData = [[VeLivePlayerStreamData alloc]init]; // 开启主备切换 streamData.enableMainBackupSwitch = YES; // 添加主流 NSMutableArray <VeLivePlayerStream *> *mainStreams = [NSMutableArray arrayWithCapacity:1]; [mainStreams addObject:playStreamMain]; streamData.mainStream = mainStreams; // 添加备流 NSMutableArray <VeLivePlayerStream *> *backupStreams = [NSMutableArray arrayWithCapacity:1]; [backupStreams addObject:playStreamBackup]; streamData.backupStream = backupStreams; // 配置播放源 [self.livePlayer setPlayStreamData:streamData]; // 开始播放 [self.livePlayer play];
onMainBackupSwitch
进行通知。代码示例如下所示。- (void)onMainBackupSwitch:(TVLManager *)player streamType:(VeLivePlayerStreamType)streamType error:(VeLivePlayerError *)error { // 主备流切换通知 }
播放器支持配置多档位的直播拉流地址,通过接口可以实现多档位直播流的切换。
获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。
本文的接入说明以下列拉流地址为例。
档位 | 拉流地址 |
---|---|
源流(Orgin) | https://pull.example.com/live/123456.flv |
超清(UHD) | https://pull.example.com/live/123456_uhd.flv |
高清(HD) | https://pull.example.com/live/123456_hd.flv |
标清(SD) | https://pull.example.com/live/123456_sd.flv |
低清(LD) | https://pull.example.com/live/123456_ld.flv |
// 配置多档位流地址 VeLivePlayerStream *playStreamOrgin = [[VeLivePlayerStream alloc]init]; playStreamOrgin.url = @"https://pull.example.com/live/123456.flv"; playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位 VeLivePlayerStream *playStreamUHD = [[VeLivePlayerStream alloc]init]; playStreamUHD.url = @"https://pull.example.com/live/123456_uhd.flv"; playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位 VeLivePlayerStream *playStreamHD = [[VeLivePlayerStream alloc]init]; playStreamHD.url = @"https://pull.example.com/live/123456_hd.flv"; playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位 VeLivePlayerStream *playStreamSD = [[VeLivePlayerStream alloc]init]; playStreamSD.url = @"https://pull.example.com/live/123456_sd.flv"; playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位 VeLivePlayerStream *playStreamLD = [[VeLivePlayerStream alloc]init]; playStreamLD.url = @"https://pull.example.com/live/123456_ld.flv"; playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位 // 创建播放源 VeLivePlayerStreamData *streamData = [[VeLivePlayerStreamData alloc]init]; // 添加多档位流 NSMutableArray <VeLivePlayerStream *> *mainStreams = [NSMutableArray arrayWithCapacity:1]; [mainStreams addObject:playStreamOrgin]; [mainStreams addObject:playStreamUHD]; [mainStreams addObject:playStreamHD]; [mainStreams addObject:playStreamSD]; [mainStreams addObject:playStreamLD]; streamData.mainStream = mainStreams; // 配置默认启播档位 streamData.defaultResolution = VeLivePlayerResolutionOrigin; // 配置播放源 [self.livePlayer setPlayStreamData:streamData]; // 开始播放 [self.livePlayer play];
switchResolution
接口可以实现多个档位之间的手动切换。代码示例如下所示。[self.livePlayer switchResolution:VeLivePlayerResolutionUHD]; // 切换到 UHD 档位
onResolutionSwitch
进行回调。代码示例如下所示。- (void)onResolutionSwitch:(TVLManager *)player resolution:(VeLivePlayerResolution)resolution error:(VeLivePlayerError *)error reason:(VeLivePlayerResolutionSwitchReason)reason { // 档位切换回调 }
自适应码率(Adaptive Bit-Rate,简称 ABR)是一种流媒体传输技术,通过一系列算法策略,动态切换不同档位媒体流,以达到适应网络带宽变化,防止观众在观看直播过程产生卡顿,提升播放质量和观看体验。
注意
ABR 功能只适用于 FLV 格式流。
获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。
本文的接入说明以下列拉流地址为例。
档位说明 | 拉流地址 | 码率(kbps) |
---|---|---|
源流(Orgin) | https://pull.example.com/live/123456.flv | 2500 |
超清(UHD) | https://pull.example.com/live/123456_uhd.flv | 2500 |
高清(HD) | https://pull.example.com/live/123456_hd.flv | 1000 |
标清(SD) | https://pull.example.com/live/123456_sd.flv | 800 |
低清(LD) | https://pull.example.com/live/123456_ld.flv | 500 |
// 配置多档位流地址 VeLivePlayerStream *playStreamOrgin = [[VeLivePlayerStream alloc]init]; playStreamOrgin.url = @"https://pull.example.com/live/123456.flv"; playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位 playStreamOrgin.bitrate = 2500; VeLivePlayerStream *playStreamUHD = [[VeLivePlayerStream alloc]init]; playStreamUHD.url = @"https://pull.example.com/live/123456_uhd.flv"; playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位 playStreamUHD.bitrate = 2500; VeLivePlayerStream *playStreamHD = [[VeLivePlayerStream alloc]init]; playStreamHD.url = @"https://pull.example.com/live/123456_hd.flv"; playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位 playStreamHD.bitrate = 1000; VeLivePlayerStream *playStreamSD = [[VeLivePlayerStream alloc]init]; playStreamSD.url = @"https://pull.example.com/live/123456_sd.flv"; playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位 playStreamSD.bitrate = 800; VeLivePlayerStream *playStreamLD = [[VeLivePlayerStream alloc]init]; playStreamLD.url = @"https://pull.example.com/live/123456_ld.flv"; playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位 playStreamLD.bitrate = 500; // 创建播放源 VeLivePlayerStreamData *streamData = [[VeLivePlayerStreamData alloc]init]; // 添加多档位流 NSMutableArray <VeLivePlayerStream *> *mainStreams = [NSMutableArray arrayWithCapacity:1]; [mainStreams addObject:playStreamOrgin]; [mainStreams addObject:playStreamUHD]; [mainStreams addObject:playStreamHD]; [mainStreams addObject:playStreamSD]; [mainStreams addObject:playStreamLD]; streamData.mainStream = mainStreams; // 配置默认启播档位 streamData.defaultResolution = VeLivePlayerResolutionOrigin; // 开启 ABR streamData.enableABR = YES; // 配置播放源 [self.livePlayer setPlayStreamData:streamData]; // 开始播放 [self.livePlayer play];
onResolutionSwitch
进行回调。代码示例如下所示。- (void)onResolutionSwitch:(TVLManager *)player resolution:(VeLivePlayerResolution)resolution error:(VeLivePlayerError *)error reason:(VeLivePlayerResolutionSwitchReason)reason { // 档位切换回调 }
截图功能允许您在播放器中截取当前直播画面并生成一张图片。
snapshot
接口可以实现截图功能。截图仅在播放器播放成功后可以生效。代码示例如下所示。int result = [self.livePlayer snapshot];
onSnapshotComplete
进行回调,同时将截取的图片数据传递给回调方法。代码示例如下所示。- (void)onSnapshotComplete:(TVLManager *)player image:(UIImage *)image { // 截图成功回调,参数 image 为截图的图片数据 }
SEI(Supplemental Enhancement Information)是直播流中的附加信息,它可以用于传递自定义的数据或元数据。
play
方法之前,您可以通过配置播放器的 enableSei
属性来开启 SEI 信息的接收功能。代码示例如下所示。// 创建播放器初始化配置 VeLivePlayerConfiguration *config = [[VeLivePlayerConfiguration alloc]init]; // 打开 SEI 开关 config.enableSei = YES; // 初始化配置 [self.livePlayer setConfig:config];
onReceiveSeiMessage
进行回调,并将接收到的 SEI 信息传递给回调方法。代码示例如下所示。- (void)onReceiveSeiMessage:(TVLManager *)player message:(NSString*)message { // SEI 回调 }
通过订阅解码后的视频数据,您可以获取视频帧数据并进行自定义的处理和渲染操作。播放器支持多种视频帧数据的回调,并提供了相应的参数和格式选项。
视频帧像素格式和视频数据封装格式的枚举和含义如下表所示。
格式类型 | 枚举 | 说明 |
---|---|---|
视频帧像素格式 | VeLivePlayerPixelFormatNV12 | NV12 |
VeLivePlayerPixelFormatI420 | I420 | |
视频数据封装格式 | VeLivePlayerVideoBufferTypePixelBuffer | CVPixelBufferRef |
VeLivePlayerVideoBufferTypeSampleBuffer | CVSampleBufferRef | |
VeLivePlayerVideoBufferTypeNSData | NSData |
配置订阅视频数据前,请您根据需要选择格式组合。格式组合需要遵循下表中提供的 VeLivePlayerPixelFormat 和 VeLivePlayerVideoBufferType 的对应关系。
像素格式/封装格式 | VeLivePlayerPixelFormatNV12 | VeLivePlayerPixelFormatI420 |
---|---|---|
VeLivePlayerVideoBufferTypePixelBuffer | √(性能最优) | × |
VeLivePlayerVideoBufferTypeSampleBuffer | √ | × |
VeLivePlayerVideoBufferTypeNSData | √ | √ |
enableVideoFrameObserver
接口开启或关闭视频帧数据订阅功能。接口参数说明如下表所示。参数 | 类型 | 说明 |
---|---|---|
enable | BOOL | 是否开启视频帧回调。 |
pixelFormat | VeLivePlayerPixelFormat | 视频帧像素格式。 |
bufferType | VeLivePlayerVideoBufferType | 视频数据封装格式。 |
代码示例如下所示。
// [self.livePlayer enableVideoFrameObserver:YES pixelFormat:VeLivePlayerPixelFormatNV12 bufferType:VeLivePlayerVideoBufferTypePixelBuffer];
onRenderVideoFrame
进行回调。代码示例如下所示。- (void)onRenderVideoFrame:(TVLManager *)player videoFrame:(VeLivePlayerVideoFrame *)videoFrame { // 视频帧数据回调 }
VeLivePlayerVideoFrame
参数说明如下表所示。
参数 | 类型 | 说明 |
---|---|---|
bufferType | VeLivePlayerVideoBufferType | 视频帧数据封装格式 |
pixelFormat | VeLivePlayerPixelFormat | 视频帧像素格式 |
width | NSInteger | 视频帧的宽度,单位为 px |
height | NSInteger | 视频帧的高度,单位为 px |
pts | int64_t | 视频帧的渲染时间戳,单位为 ms |
pixelBuffer | CVPixelBufferRef | bufferType 为 VeLivePlayerVideoBufferTypePixelBuffer 时的视频数据 |
sampleBuffer | CMSampleBufferRef | bufferType 为 VeLivePlayerVideoBufferTypeSampleBuffer 时的视频数据 |
data | NSData* | bufferType 为 VeLivePlayerVideoBufferTypeNSData 时的视频数据 |
通过订阅解码后的音频数据,您可以获取音频帧数据并进行自定义的处理和渲染操作。
播放器支持音频帧数据帧回调格式为 PCM Float32 类型,数据封装格式为 NSData。
VeLivePlayerAudioBufferType | 音频数据封装格式 |
---|---|
VeLivePlayerAudioBufferTypeNSData | NSData 格式 |
enableAudioFrameObserver
接口开启或关闭音频帧数据订阅功能。接口参数说明如下表所示。参数 | 类型 | 说明 |
---|---|---|
enable | BOOL | 是否开启音频帧回调。 |
enableRendering | BOOL | 是否开启播放器渲染。当不需要播放器内部进行音频播放时,可以将该参数值配置为 NO 。 |
代码示例如下所示。
// 订阅音频帧数据,打开播放器内部音频渲染 [self.livePlayer enableAudioFrameObserver:YES enableRendering:YES];
onRenderAudioFrame
接口进行回调。代码示例如下所示。- (void)onRenderAudioFrame:(TVLManager *)player audioFrame:(VeLivePlayerAudioFrame *)audioFrame { // 音频帧数据回调 }
VeLivePlayerAudioFrame
参数说明如下表所示。
参数 | 数据类型 | 说明 |
---|---|---|
bufferType | VeLivePlayerAudioBufferType | 音频帧数据封装格式 |
sampleRate | int | 音频采样率,单位为 Hz |
channels | int | 声道数 |
bitDepth | int | 音频位深度 |
pts | CMTime | 音频渲染时间戳,单位为 ms |
data | NSData* | PCM 音频数据 |
samples | int | 音频采样点个数 |
超分,即超分辨率技术(Super-Resolution, SR)是指从观测到的低分辨率图像重建出相应的高分辨率图像的过程,移动端实时超分,是指利用算法技术在端上对低分辨率的帧进行实时重建,产生高分辨率的帧显示在屏幕上,从而改善视频内容的细节与对比度,全面提升视频的播放清晰度和观看体验的优化手段。
setEnableSuperResolution:(BOOL)enable
方法开启或者关闭拉流超分功能,默认状态为关闭。参数 | 类型 | 说明 |
---|---|---|
enable | BOOL | 是否开启超分功能。 |
onStreamFailedOpenSuperResolution
进行回调。代理方法签名如下所示。- (void)onStreamFailedOpenSuperResolution:(TVLManager *_Nonnull)player error:(VeLivePlayerError *_Nullable)error;
如果开启超分失败,可能有以下几种原因。
直播拉流 SDK 支持调用火山引擎 HTTPDNS 服务对拉流地址的预解析,以此来降低播放首帧时长。
开通云解析 DNS 服务。
左侧导航栏选择实例信息,记录您的鉴权密钥,包含 SERVICE ID 和 SECRET KEY。
在拉流客户端调用 setVeHttpDNSAuth
方法配置调用 HTTPDNS 服务需要使用的鉴权密钥,代码示例如下所示。
[VeLiveCommon setVeHttpDNSAuth:@"http_dns_serviceID" key:@"http_dns_key"];
调用 prefetchDomains
方法进行域名解析,解析成功后的 IP 地址会自动设置给播放器,代码示例如下所示。
[VeLiveCommon prefetchDomains:@[@"xxx.pull.com", @"yyy.pull.com"]];