特效直播
直播模块不含音视频采集功能,我们需要使用拍摄器模块进行音视频的采集。当然我们也可以参考直播Demo中的 ‘BDCloudExternalCapture.m’文件实现外部采集后讲数据传递给直播模块。
示例代码:
1. // 1. 开起相机
2. – (void)start {
3. if (self.isRunning) {
4. return;
5. }
6. // 拍摄配置
7. BDCloudAVStreamSettings *settings = [BDCloudAVStreamSettings defaultSettings];
8. // 视频帧率
9. settings.videoFrameRate = self.setting.frameRate;
10. // 视频分辨率
11. settings.dimensions = self.setting.caputreDimension;
12. // 视频横屏设置
13. settings.enablelandscapeLeftRecord = self.setting.enablelandscapeLeftRecord;
14. settings.stabilizationMode = AVCaptureVideoStabilizationModeStandard;
15. // 直播状态配置(非常关键)
16. settings.enableLive = YES;
17. // 根据相机配置初始化相机
18. self.captureSession = [[BDCloudAVRecordSession sharedInstance] initWithCaptureConfig:settings];
19. // 拍摄代理
20. self.captureSession.delegate = self;
21. if (self.setting.enablelandscapeLeftRecord) {
22. self.captureSession.view.transform = CGAffineTransformMakeRotation(-M_PI_2);
23. }
24. self.captureSession.view.frame = self.preView.bounds;
25.
26. // 直播支持后台推流
27. [self.captureSession autoPauseAudioBackground:NO];
28. // 水印
29. if (self.setting.enableWatermark) {
30. [self setWatermark:[UIImage imageNamed:@"pushlogo"]];
31. }
32.
33. // 创建特效控制UI(等相机开启回调后添加到preview)
34. self.captrueControlView = [[BDCloudCaptureView alloc] initWithFrame:[UIScreen mainScreen].bounds
35. session:self.captureSession];
36. self.captrueControlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
37. self.isRunning = YES;
38.
39. // 注意 captureSession 内含接受手势的view,会添加在 self.captureSession.view 的父view上。
40. [self.captrueControlView insertSubview:self.captureSession.view atIndex:0];
41. [self.preView insertSubview:self.captrueControlView atIndex:0];
42. }
43. // 2. 美颜相机配置
44. - (void)captureCameraStarted {
45. // 添加特效效果(基础美颜)
46. [self.captureSession applyBeautyBaseVideoFx];
47. [self.captureSession adjustBeautyWhiteLevel:0.7];
48. [self.captureSession adjustBeautyBlurLevel:0.7];
49.
50. // 横屏的UI没有适配暂不开放,客户可以在configBaseUI内进行UI适配后开放此开关。
51. if (!self.setting.enablelandscapeLeftRecord) {
52. // 保证AR手势View在最下,防止AR手势View当住了captrueControlView的一些操作。
53. [self.captrueControlView configBaseUI];
54. }
1.1初始化推流参数并配置
这里我们以直播Demo ‘BDCloudLiveContextHelper.mm’文件为例. 示例代码:
1. // 1. 创建并初始化
2. BDCloudAVLiveParameter *par = [[BDCloudAVLiveParameter alloc] init];
3. // 2. 配置音频默认编码参数
4. par.audioSettings = [BDCloudAVAudioOutputSettings defaultSettings];
5. // 3. 配置视频默认编码参数
6. par.videoSettings = [BDCloudAVVideoOutputSettings defaultSettings];
7. // 4. 修改视频编码分辨率
8. par.videoSettings.dimension = self.settings.dimension;
9. // 5. 修改视频编码码率。
10. par.videoSettings.bitRate = self.settings.bitRate * 1000;
11. // 6. 修改视频编码帧率
12. par.videoSettings.frameRate = self.settings.frameRate;
13. // 7. 修改推流协议
14. par.streamType = BDCloudAVLiveTypeNormal;
15. // 8. 设置推流地址
16. par.url = [NSURL URLWithString:[settings pushUrl]];
17. if (settings.pushType == BDCloudPushSettingTypeLowerLatency) {
18. par.streamType = BDCloudAVLiveTypeLowerLatency;
19. par.url = [NSURL URLWithString:[settings pushUrl]];
20. // test ip and domain mixer
21. if (!par.url) {
22. par.c_url = [settings pushUrl];
23. }
24. }
1.2 初始化视频直播控制
类型:方法 参数:BDCloudAVLiveParameter 推流参数 返回值:BDCloudAVLiveContext实例
- (instancetype)initWithLiveParameter:(BDCloudAVLiveParameter*)parameter;
示例代码:
1. _liveContext = [[BDCloudAVLiveContext alloc] initWithLiveParameter:par];
1.3连接音视频数据源和推流器
示例代码:
1. // 1. BDCloudPushLiveController.mm 文件
2. // 连接 BDCloudAVRecordSession 和 BDCloudLivePushViewModel
3. [self.captureViewModel addBufferListener:self.pushViewModel];
4.
5. // 2. BDCloudLivePushViewModel.mm 文件
6. // 连接 BDCloudLivePushViewModel 和 BDCloudAVLiveContext
7. self.videoOutput = [[BDCloudAVOutput alloc] initWithMediaType:AVMediaTypeVideo];
8. self.audioOutput = [[BDCloudAVOutput alloc] initWithMediaType:AVMediaTypeAudio];
9. [self.videoOutput addTarget:self.liveHelper.liveContext];
10. [self.audioOutput addTarget:self.liveHelper.liveContext];
11.
12. // 3. BDCloudLivePushViewModel.mm 文件
13. // 数据传输
14. - (void)frame:(CMSampleBufferRef)frame type:(NSString *)type {
15. if ([type isEqualToString:AVMediaTypeVideo]) {
16. [self.videoOutput raiseFrame:frame];
17. } else if ([type isEqualToString:AVMediaTypeAudio]) {
18. [self.audioOutput raiseFrame:frame];
19. }
20. }
可以直接数据源(BDCloudAVRecordSession)和推流器(BDCloudAVLiveContext) 示例代码:
1. // 伪代码
2. [recordSession addBufferListener: liveContext]
1.4 设置推流状态监听
推流状态监听必须在开始推流前设置。
类型:属性
默认值:nil
@property(nonatomic, weak) id
示例代码:
1. _liveContext.delegate = self;
1.5 开始推流
类型:方法 返回值:是否开起成功。当重复调用时返回NO。
- (BOOL)start;
示例代码:
1. [self.liveContext start];
1.6 结束推流
类型:方法 返回值:是否关闭成功。当重复调用时返回NO。
- (BOOL)stop;
示例代码:
1. [self.liveContext stop];
1.7 断网重连
断网重连我们通常是根据代理回调的错误码根据自身业务情况判断是否进行重连。 重连方法必须在开始推流后才能调用。
类型:方法 返回值;重连是否成功。(异步重连,返回值不作为重连的真实结果,真实结果以代理回调为主)
- (BOOL)reconnect;
示例代码:
1. // 1. 重连函数
2. - (void)reconnect {
3. [self.liveContext reconnect];
4. }
5. // 2. 根据回调代理的错误码判断是否应该重连。
6. - (void)liveContextError:(RtmpSocketErrorCode)code {
7. dispatch_async(dispatch_get_main_queue(), ^{
8. if (self.liveContextStatusChange) {
9. self.liveContextStatusChange(NO, code);
10. }
11. });
12. if (code == ErrorCodeLicenseInvalid) {
13. NSLog(@"鉴权失败,请检查自己的license文件!!!");
14. return;
15. } else if (code == -5) {
16. NSLog(@"SRT 发送失败...开始重连");
17. [self reconnect];
18. } else {
19. [self reconnect];
20. }
21. }
1.8 开始动态码率
动态码率的本质是在推流过程中,通过数据监控判断当前的网络状态是否满足当前的码率进行数据上传,动态的调整当前视频编码的码率,使音视频数据可以高质量的上传到Server。 动态码率主要应用于网络状态不稳定的一些场景,例如户外直播等。 动态码率在开始推流前不生效,但设置后内部会在推流连接成功以后自动开启。
类型:方法 参数: Sensibility:检测频次,检测频次与动态码率灵敏度成反相关。 maxBitRate: 动态码率的最大码率。 minBitRate: 动态码率的最小码率。 返回值:是否开启成功。当maxBitRate < minBitRate 时返回失败。
- (BOOL)startQOS:(NSUInteger)sensibility maxBitRate:(NSUInteger)maxBitRate minBitRate:(NSUInteger)minBitRate
示例代码:
1. self.liveContext startQOS:5
2. maxBitRate:self.settings.maxbitRate * 1000
3. minBitRate:self.settings.minbitRate * 1000];
1.9 关闭动态码率
类型:方法
- (void)stopQOS;
示例代码:
1. [self.liveContext stopQOS];
1.10 开关静音直播
BDCloudAVLiveContext类中的开关静音方法实际上是通过改变传入的音频数据实现的,如果对于传入的音频数据还需要二次使用,必须慎用。
示例代码:
‘BDCloudARCaptrue.mm’文件中
1. - (void)switchAudioSilent:(BOOL)isSilent {
2. [self.captureSession switchBufferListenerAudioSilent:isSilent];
1.11 自定义图片推流(后台推流)
自定义图片推流是使用指定图片进行推流,此时相机传入的视频数据失效。推流将自定义的图片进行编码打包后上报。 应用场景通常是APP进入后台后,相机无法采集数据时为了让视频数据更加的连贯和反馈给观众端的一种方法。 我们推荐如果APP长时间(超过一个gop时长)退到后台时是一定需要设置的,否则观众拉流可能会因为拉取不到视频帧导致解码器未正确初始化,推流端回到前台后拉流端仍然无法恢复。
示例代码:
‘BDCloudARCaptrue.mm’文件中
1 // 退到后台时输出固定图像。
2 - (void)onAppEnterBackground:(NSNotification *)notification {
3 [self.captureSession setBufferListenerImageOutput:[UIImage imageNamed:@"pusbackground"]];
4 }
5 // 回到前台时回复相机图像。
6 - (void)onAppWillEnterForeground:(NSNotification *)notification {
7 [self.captureSession setBufferListenerImageOutput:nil];
8 }
1.12 发送Metadata
主播在直播流中可以发送metadata消息。可由百度云播放器解析并通过通知发送给每一个观众用户。常用于直播答题、直播换装等需要由主播添加进实时流内的消息功能。 发送metadata之前需要校验权限,此时就是需要配置该参数。
类型:方法 参数:BDCloudAVLiveMetadataConfig 鉴权及播放流信息 返回值:本地校验是否成功。当本地校验失败时返回NO(本地校验主要针对参数是否非法)
- (BOOL)setConfig:(BDCloudAVLiveMetadataConfig *)config
示例代码:
1. [self.liveContext setConfig:self.metadataPushServer.config]
Metadata发送信息 类型:方法 参数: NSDictionary:需要发送的json信息。 Block:发送结果和错误码
- (void)pushInfoToMetadata:(NSDictionary )info complete:(void(^)(BOOL success, NSError error))complete
示例代码:
2. [self.liveContext pushInfoToMetadata:define
3. complete:^(BOOL success, NSError *error) {
4. NSLog(@"asyncPushUserDefine error = %@", error);
5. }];
1.13 获取直播上行速度
直播上行速度是指每秒的传送到服务端的数据量。通常用来和视频编码的码率作为对比判断当前的网速和编码码率是否匹配。 类型:参数 默认值:0 @property(nonatomic, readonly) double realtimeUploadSpeed; 示例代码;
1. double realtimeUploadSpeed = liveContext.realtimeUploadSpeed
1.14 获取直播上行帧率
直播上行帧率是指每秒的传送到服务端的视频帧数。通常用来和视频编码的帧率作为对比判断当前的推流卡顿程度。 类型:参数 默认值:0 @property(nonatomic, readonly) double realtimeUploadFPS; 示例代码:
1. double realtimeUploadFPS = liveContext.realtimeUploadFPS
1.15 获取视频编码码率
视频编码码率是指视频编码时真实每秒产出的视频数据量大小。尽管我们编码设置了目标码率,但是并不是真实产生的编码数据量的大小。通常我们会通过比较真实的编码码率和真实的上行速度来判断当前的网络宽带是否够用。 类型:参数 默认值:0 @property(nonatomic, readonly) double realtimeBitrate;
示例代码:
1. double realtimeBitrate = liveContext.realtimeBitrate
1.16 获取推流缓冲区数据占比
音视频数据编码打包后进入推流缓冲区,推流协议模块有序从推流缓冲区取出数据进行上传。推流缓冲区能够体现网络延迟和当前上行不满足当前码率等问题。 推流缓冲区占比数据当前仅适用于RTMP协议。 类型:参数 默认值:0 @property(nonatomic, readonly) double packetCacheRate; 示例代码:
1. double packetCacheRate = liveContext.packetCacheRate
1.17 获取往返延迟RTT
在使用SRT传输协议时,可以实时获取往返延迟数据。 RTT参数当前仅适用于SRT协议。 类型:参数 默认值:0 @property(nonatomic, readonly) double msRTT; 示例代码:
1. double msRTT = liveContext.msRTT
1.18 获取预估上行带宽
在使用SRT传输协议时,可以实时获取预估的上行带宽。需要注意区分预估带宽和真实上行的区别。 预估上行带宽参数当前仅适用于SRT协议。 类型:参数 默认值:0 @property(nonatomic, readonly) double mbpsBandwidth;
示例代码:
1. double mbpsBandwidth = liveContext.mbpsBandwidth
1.19 获取交互延迟
在使用SRT传输协议时,可以实时获取交互延迟。 交互延迟参数当前仅适用于SRT协议。 类型:参数 默认值:0 @property(nonatomic, readonly) double peerlatency; 示例代码:
1. double peerlatency= liveContext.peerlatency