录制
录制的相关接口是在BDCloudAVStreamContext类里,包括采集预览(startPreview),录制(startRecording:),添加视频美颜(applyBeautyBaseVideoFx)等。
注意:百度云拍摄器SDK所有的类都是以“BDCloud”开头。
BDCloudAVStreamContext类
BDCloudAVStreamContext是拍摄器SDK的流媒体上下文类,是接入拍摄器SDK产品的入口。开始使用前,需要先初始化BDCloudAVStreamContext类,注意BDCloudAVStreamContext是单例类。
BDCloudAVStreamContext初始化代码如下
1_avStreamContext = [BDCloudAVStreamContext sharedInstance];
BDCloudAVStreamContext销毁代码如下
1[_avStreamContext destroyInstance];
2_avStreamContext = nil;
注意:BDCloudAVStreamContext初始化后,需要调用verifySDKLicense: completionHandler:验证客户的合法性,其中appid即用户申请的licenseID,若未申请授权,请参考快速接入
BDCloudAVStreamSettings类配置
BDCloudAVStreamSettings是拍摄器SDK配置项,支持客户调整摄像头位置、摄像头类型、视频维度(分辨率)、视频帧速率、视频帧码率及手电筒、对焦、曝光补光、预览放大缩小、预览模式。
考虑到配置项较多且偏专业,拍摄器SDK提供默认配置项,代码如下:
1BDCloudAVStreamSettings *settings = [BDCloudAVStreamSettings defaultSettings];
预览前设置
完成流媒体上下文初始化及配置项后,下面就要创建预览前配置,创建拍摄器及预览画面,代码如下:
1 // 使用配置项创建拍摄器
2 _avStreamContext = [_avStreamContext initWithCaptureConfig:settings];
3 // 获取拍摄器预览界面
4 UIView *preview = _avStreamContext.view;
5 // 设置预览界面展示区域
6 preview.frame = self.view.bounds;
7 // 设置拍摄器回调代理
8 _avStreamContext.delegate = self;
9 // 将预览界面添加到用户控制器上
10 [self.view insertSubview:preview atIndex:0];
启动预览
启动预览对应startPreview接口,此接口发检查用户照相机和麦克风系统权限。
录制与停止录制
录制
- 调用录制接口前startRecording: recordCallBack:,需要先创建录制文件的路径,建议用户使用.MOV和.mp4文件
- 录制接口在写入文件的同时,会不断回调给使用方,用户需要关心回调状态BDCloudAVStreamFileOutputState。
- 代码示例如下:
1[[BDCloudAVStreamContext sharedInstance] startRecording:recordVideoPath recordCallBack:^(BDCloudAVStreamFileOutputState state, double recordSecond, NSError *error) {
2
3 switch (state) {
4
5 case BDCloudAVStreamFileOutputStateStarting:
6 break;
7 case BDCloudAVStreamFileOutputStateStarted:
8 break;
9 case BDCloudAVStreamFileOutputStateCancel:
10 break;
11 case BDCloudAVStreamFileOutputStateError:
12 //错误信息
13 break;
14 case BDCloudAVStreamFileOutputStateEnding:
15 //录制结束
16 break;
17 case BDCloudAVStreamFileOutputStateEnded:
18 break;
19 default:
20 break;
21 }
22
23 }];
停止录制
- 代码示例如下:
1[[BDCloudAVStreamContext sharedInstance] stopRecording];
录制设置
- 设置闪光灯是否开启,代码示例如下:
1 AVCaptureFlashMode _flashMode;
2 _flashMode = _flashMode == AVCaptureFlashModeOff ? AVCaptureFlashModeOn : AVCaptureFlashModeOff;
3 [[BDCloudAVStreamContext sharedInstance] toggleFlash:_flashMode];
4 if (_flashMode == AVCaptureFlashModeOff) {
5 [[BDCloudAVStreamContext sharedInstance] toggleTorch:NO];
6 }else {
7 [[BDCloudAVStreamContext sharedInstance] toggleTorch:YES];
8 }
- 设置自动对焦
1 [[BDCloudAVStreamContext sharedInstance] setCameraContinuousAutofocus:YES];
2 [[BDCloudAVStreamContext sharedInstance] setCameraFocusPointOfInterest:[BDCloudAVStreamContext sharedInstance].view.center];
- 设置曝光点
1[[BDCloudAVStreamContext sharedInstance] setCameraExposurePointOfInterest:[BDCloudAVStreamContext sharedInstance].view.center];
- 设置缩放
1[[BDCloudAVStreamContext sharedInstance] setCameraZoomFactor:1.3];
开启美颜
- 添加美颜(applyBeautyBaseVideoFx)特效后,在预览窗口就可以看到美颜效果。录制视频时,用户需要根据手机性能任意选择带美颜录制或者不带美颜录制。 美颜特效分为基础美颜(美白、磨皮)和高级美颜(大眼、瘦脸)。
- 开启美颜,代码示例如下:
1//开启美颜
2[_avStreamContext applyBeautyBaseVideoFx];
3//调整美白
4[[BDCloudAVStreamContext sharedInstance] adjustBeautyWhiteLevel:newValue];
5//调整磨皮
6[[BDCloudAVStreamContext sharedInstance] adjustBeautyBlurLevel:newValue];
7//调整大眼
8[[BDCloudAVStreamContext sharedInstance] adjustBeautyEnlargingLevel:newValue];
9//调整瘦脸
10[[BDCloudAVStreamContext sharedInstance] adjustBeautyThinningLevel:newValue];
- 注意,开启美颜需要在初始化拍摄器后。
- 注意:使用高级美颜时,需要申请对应权限,免费版本不支持此功能
开启滤镜
- 开启滤镜(applyEffect:)特效后,在预览窗口就可以看到滤镜效果。
- 代码示例如下:
1[[BDCloudAVStreamContext sharedInstance] applyEffect:filterID];
- 注意:当前filterID仅支持内置滤镜使用,用户在申请授权成功后,会得到滤镜资源包,具体使用可以参考短视频SDK DemoD拍摄模块
开启贴纸
- 开启滤镜(applyLocalStickerVideoFx: stickerModelPath: stickerType: stickerIdentify:)特效后,在预览窗口就可以看到贴纸效果。注:【v3.0.0】版本后,贴纸不在支持内置使用,详见下方下载贴纸
- 代码示例如下:
1- (void)setLocalSticker:(NSString *)stickerID andSubtype:(NSString *)subType withModel:(NSString *)model gestureSupport:(BOOL)isSupport {
2
3 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
4
5 dispatch_async(queue, ^{
6
7 if (stickerID == nil || stickerID.length == 0) {
8
9 [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx];
10
11 } else {
12 [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx];
13
14 NSString *path = [BDSSVFileUtils getDocumentPath]; //大文件放在沙盒下的Library/Caches
15
16 NSString *finishPath = [NSString stringWithFormat:@"%@/Stickers", path]; //保存解压后文件的文件夹的路径
17
18 NSString *resultpath = [NSString stringWithFormat:@"%@/%@.zip", finishPath, stickerID]; //下载的zip包存放路径
19
20 //模型地址
21
22 NSString *modelpath = [NSString stringWithFormat:@"%@/%@.zip", finishPath, model]
23
24 BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:resultpath];
25
26 BOOL isModelExist = [[NSFileManager defaultManager] fileExistsAtPath:modelpath];
27
28 //解压
29
30 if (isExist) {
31
32 NSString *localPath = [self localPath];
33
34
35
36 //资源地址
37
38 NSString *resultDestPath = [localPath stringByAppendingPathComponent:stickerID];
39
40 BOOL bSucess = [self unzipStickerPackage:resultpath destPath:resultDestPath];
41
42 NSString *modelDestPath = [localPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-model", stickerID]];
43
44 BOOL bModelSucess = NO;
45
46 if (isModelExist) {
47
48 bModelSucess = [self unzipStickerPackage:modelpath destPath:modelDestPath];
49
50 }
51
52 if (!bModelSucess) {
53
54 modelDestPath = @"";
55
56 }
57
58 if (bSucess) {
59
60 if (isSupport) {
61
62 [[BDCloudAVStreamContext sharedInstance] applyLocalStickerVideoFx:resultDestPath stickerModelPath:modelDestPath stickerType:subType stickerIdentify:@"10273" upportGesture:YES];
63
64 } else {
65
66 [[BDCloudAVStreamContext sharedInstance] applyLocalStickerVideoFx:resultDestPath stickerModelPath:modelDestPath stickerType:subType stickerIdentify:@"10273" upportGesture:NO];
67
68 }
69
70 }
71
72 } else {
73
74 [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx];
75
76 }
77
78 }
79
80 });
81
82}
- 注意:当前仅支持贴纸内置使用,用户在申请授权成功后,会得到贴纸资源包,具体使用可以参考短视频SDK DemoD拍摄模块
下载贴纸
【v3.0】版本后,/贴纸采用后下载方式使用/,开通license的同时可以在Console购买或选择贴纸信息
下载贴纸涉及两个接口,贴纸列表信息和贴纸下载使用。
- 贴纸列表信息,即用于产品展示,建议开发者提前获取贴纸列表,可缓存,减少用户等待。
下方获取贴纸列表数据实例代码:
1- (NSMutableArray<BDMVComposeStickerItem *> *)stickerItems {
2
3 if (!_stickerItems) {
4
5 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
6
7 _stickerItems = [[NSMutableArray<BDMVComposeStickerItem *> alloc] init];
8
9
10
11 /**在线获取贴纸信息**/
12
13 //建议提前获取贴纸列表&&缓存本地
14
15 [[BDCloudAVStreamContext sharedInstance] downloadStickerList:^(NSArray * _Nonnull stickerList,
16
17 NSError * _Nonnull error)
18
19 {
20
21 if (stickerList) {
22
23 for (NSDictionary *dict in stickerList) {
24
25 BDMVComposeStickerItem *item = [[BDMVComposeStickerItem alloc] initWitStickerDict:dict type:YES];
26
27 [self->_stickerItems addObject:item];
28
29 }
30
31 }
32
33 dispatch_semaphore_signal(semaphore);
34
35 }];
36
37 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
38
39 return _stickerItems;
40
41 }
42
43 return _stickerItems;
44
45}
贴纸下载使用,即用户选择某个贴纸后,下载贴纸并且加载使用。注:部分贴纸还会涉及模型下载,见下方示例代码
1- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
2
3
4
5 BDMVComposeStickerItem *item = self.stickers[indexPath.row];
6
7
8
9 if (item.state == BDMVComposeStickerItemState_Downloading || indexPath == self.selectedIndexPath) {
10
11 return;
12
13 }
14
15 // 移除当前贴纸
16
17 if (self.selectedIndexPath && self.selectedIndexPath.row < self.stickers.count) {
18
19 BDMVComposeStickerItem *item = self.stickers[self.selectedIndexPath.row];
20
21 item.state = BDMVComposeStickerItemState_Inexistence;
22
23 [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]];
24
25 }
26
27 //选择新贴纸
28
29 if (indexPath.row < self.stickers.count) {
30
31 if (![self isExistWithStickerItem:item]) {
32
33 //本地无缓存当前贴纸
34
35 item.state = BDMVComposeStickerItemState_Downloading;
36
37 [collectionView reloadItemsAtIndexPaths:@[indexPath]];
38
39 // 首先创建缓存文件夹
40
41 // 再下载贴纸列表
42
43 if (![self isExistWithStickerDir]) {
44
45 NSLog(@"缓存贴纸文件夹创建失败~~");
46
47 }
48
49 [[BDCloudAVStreamContext sharedInstance] downloadStickerVideoFx:item.identifier
50
51 downloadCallBack:^(NSDictionary * _Nonnull stickerDic,
52
53 NSError * _Nonnull error) {
54
55 if (stickerDic) {
56
57 BDMVComposeStickerItem *remoteItem = [[BDMVComposeStickerItem alloc] initWitStickerDict:stickerDic type:YES];
58
59 [self downloadStickerZip:remoteItem.decryptFile md5:remoteItem.fileMd5 completionHandler:^(NSString *md5){
60
61 // fix 用户快速切换贴纸
62
63 if ([md5 containsString:item.fileMd5]) {
64
65 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
66
67 dispatch_async(queue, ^{
68
69 // 部分贴纸还依赖模型文件
70
71 if (remoteItem.modelRemotePath) {
72
73 [self asynDownloadDecalsWithURL:[NSURL URLWithString:remoteItem.modelRemotePath] destination:remoteItem.model_sk completion:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
74
75 if (!error) {
76
77 [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type withModel:remoteItem.model_sk gestureSupport:item.gestureSupport];
78
79 }else {
80
81 NSLog(@"AR模型下载失败");
82
83 }
84
85 }];
86
87 }else {
88
89 [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type withModel:remoteItem.model_sk gestureSupport:item.gestureSupport];
90
91 }
92
93
94
95 dispatch_async(dispatch_get_main_queue(), ^{
96
97
98
99 if (self.selectedIndexPath) {
100
101 BDMVComposeStickerItem *selectedItem = self.stickers[self.selectedIndexPath.row];
102
103 selectedItem.state = BDMVComposeStickerItemState_Inexistence;
104
105 [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]];
106
107 }
108
109 item.state = BDMVComposeStickerItemState_OK;
110
111 self.selectedIndexPath = indexPath;
112
113 [collectionView reloadItemsAtIndexPaths:@[indexPath]];
114
115
116
117 });
118
119 });
120
121 } else {
122
123 remoteItem.state = BDMVComposeStickerItemState_Inexistence;
124
125 [collectionView reloadItemsAtIndexPaths:@[indexPath]];
126
127 }
128
129 }];
130
131 }
132
133 }];
134
135 } else {
136
137 //本地有缓存
138
139 NSLog(@"贴纸已缓存");
140
141 [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type withModel:item.model_sk gestureSupport:item.gestureSupport];
142
143 dispatch_async(dispatch_get_main_queue(), ^{
144
145 if (self.selectedIndexPath) {
146
147 BDMVComposeStickerItem *selectedItem = self.stickers[self.selectedIndexPath.row];
148
149 selectedItem.state = BDMVComposeStickerItemState_Inexistence;
150
151 [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]];
152
153 }
154
155 item.state = BDMVComposeStickerItemState_OK;
156
157 self.selectedIndexPath = indexPath;
158
159 [collectionView reloadItemsAtIndexPaths:@[indexPath]];
160
161 });
162
163 }
164
165 }
166
167}