| 头文件 | 功能说明 | 
|---|---|
| TuSDKRecordVideoCamera.h | 相机拍照录制类,支持参数设置,包含添加滤镜,贴纸,录制变声功能 | 
录制相机对象
遵守代理 TuSDKRecordVideoCameraDelegate
  @property (nonatomic, strong) TuSDKRecordVideoCamera *camera;
相机权限
  // 开启访问相机权限
  [TuSDKTSDeviceSettings checkAllowWithController:self
                                             type:lsqDeviceSettingsCamera
                                        completed:^(lsqDeviceSettingsType type, BOOL openSetting)
   {
       if (openSetting) {
           lsqLError(@"Can not open camera");
           return;
       }
       // 启动相机的方法
       // ...
   }];
相册权限
  // 测试相册访问权限
  [TuSDKTSAssetsManager testLibraryAuthor:^(NSError *error)
  {
      if (error) {
          [TuSDKTSAssetsManager showAlertWithController:self loadFailure:error];
      }else{
          NSLog(@"已经获得了相册的权限");
      }
  }];
滤镜列表,获取滤镜前往 TuSDK.bundle/others/lsq_tusdk_configs.json
TuSDK 滤镜信息介绍请参考文档自定义滤镜
需要先配置好 _filterCodes 中的 filterCode
  _filterCodes = @[@"Normal", kCameraFilterCodes];
启动相机对象
  // SessionPreset :采集画面的清晰度,建议 AVCaptureSessionPresetHigh 
  // 设置参考:AVFoundation/AVCaptureSession.h
  // cameraPosition:默认前置摄像头,[AVCaptureDevice lsqFirstFrontCameraPosition]
  _camera = [TuSDKRecordVideoCamera initWithSessionPreset:AVCaptureSessionPresetHigh
     cameraPosition:[AVCaptureDevice lsqFirstFrontCameraPosition]
         cameraView:_cameraView];
  // 在这里进行相关参数的配置
  // ........
  // 启动相机
  [_camera tryStartCameraCapture];
初始化相机时,以下几点需要注意
_camera.outputSize 和 _camera.videoQuality,影响保存视频的文件大小。
设置 outputSize 尺寸时,需要设置为 16 的倍数。
相机初始化之后可根据实际使用需求进行相关参数配置
设置录制文件格式(默认:lsqFileTypeQuickTimeMovie),可输出 MP4
  _camera.fileType = lsqFileTypeMPEG4;
输出视频的画质,影响保存视频文件的体积
  _camera.videoQuality = [TuSDKVideoQuality makeQualityWith:TuSDKRecordVideoQuality_Medium2];  
设置委托
  _camera.videoDelegate = self;
预览画面画幅设置,_cameraView 设置为全屏尺寸后,调节比例可以输出 1:1 画幅视频
  _camera.cameraViewRatio = 1.0;
指定比例后,建议输出画面尺寸比例和设定的 cameraViewRatio 保持一致,SDK 会根据设备情况自动输出最合适的尺寸
  _camera.outputSize = CGSizeMake(640, 640);
禁止触摸聚焦功能 (默认: NO)
   _camera.disableTapFocus = NO;
禁用持续自动对焦
  _camera.disableContinueFoucs = NO;
视频覆盖区域颜色 (默认:[UIColor blackColor])
  _camera.regionViewColor = [UIColor blackColor];
禁用前置摄像头自动水平镜像 (默认: NO,前置摄像头拍摄结果自动进行水平镜像)
  _camera.disableMirrorFrontFacing = NO;
闪光灯模式(默认是关闭:AVCaptureFlashModeOff)
  [_camera flashWithMode:AVCaptureFlashModeOff];
相机采集帧率,默认30帧; 开启智能贴纸时,帧率建议:25 ~ 30; 关闭智能贴纸时,帧率建议:30。(视机器性能决定)
  _camera.frameRate = 30;
不保存到相册,可在代理方法中获取 result.videoPath(默认:YES,录制完成自动保存到相册)
  _camera.saveToAlbum = NO;
