短视频录制方法有很多,其中UIImagePickerController录制视频是系统封装好的,相对比较简单,不需要管理输入流和输出流以及相关的设备,只需要获取相应的录制结果即可,录制的画质也可以设置。利用这种方式录制视频中UI可以自己重新设置也可以用系统提供的UI(个人感觉系统提供的相对还不错)
- 录制视频的大致思路
- 创建捕捉会话
- 设置视频的输入
- 设置音频的输入
- 输出源设置,这里视频,音频数据会合并到一起输出,在代理方法中国也可以单独拿到视频或者音频数据,给AVCaptureMovieFileOutput指定路径,开始录制之后就会向这个路径写入数据
- 添加视频预览层
- 开始采集数据,这个时候还没有写入数据,用户点击录制后就可以开始写入数据
注意:在开始之前需要在plist文件中添加几个权限,这也是在APP访问手机的相机相册时候需要添加的权限
1、Privacy - Camera Usage Description 使用相机
2、Privacy - Microphone Usage Description 使用麦克风
3、Privacy - Photo Library Usage Description 使用相册
以下是实现UIImagePickerController录制视频的部分
引入头文件
#import
#import
引入代理以及设置相关的属性
@interface AVImagePickerController ()
@property(nonatomic,strong)UIImagePickerController * pickerView;
@property(nonatomic,assign)BOOL isVideo;
@property(nonatomic,strong) NSURL * videoURL;
@property(nonatomic,strong) UIView * camereaFace;
@property(nonatomic,assign) BOOL isCameraSupport;
@property(nonatomic,assign) BOOL isRearSupport;
@property(nonatomic,assign) BOOL isFontSupport;
@end
这是刚开始进入时候的页面,里边有两个按钮
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton * btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@"录制" forState:UIControlStateNormal];
btn.frame = CGRectMake(100, 100, 40, 40);
[btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
UIButton * btn1 = [UIButton buttonWithType:UIButtonTypeSystem];
[btn1 setTitle:@"拍照" forState:UIControlStateNormal];
btn1.frame = CGRectMake(100, 150, 40, 40);
[btn1 addTarget:self action:@selector(btnClick1) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn1];
}
-(void)btnClick
{
_isVideo = YES;
//这里需要判断相机是否能正常使用
if (self.isCameraSupport)
{
[self presentViewController:self.pickerView animated:YES completion:nil];
}
}
-(void)btnClick1
{
_isVideo = NO;
//判断相机是否能正常使用
if (self.isCameraSupport)
{
[self presentViewController:self.pickerView animated:YES completion:nil];
}
}
视频录制结束以后会调用该方法
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//根据info中的属性获取数据的类型
NSString * mediaType = [info objectForKey:UIImagePickerControllerMediaType];
//kUTTypeImage 属于照片格式的一种
if ([mediaType isEqualToString:(NSString * )kUTTypeImage]) {
UIImage * image;
if (self.pickerView.allowsEditing)//如果是编辑过的
{
image = [info objectForKey:UIImagePickerControllerEditedImage];
}else
{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
//保存到相册当中
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
//kUTTypeVideo 属于视频格式的一种
}else if ([mediaType isEqualToString:(NSString *)kUTTypeVideo])
{
if (@available(iOS 11.0, *)) {
//获取视频路径
NSURL * url = [info objectForKey:UIImagePickerControllerImageURL];
NSString * urlString = [url path];
//保存视频到相册中
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(urlString)) {
UISaveVideoAtPathToSavedPhotosAlbum(urlString, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}
} else {
// Fallback on earlier versions
}
}
}
视频保存后的回调
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
//将压缩后的文件保存到沙河路径当中,将来可以删除
NSString * pathDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString * newVideoPath = [NSString stringWithFormat:@"%@/Image",pathDocuments];
[self convertVideoQuailtyWithInputURL:[NSURL URLWithString:videoPath] outputURL:[NSURL URLWithString:newVideoPath]];
}
压缩视频
- (void) convertVideoQuailtyWithInputURL:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
{
//转码配置
AVURLAsset * avAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession * exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusUnknown:
{
}
break;
case AVAssetExportSessionStatusCompleted:
{
//转码成功
NSData *data = [NSData dataWithContentsOfFile:outputURL];
//将缓存删掉
NSFileManager * file = [NSFileManager defaultManager];
[file removeItemAtPath:[outputURL path] error:nil];
}
break;
default:
break;
}
}];
}
初始化展示页面(在手机上显示相头拍到的内容)
#pragma mark - Getter and Setter
-(UIImagePickerController *)pickerView
{
if (_pickerView == nil) {
_pickerView = [[UIImagePickerController alloc] init];
//imagePick 的来源,设置为相头
_pickerView.sourceType = UIImagePickerControllerSourceTypeCamera;
//使用哪个相头(后像头)
_pickerView.cameraDevice = UIImagePickerControllerCameraDeviceRear;
if (_isVideo) {
_pickerView.mediaTypes = @[(NSString *)kUTTypeMovie];
//拍照的质量
_pickerView.videoQuality = UIImagePickerControllerQualityTypeIFrame1280x720;
//设置摄像头模式
_pickerView.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
//设置散光灯
_pickerView.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
//设置录制的最大时间
_pickerView.videoMaximumDuration = 3;
}else
{
_pickerView.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
}
_pickerView.allowsEditing = YES;//允许编辑(拍完之后添加一个方形的边框进行筛选)
_pickerView.delegate = self;
//该方法可将系统自带的UI关掉,自己进行UI设计,将设计好的view赋值给_pickerView的cameraOverlayView 属性即可,其中当关闭系统UI的时候会导致开始录制按钮和停止的按钮消失不见,此时可通过调用[_pickerView startVideoCapture]方法即可开始录制视频,再调用[_pickerView stopVideoCapture]可以停止录像
//_pickerView.showsCameraControls = NO;
}
return _pickerView;
}
是否支持使用相机
-(BOOL)isCameraSupport
{
return [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
}
是否支持使用后置相头
-(BOOL)isRearSupport
{
return [UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear];
}
是否支持前置相头
-(BOOL)isFontSupport
{
return [UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront];
}
- 如果想自定义UI的话,可以设置pickerView的showsCameraControls属性为NO,然后将自定义的View赋值给pickerView的cameraOverlayView属性即可,其中
[_pickerView startVideoCapture];为录制视频
[_pickerView stopVideoCapture];为停止视频录制
- UIImagePickerController静态方法判断设备是否支持照相机/图片库/相册功能
/*
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary,
UIImagePickerControllerSourceTypeCamera,
UIImagePickerControllerSourceTypeSavedPhotosAlbum
};
*/
BOOL isCameraSupport = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
- UIImagePickerController静态方法判断设备是否支持前置摄像头/后置摄像头
/*
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,
UIImagePickerControllerCameraDeviceFront
};
*/
BOOL isRearSupport = [UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear];
- UIImagePickerController静态方法判断设备是否支持前置摄像头闪光灯/后置摄像头闪光灯
/*
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,
UIImagePickerControllerCameraDeviceFront
};
*/
BOOL isFlushSupport = [UIImagePickerController isFlashAvailableForCameraDevice:UIImagePickerControllerCameraDeviceRear];