阿里云短视频IOS-SDK录制接口及配置

录制的相关接口是在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:[BDCloudAVStreamContext 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.identifierdownloadCallBack:^(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]];}); } }}