保存到指定相册(需要将 saveToAlbum 置为 YES 后生效)
  _camera.saveToAlbumName = @"TuSDK";
启用智能贴纸(开启后,可使用动态贴纸)
  _camera.enableLiveSticker = YES;
设置是否启用人脸检测。 如果使用人脸贴纸及微整形功能,该项需置为 YES。 (注:须在相机启动之前调用)
  _camera.enableFaceDetection = YES;
设置图片水印,默认为空
  _camera.waterMarkImage = [UIImage imageNamed:@"sample.png"];
设置水印图片的位置
  _camera.waterMarkPosition = lsqWaterMarkBottomRight;
最大录制时长 15s
  _camera.maxRecordingTime = 15;
最小录制时长 3s
  _camera.minRecordingTime = 3;
录制模式:续拍模式
  _camera.recordMode = lsqRecordModeKeep;
设置默认滤镜(3.1.2 以后的版本请使用 TuSDKMediaFilterEffect 的 addMediaEffect 方法)
  [_camera switchFilterWithCode:_filterCodes[1]];
设置使用录制相机最小空间限制,开发者可根据需要自行设置(单位:字节 默认:50M)
  _camera.minAvailableSpaceBytes = 1024.f*1024.f*50.f;  
设置预览画面距离顶端距离,SDK 会自动调整预览画面位置
  CGFloat offset = 64/self.view.lsqGetSizeHeight;
  _camera.regionHandler.offsetPercentTop = offset;
开始录制:
  [_camera startRecording];
暂停录制:
   [_camera pauseRecording];
结束录制:
  [_camera finishRecording];   
取消录制:
  [_camera cancelRecording];
TuSDKMediaFilterEffect 滤镜特效
Demo 提供使用范例,用户可根据接口自定义修改相关使用
视图层级介绍:CameraViewController -> cameraView -> CameraControlMaskView -> CameraFilterPanelView 
CameraControlMaskView 引入头文件 #import "CameraFilterPanelView.h"
需要先配置好 _filterCodes 中的 filterCode ,再初始化滤镜栏
  // 滤镜列表,获取滤镜前往 TuSDK.bundle/others/lsq_tusdk_configs.json  
  // TuSDK 滤镜信息介绍 @see-https://tusdk.com/docs/ios/self-customize-filter
  _filterCodes = @[kCameraFilterCodes];
CameraViewController 实现CameraFilterPanelDelegate代理方法,切换滤镜 
   /**
   滤镜,美颜栏点击回调
   @param controlMask 相机界面遮罩视图
   @param filterPanel 滤镜回调事件
   */
  - (void)controlMask:(CameraControlMaskView *)controlMask didShowFilterPanel:(id<CameraFilterPanelProtocol>)filterPanel;
TuSDKMediaSkinFaceEffect 滤镜参数调节,包含参数名,参数值等
Demo 提供使用范例,用户可根据接口自定义修改相关使用
视图层级介绍:CameraViewController -> cameraView -> CameraControlMaskView -> CameraBeautyPanelView  
CameraControlMaskView 引入头文件 #import "CameraBeautyPanelView.h"
  /**
   当前正在应用的特效
   @param videoCamera 相机对象
   @param mediaEffectData 正在预览特效
   @since v3.2.0
   */
  - (void)onVideoCamera:(TuSDKVideoCameraBase *_Nonnull)videoCamera didApplyingMediaEffect:(id<TuSDKMediaEffect>_Nonnull)mediaEffectData;               
TuSDKPFStickerGroup 贴纸对象,包含贴纸id,缩略图地址等
Demo 提供使用范例,用户可根据接口自定义修改相关使用
视图层级介绍:CameraViewController -> cameraView -> CameraControlMaskView -> StickerPanelView -> StickerCategoryPageView 
CameraControlMaskView 引入头文件 #import "PropsPanelView.h"
CameraViewController 实现 PropsPanelViewDelegate 代理方法,添加贴纸
   /**
   贴纸选中回调
   @param propsPanelView 相机贴纸协议
   @param propsItem 贴纸组
   */
  - (void)propsPanel:(PropsPanelView *)propsPanelView didSelectPropsItem:(__kindof PropsItem *)propsItem;
