什么是视频录制
视频录制其实就是一个类似于拍电影的过程,通过手机的摄像头和麦克风,录入声音和画面,然后经过一个加工厂加工,然后导出,就变成了我们口中定义的视频。接下来,我会带大家看一下,iOS中的视频录制到底是怎么做的,让大家能初步地写出一个录制视频的小demo。当然,还会教大家怎么进行视频图像的捕获还有压缩。
iOS如何进行视频录制
- 视频录制需要导入一个框架--
AVFoundation
框架
#import <AVFoundation/AVFoundation.h>
- 根据前言的分析,所以我们需要设置四个属性来进行视频录制的相关配置
//输入声音
@property (nonatomic, strong) AVCaptureDeviceInput *inputAudio;
//输入画面
@property (nonatomic, strong) AVCaptureDeviceInput *inputVideo;
//会话属性
@property (nonatomic, strong) AVCaptureSession *session;
//导出
@property (nonatomic, strong) AVCaptureMovieFileOutput *output;
- 我们就做一个简单点的demo,在touchesBegan方法中进行视频录制相关操作
// 3.创建对象,并且实例化
// 3.1创建一个设备
// 声音
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
self.inputAudio = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
// 3.2画面
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.inputVideo = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil];
// 3.3会话
self.session = [[AVCaptureSession alloc] init];
// 3.4 导出
self.output = [[AVCaptureMovieFileOutput alloc] init];
- 添加到加工厂(输入&输出)
if ([self.session canAddInput:self.inputAudio]) {
[self.session addInput:self.inputAudio];
}
if ([self.session canAddInput:self.inputVideo]) {
[self.session addInput:self.inputVideo];
}
if ([self.session canAddOutput:self.output]) {
[self.session addOutput:self.output];
}
// 添加一个预览的图层
AVCaptureVideoPreviewLayer *prelayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
prelayer.frame = self.view.bounds;
// [self.view.layer addSublayer:prelayer];
[self.view.layer insertSublayer:prelayer atIndex:0];
- 开启加工厂
[self.session startRunning];
- 添加视频录制开关按钮
// 视频录制的开关
- (IBAction)startOrClose:(id)sender {
if ([self.output isRecording]) {
// 正在录制
[self.output stopRecording];
} else {
// 没有录制
// 获取沙盒路径,用于存储
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"录制的视频.mov"];
// 开始录制
[self.output startRecordingToOutputFileURL:[NSURL fileURLWithPath:path] recordingDelegate:self];
}
}
- 监听视频录制的进度
#pragma mark - AVCaptureFileOutputRecordingDelegate
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error;
{
NSLog(@"完成录制");
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections
{
NSLog(@"开始录制");
}
为什么需要做视频截图
视频截图就是截取视频播放中的某一帧(关键帧)画面。
有时候当我们观看视频的时候,或者观看直播的时候,看到一些好玩,有趣的画面需要和朋友进行分享的时候,就要用到视频截图这个功能了。
下面,我们一起来看一下如何进行视频截图。
如何进行视频截图
- 导入框架
#import <AVFoundation/AVFoundation.h>
- 核心代码
创建视频资源对象
// 1.1获取资源的url
NSURL *url = [[NSBundle mainBundle] URLForResource:@"movie.mp4" withExtension:nil];
// 1.2对url进行封装
AVAsset *asset = [AVAsset assetWithURL:url];
// 1.创建一个视频截取的截取器
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
// <#int64_t value#>: 截取的时间
// <#int32_t timescale#>: 每秒播放多少帧
CMTime time = CMTimeMake(23, 1);
NSValue *value = [NSValue valueWithCMTime:time];
[generator generateCGImagesAsynchronouslyForTimes:@[value] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {
// UI的更新一定要在主线程进行,要不然不能够时时获得更新
dispatch_sync(dispatch_get_main_queue(), ^{
self.picImageView.image = [UIImage imageWithCGImage:image];
});
}];
为什么要进行视频压缩
通常录制出来的原视频都会很大,如果不压缩就进行上传,一个是浪费用户的流量,二个会造成上传时间过长,影响用户体验。
如何进行视频压缩
获取视频的位置-------相册
创建相册控制器对象,访问相册
// 创建访问相册的控制器对象
UIImagePickerController *picker = [[UIImagePickerController alloc]
init];
- 访问相册之前,需要判断是否存在相册
// 0. 判断是否有相册
if (![UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{NSLog(@" ");
return;}
- 弹出控制器
[self presentViewController:picker animated:YES completion:nil];
- 访问相册可以通过不同的方式,改变的方法为:
设置他的资源类型
/**
UIImagePickerControllerSourceTypePhotoLibrary, //照片库 UIImagePickerControllerSourceTypeCamera, //照相机
UIImagePickerControllerSourceTypeSavedPhotosAlbum //相册
*/
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
- 可以看到,相册中没有视频,这是因为需要设置 媒体类型才能看到
// 设置媒体类型
picker.mediaTypes = [UIImagePickerControlleravailableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
- 看到视频后,我们需要拿到该视频,才能进行压缩操作,所以需要设置代理
picker.delegate = self;
并且遵守协议
@interface ViewController () <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
实现方法:
// MARK: - delegate方法
// 选择照片或者是视频时 调用
// info: 相关参数
- (void)imagePickerController:(UIImagePickerController *)pickerdidFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
// 选择 取消时 调用
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
- 打印代理方法中的info这个参数,可以看到里面包含该视频的地址, 接收该地址
NSLog(@"%@",info);
NSURL *url = info[UIImagePickerControllerMediaURL];
- 视频压缩的原理: 把视频用低质量导出
- 创建视频资源对象
// asset :资源
AVAsset *asset = [AVAsset assetWithURL:url];
- 创建视频导出会话
/**
AVAssetExportPresetLowQuality //低质量
AVAssetExportPresetMediumQuality//中质量
AVAssetExportPresetHighestQuality//高质量
*/
// 创建视频导出会话
// presetName : 视频导出质量
AVAssetExportSession *session = [AVAssetExportSessionexportSessionWithAsset:asset presetName:AVAssetExportPresetLowQuality];
- 导出视频:
// 导出
[session exportAsynchronouslyWithCompletionHandler:^{NSLog(@" ");
}];
- 导出视频之前,需要我们确定导出到哪里
获取沙盒路径//
NSString *filePath =[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
// session.outputURL = [NSURL fileURLWithPath:filePath];
- 演示视频导出, 报错, 查看原因,发现视频导出错的原因是没有设置视频导出的类型根据属性介绍,可以看到需要查看session.supportedFileTypes属性,打印该属性
// NSLog(@"%@",session.supportedFileTypes);
/**
"com.apple.quicktime-movie", quicktime-movie 类型
"public.mpeg-4" mp4 类型
*/
// 视频导出的文件类型
session.outputFileType = @"public.mpeg-4";