文档简介:
录制的相关接口是在BDCloudAVStreamContext类里,包括采集预览(startPreview),录制(startRecording:),添加视频美颜(applyBeautyBaseVideoFx)等。
注意:百度云拍摄器SDK所有的类都是以“BDCloud”开头。
BDCloudAVStreamContext类
BDCloudAVStreamContext是拍摄器SDK的流媒体上下文类,是接入拍摄器SDK产品的入口。开始使用前,需要先初始化BDCloudAVStreamContext类,注意BDCloudAVStreamContext是单例类。
BDCloudAVStreamContext初始化代码如下
_avStreamContext = [BDCloudAVStreamContext sharedInstance];
BDCloudAVStreamContext销毁代码如下
[_avStreamContext destroyInstance];
_avStreamContext = nil;
注意:BDCloudAVStreamContext初始化后,需要调用verifySDKLicense: completionHandler:验证客户的合法性,其中appid即用户申请的licenseID,若未申请授权,请参考快速接入
BDCloudAVStreamSettings类配置
BDCloudAVStreamSettings是拍摄器SDK配置项,支持客户调整摄像头位置、摄像头类型、视频维度(分辨率)、视频帧速率、视频帧码率及手电筒、对焦、曝光补光、预览放大缩小、预览模式。
考虑到配置项较多且偏专业,拍摄器SDK提供默认配置项,代码如下:
BDCloudAVStreamSettings *settings = [BDCloudAVStreamSettings defaultSettings];
预览前设置
完成流媒体上下文初始化及配置项后,下面就要创建预览前配置,创建拍摄器及预览画面,代码如下:
// 使用配置项创建拍摄器
_avStreamContext = [_avStreamContext initWithCaptureConfig:settings];
// 获取拍摄器预览界面
UIView *preview = _avStreamContext.view;
// 设置预览界面展示区域
preview.frame = self.view.bounds;
// 设置拍摄器回调代理
_avStreamContext.delegate = self;
// 将预览界面添加到用户控制器上
[self.view insertSubview:preview atIndex:0];
启动预览
启动预览对应startPreview接口,此接口发检查用户照相机和麦克风系统权限。
录制与停止录制
录制
- 调用录制接口前startRecording: recordCallBack:,需要先创建录制文件的路径,建议用户使用.MOV和.mp4文件
- 录制接口在写入文件的同时,会不断回调给使用方,用户需要关心回调状态BDCloudAVStreamFileOutputState。
- 代码示例如下:
[[BDCloudAVStreamContext sharedInstance] startRecording:recordVideoPath recordCallBack:^
(BDCloudAVStreamFileOutputState state, double recordSecond, NSError *error) { switch (state) { case BDCloudAVStreamFileOutputStateStarting: break; case BDCloudAVStreamFileOutputStateStarted: break; case BDCloudAVStreamFileOutputStateCancel: break; case BDCloudAVStreamFileOutputStateError: //错误信息 break; case BDCloudAVStreamFileOutputStateEnding: //录制结束 break; case BDCloudAVStreamFileOutputStateEnded: break; default: break; } }];
停止录制
- 代码示例如下:
[[BDCloudAVStreamContext sharedInstance] stopRecording];
录制设置
- 设置闪光灯是否开启,代码示例如下:
AVCaptureFlashMode _flashMode;
_flashMode = _flashMode == AVCaptureFlashModeOff ? AVCaptureFlashModeOn : AVCaptureFlashModeOff;
[[BDCloudAVStreamContext sharedInstance] toggleFlash:_flashMode];
if (_flashMode == AVCaptureFlashModeOff) {
[[BDCloudAVStreamContext sharedInstance] toggleTorch:NO];
}else {
[[BDCloudAVStreamContext sharedInstance] toggleTorch:YES];
}
- 设置自动对焦
[[BDCloudAVStreamContext sharedInstance] setCameraContinuousAutofocus:YES]; [[BDCloudAVStreamContext sharedInstance] setCameraFocusPointOfInterest:[BDCloudAVStr
eamContext sharedInstance].view.center];
- 设置曝光点
[[BDCloudAVStreamContext sharedInstance] setCameraExposurePointOfInterest:[BDCloudAVStreamContext
sharedInstance].view.center];
- 设置缩放
[[BDCloudAVStreamContext sharedInstance] setCameraZoomFactor:1.3];
开启美颜
- 添加美颜(applyBeautyBaseVideoFx)特效后,在预览窗口就可以看到美颜效果。录制视频时,用户需要根据手机性能任意选择带美颜录制或者不带美颜录制。 美颜特效分为基础美颜(美白、磨皮)和高级美颜(大眼、瘦脸)。
- 开启美颜,代码示例如下:
//开启美颜
[_avStreamContext applyBeautyBaseVideoFx];
//调整美白
[[BDCloudAVStreamContext sharedInstance] adjustBeautyWhiteLevel:newValue];
//调整磨皮
[[BDCloudAVStreamContext sharedInstance] adjustBeautyBlurLevel:newValue];
//调整大眼
[[BDCloudAVStreamContext sharedInstance] adjustBeautyEnlargingLevel:newValue];
//调整瘦脸
[[BDCloudAVStreamContext sharedInstance] adjustBeautyThinningLevel:newValue];
- 注意,开启美颜需要在初始化拍摄器后。
- 注意:使用高级美颜时,需要申请对应权限,免费版本不支持此功能
开启滤镜
- 开启滤镜(applyEffect:)特效后,在预览窗口就可以看到滤镜效果。
- 代码示例如下:
[[BDCloudAVStreamContext sharedInstance] applyEffect:filterID];
- 注意:当前filterID仅支持内置滤镜使用,用户在申请授权成功后,会得到滤镜资源包,具体使用可以参考短视频SDK DemoD拍摄模块
开启贴纸
- 开启滤镜(applyLocalStickerVideoFx: stickerModelPath: stickerType: stickerIdentify:)特效后,在预览窗口就可以看到贴纸效果。注:【v3.0.0】版本后,贴纸不在支持内置使用,详见下方下载贴纸
- 代码示例如下:
- (void)setLocalSticker:(NSString *)stickerID andSubtype:(NSString *)subType
withModel:(NSString *)model gestureSupport:(BOOL)isSupport { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ if (stickerID == nil || stickerID.length == 0) { [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx]; } else { [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx]; NSString *path = [BDSSVFileUtils getDocumentPath]; //大文件放在沙盒下的Library/Caches NSString *finishPath = [NSString stringWithFormat:@"%@/Stickers", path]; //保存解压后文件的文件夹的路径 NSString *resultpath = [NSString stringWithFormat:@"%@/%@.zip", finishPath, stickerID]; //下载的zip包存放路径 //模型地址 NSString *modelpath = [NSString stringWithFormat:@"%@/%@.zip", finishPath, model] BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:resultpath]; BOOL isModelExist = [[NSFileManager defaultManager] fileExistsAtPath:modelpath]; //解压 if (isExist) { NSString *localPath = [self localPath]; //资源地址 NSString *resultDestPath = [localPath stringByAppendingPathComponent:stickerID]; BOOL bSucess = [self unzipStickerPackage:resultpath destPath:resultDestPath]; NSString *modelDestPath = [localPath stringByAppendingPathComponent:[NSString
stringWithFormat:@"%@-model", stickerID]]; BOOL bModelSucess = NO; if (isModelExist) { bModelSucess = [self unzipStickerPackage:modelpath destPath:modelDestPath]; } if (!bModelSucess) { modelDestPath = @""; } if (bSucess) { if (isSupport) { [[BDCloudAVStreamContext sharedInstance] applyLocalStickerVideoFx:resultDestPath
stickerModelPath:modelDestPath stickerType:subType stickerIdentify:@"10273" upportGesture:YES]; } else { [[BDCloudAVStreamContext sharedInstance] applyLocalStickerVideoFx:resultDestPath
stickerModelPath:modelDestPath stickerType:subType stickerIdentify:@"10273" upportGesture:NO]; } } } else { [[BDCloudAVStreamContext sharedInstance] disabledStickerVideoFx]; } } }); }
- 注意:当前仅支持贴纸内置使用,用户在申请授权成功后,会得到贴纸资源包,具体使用可以参考短视频SDK DemoD拍摄模块
下载贴纸
【v3.0】版本后,/贴纸采用后下载方式使用/,开通license的同时可以在Console购买或选择贴纸信息
下载贴纸涉及两个接口,贴纸列表信息和贴纸下载使用。
- 贴纸列表信息,即用于产品展示,建议开发者提前获取贴纸列表,可缓存,减少用户等待。
下方获取贴纸列表数据实例代码:
- (NSMutableArray<BDMVComposeStickerItem *> *)stickerItems {
if (!_stickerItems) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
_stickerItems = [[NSMutableArray<BDMVComposeStickerItem *> alloc] init];
/**在线获取贴纸信息**/
//建议提前获取贴纸列表&&缓存本地
[[BDCloudAVStreamContext sharedInstance] downloadStickerList:^(NSArray * _Nonnull stickerList,
NSError * _Nonnull error)
{
if (stickerList) {
for (NSDictionary *dict in stickerList) {
BDMVComposeStickerItem *item = [[BDMVComposeStickerItem alloc] initWitStickerDict:dict type:YES];
[self->_stickerItems addObject:item];
}
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return _stickerItems;
}
return _stickerItems;
}
贴纸下载使用,即用户选择某个贴纸后,下载贴纸并且加载使用。注:部分贴纸还会涉及模型下载,见下方示例代码
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { BDMVComposeStickerItem *item = self.stickers[indexPath.row]; if (item.state == BDMVComposeStickerItemState_Downloading || indexPath == self.selectedIndexPath) { return; } // 移除当前贴纸 if (self.selectedIndexPath && self.selectedIndexPath.row < self.stickers.count) { BDMVComposeStickerItem *item = self.stickers[self.selectedIndexPath.row]; item.state = BDMVComposeStickerItemState_Inexistence; [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]]; } //选择新贴纸 if (indexPath.row < self.stickers.count) { if (![self isExistWithStickerItem:item]) { //本地无缓存当前贴纸 item.state = BDMVComposeStickerItemState_Downloading; [collectionView reloadItemsAtIndexPaths:@[indexPath]]; // 首先创建缓存文件夹 // 再下载贴纸列表 if (![self isExistWithStickerDir]) { NSLog(@"缓存贴纸文件夹创建失败~~"); } [[BDCloudAVStreamContext sharedInstance] downloadStickerVideoFx:item.identifier downloadCallBack:^(NSDictionary * _Nonnull stickerDic, NSError * _Nonnull error) { if (stickerDic) { BDMVComposeStickerItem *remoteItem = [[BDMVComposeStickerItem alloc] initWitStickerDict:stickerDic type:YES]; [self downloadStickerZip:remoteItem.decryptFile md5:remoteItem.fileMd5 completionHandler:^(NSString *md5){ // fix 用户快速切换贴纸 if ([md5 containsString:item.fileMd5]) { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ // 部分贴纸还依赖模型文件 if (remoteItem.modelRemotePath) { [self asynDownloadDecalsWithURL:[NSURL URLWithString:remoteItem.
modelRemotePath] destination:remoteItem.model_sk completion:^(NSURLResponse *response, NSURL *filePath, NSError *error) { if (!error) { [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type
withModel:remoteItem.model_sk gestureSupport:item.gestureSupport]; }else { NSLog(@"AR模型下载失败"); } }]; }else { [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type
withModel:remoteItem.model_sk gestureSupport:item.gestureSupport]; } dispatch_async(dispatch_get_main_queue(), ^{ if (self.selectedIndexPath) { BDMVComposeStickerItem *selectedItem = self.stickers[self.selectedIndexPath.row]; selectedItem.state = BDMVComposeStickerItemState_Inexistence; [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]]; } item.state = BDMVComposeStickerItemState_OK; self.selectedIndexPath = indexPath; [collectionView reloadItemsAtIndexPaths:@[indexPath]]; }); }); } else { remoteItem.state = BDMVComposeStickerItemState_Inexistence; [collectionView reloadItemsAtIndexPaths:@[indexPath]]; } }]; } }]; } else { //本地有缓存 NSLog(@"贴纸已缓存"); [self setLocalSticker:item.fileMd5 andSubtype:item.sub_type withModel:item.model_sk gestureSupport:item.gestureSupport]; dispatch_async(dispatch_get_main_queue(), ^{ if (self.selectedIndexPath) { BDMVComposeStickerItem *selectedItem = self.stickers[self.selectedIndexPath.row]; selectedItem.state = BDMVComposeStickerItemState_Inexistence; [collectionView reloadItemsAtIndexPaths:@[self.selectedIndexPath]]; } item.state = BDMVComposeStickerItemState_OK; self.selectedIndexPath = indexPath; [collectionView reloadItemsAtIndexPaths:@[indexPath]]; }); } } }