创建属性
  @property (nonatomic, strong) TuSDKOnlineStickerDownloader *_stickerDownloader;
初始化贴纸在线下载工具
  - (TuSDKOnlineStickerDownloader *)stickerDownloader 
  {
      if (!_stickerDownloader) {
          _stickerDownloader = [[TuSDKOnlineStickerDownloader alloc] init];
          _stickerDownloader.delegate = self;
      }
      return _stickerDownloader;
  }
遵守 TuSDKOnlineStickerDownloaderDelegate 代理,实现下载管理
  #pragma mark - TuSDKOnlineStickerDownloaderDelegate
  - (void)onDownloadProgressChanged:(uint64_t)stickerGroupId progress:(CGFloat)progress changedStatus:(lsqDownloadTaskStatus)status;
  {
      if (status == lsqDownloadTaskStatusDowned || status == lsqDownloadTaskStatusDownFailed) 
      {
          BOOL success = status == lsqDownloadTaskStatusDowned;
          void (^downloaderCompletion)(BOOL success) = _downloadCallbackDic[@(stickerGroupId)];
          if (downloaderCompletion) {
              downloaderCompletion(success);
          }
      }
  }
Demo/Resources/Assets 提供了customStickerCategories.json 文件,用户可根据需要自行添加删除贴纸。
json 文件中信息如下
    {
      "categories": [
      {
          // 分类名称
          "categoryName": "搞怪cos",
          "stickers": [
          {  
              // 贴纸名称
              "name": "晕",
              // 贴纸 ID, stickerID
              "id": "1622",
              // 贴纸 preview URL 地址
              "previewImage": "https://img.tusdk.com/api/stickerGroup/img?id=1622"
          },
          {
              "name": "绅士礼服",
              "id": "1566",
              "previewImage": "https://img.tusdk.com/api/stickerGroup/img?id=1566"
          }],
      },
      {
          "categoryName": "场景",
          "stickers": [
          {
              "name": "星球",
              "id": "1578",
              "previewImage": "https://img.tusdk.com/api/stickerGroup/img?id=1578"
          }]
      },
      {
          "categoryName": "萌宠",
          "stickers": [
          {
              "name": "白狐狸",
              "id": "1602",
              "previewImage": "https://img.tusdk.com/api/stickerGroup/img?id=1602"
          }]
      }]
      }
StickerPanelView 中 -(void)loadStickers; 方法中对 json 文件进行了读取使用
  // 获取本地所有贴纸,并创建索引字典
  NSArray<TuSDKPFStickerGroup *> *allLocalStickers = [[TuSDKPFStickerLocalPackage package] getSmartStickerGroups];
  NSMutableDictionary *localStickerDic = [NSMutableDictionary dictionary];
  for (TuSDKPFStickerGroup *sticker in allLocalStickers) {
      localStickerDic[@(sticker.idt)] = sticker;
  }
  // 遍历 categories 字段的数组,其每个元素是字典
  NSArray *jsonCategories = jsonDic[kStickerCategoryCategoriesKey];
  NSMutableArray *stickerCategories = [NSMutableArray array];
  for (NSDictionary *categoryDic in jsonCategories) {
      StickerCategory *stickerCategory = [[StickerCategory alloc] init];
      stickerCategory.name = categoryDic[kStickerCategoryNameKey];
      // 通过 idt 进行筛选,若本地存在该贴纸,则使用本地的贴纸对象;否则为在线贴纸
      NSMutableArray *stickers = [NSMutableArray array];
      for (NSDictionary *stickerDic in categoryDic[kStickerCategoryStickersKey]) {
          NSInteger idt = [stickerDic[kStickerIdKey] integerValue];
          TuSDKPFStickerGroup *sticker = localStickerDic[@(idt)];
          if (sticker) {
              [stickers addObject:sticker];
          } else {
              // 在线贴纸对象创建
              OnlineStickerGroup *onlineSticker = [[OnlineStickerGroup alloc] init];
              sticker = onlineSticker;
              onlineSticker.idt = idt;
              onlineSticker.previewImage = stickerDic[kStickerPreviewImageKey];
              onlineSticker.name = stickerDic[kStickerNameKey];
              [stickers addObject:sticker];
          }
      }
      // 贴纸数组添加各个分类贴纸数组
      stickerCategory.stickers = stickers.copy;
      [stickerCategories addObject:stickerCategory];
  }
