头文件 | 功能说明 |
---|---|
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;
}
}