动态贴纸的在线下载功能实现需要贴纸 ID(stickerID),如 json 文件中配置的贴纸已经打包在本地,那么界面将不会展示该贴纸可以进行在线下载
控制台操作,动态贴纸库,查看详情可看到对应的 贴纸 ID 和贴纸名称。
可以动态下发包含贴纸 ID,categoryName 和 previewImage 的 URL 地址的 json 数据,来替换 demo customStickerCategories.json 文件来获取贴纸 ID,这部分为自定义操作。
customStickerCategories.json 不是必需文件,用户可自定义或调整。
清理或更新本地动态贴纸资源,可通过以下方式进行删除贴纸操作,然后选择重新下载或以后下载
  TuSDKPFStickerGroup *sticker = self.stickerCategorys[pageView.pageIndex].stickers[index];
  [[TuSDKPFStickerLocalPackage package] removeDownloadWithIdt:sticker.idt];
  // 完成删除操作后,记得重载数据刷新界面        
  // [self reloadDataWithStickerId:sticker.idt];
TuSDKMediaMonsterFaceEffect 变脸特效(哈哈镜)
特效类型:
  typedef NS_ENUM(NSUInteger,TuSDKMonsterFaceType) {
      /** 哈哈镜 - 大鼻子  @since v3.2.1 */
      TuSDKMonsterFaceTypeBigNose,
      /** 哈哈镜 - 大饼脸 @since v3.2.1 */
      TuSDKMonsterFaceTypePieFace,
      /** 哈哈镜 - 国字脸 @since v3.2.1 */
      TuSDKMonsterFaceTypeSquareFace,
      /** 哈哈镜 - 厚嘴唇 @since v3.2.1 */
      TuSDKMonsterFaceTypeThickLips,
      /** 哈哈镜 - 眯眯眼 @since v3.2.1 */
      TuSDKMonsterFaceTypeSmallEyes,
      /** 哈哈镜 - 木瓜脸 @since v3.2.1 */
      TuSDKMonsterFaceTypePapayaFace,
      /** 哈哈镜 - 蛇精脸 @since v3.2.1 */
      TuSDKMonsterFaceTypeSnakeFace,
  };
  * 默认添加一个变脸特效
  TuSDKMediaMonsterFaceEffect *monsterEfffect = [[TuSDKMediaMonsterFaceEffect alloc]initWithMonsterFaceType:TuSDKMonsterFaceTypePapayaFace];
  [self.camera addMediaEffect:monsterEfffect];
变调参数设置须在点击录制按钮前调用,支持断点录制下不同声调的变换
支持的声调:正常,怪兽,大叔,女生,萝莉
  /**
   * 录制变声类型
   *
   * @since v3.0.1
   */
  typedef NS_ENUM(NSUInteger, lsqSoundPitch) {
      // 正常
      lsqSoundPitchNormal,
      // 怪兽
      lsqSoundPitchMonster,
      // 大叔
      lsqSoundPitchUncle,
      // 女生
      lsqSoundPitchGirl,
      // 萝莉
      lsqSoundPitchLolita,
  };
不支持自定义的声调调节
  // 变声开关回调
  - (void)moreMenu:(CameraMoreMenuView *)moreMenu didSwitchPitchType:(lsqSoundPitch)pitchType {
      _camera.soundPitch = pitchType;
  }
在 TuSDKVideoCameraDelegate 方法中获取录制结果
录制视频的结果获取
  - (void)onVideoCamera:(TuSDKRecordVideoCamera *)camerea result:(TuSDKVideoResult *)result 
  {
      // 通过相机初始化设置  _camera.saveToAlbum = NO;  result.videoPath 拿到视频的临时文件路径
      if (result.videoPath) {
          [[TuSDK shared].messageHub showSuccess:@"录制完成"];
          // 进行自定义操作,例如保存到相册
          UISaveVideoAtPathToSavedPhotosAlbum(result.videoPath, nil, nil, nil);
          [[TuSDK shared].messageHub showSuccess:@"保存成功"];
      } else {
          [[TuSDK shared].messageHub showSuccess:@"保存成功"];
      }
      // 保存操作执行后,记得更新界面 UI 的状态
      // [_captureMode reset];
  }
saveToAlbum 置为 YES,在录制达到最大时长或中途保存后,会自动保存到相册中。saveToAlbum 置为 NO,在录制达到最大时长或中途保存后,会通过 result.videoPath 获取到对应视频的临时文件,可进行自定义操作。拍照结果获取
  - (void)onVideoCamera:(id<TuSDKVideoCameraInterface>)camera takedResult:(TuSDKResult *)result error:(NSError *)error {
      if (result.image) {
          NSLog(@"result.image: %@",result.image);
          // 进行自定义操作,例如保存到相册
          // UIImageWriteToSavedPhotosAlbum(result.image, NULL, NULL, NULL);
      }
  }
录制出现错误的各种错误信息及处理
  /**
   *  组件错误类型
   */
  typedef NS_ENUM(NSInteger, lsqRecordError)
  {
      /**
       *  未知
       */
      lsqRecordVideoErrorUnknow,
      /**
       * 存储空间不足
       */
      lsqRecordVideoErrorNotEnoughSpace,
      /**
       *  小于最小录制时长
       */
      lsqRecordVideoErrorLessMinDuration,
      /**
       *  大于最大录制时长
       */
      lsqRecordVideoErrorMoreMaxDuration,
      /**
       * 文件保存失败
       */
      lsqRecordVideoErrorSaveFailed,
  };
  - (void)onVideoCamera:(TuSDKRecordVideoCamera *)camerea failedWithError:(NSError*)error;
  {
     switch (error.code) {
          case lsqRecordVideoErrorUnknow:
              break;
          default:
          break;
       }
    }
相机录制操作过程中的各种录制状态
  /**
   *  录制状态
   */
  typedef NS_ENUM(NSInteger,lsqRecordState)
  {
      /** 正在录制 */
      lsqRecordStateRecording,
      /** 录制完成 */
      lsqRecordStateRecordingCompleted,
      /** 正在保存 */
      lsqRecordStateSaveing,
      /** 保存完成 */
      lsqRecordStateSaveingCompleted,
      /** 正在合并视频 */
      lsqRecordStateMerging,
      /** 已暂停 */
      lsqRecordStatePaused,
      /** 已取消 */
      lsqRecordStateCanceled,
  };
  - (void)onVideoCamera:(TuSDKRecordVideoCamera *)camerea recordStateChanged:(lsqRecordState)state;
  {
      switch (state) {
          case lsqRecordStatePaused:
              break;
          default:
          break;
       }
  }
相机的各种状态
  /**
   *  视频相机状态
   */
  typedef NS_ENUM(NSInteger, lsqCameraState)
  {
      /**
       *  未知
      */
      lsqCameraStateUnknow = 0,
      /**
       *  正在启动
       */
      lsqCameraStateStarting = 1,
      /**
       *  启动完成
       */
      lsqCameraStateStarted = 2,
      /**
       * 正在拍摄
       */
      lsqCameraStateCapturing = 3,
      /**
       * 录制暂停
       */
      lsqCameraStatePaused = 4,
      /**
       * 拍摄完成
       */
      lsqCameraStateCaptured = 5
  };
  - (void)onVideoCamera:(id<TuSDKVideoCameraInterface>)camera stateChanged:(lsqCameraState)state {
          switch (state) {
              case lsqCameraStateStarting:
                  // 相机正在启动
                  NSLog(@"TuSDKRecordVideoCamera state: 相机正在启动");
                  break;
              default:
                  break;
          }
  }