前言
摄像头是移动设备的重要工具。随着移动端技术的发展,摄像头作为移动设备的图像采集工具,也变得越来越重要。不论是AR特效,计算机视觉技术,都离不开摄像头稳定高效地工作。
本文记录iOS的AVFoundation中Camera相关API的使用方法。
Camera架构
image.png我们可以看到,总的来说移动端的视觉设备是由,输入、会话、输出三部分组成。
//捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)
@property (nonatomic, strong) AVCaptureDevice *device;
//AVCaptureDeviceInput 代表输入设备,他使用AVCaptureDevice 来初始化
@property (nonatomic, strong) AVCaptureDeviceInput *input;
//输出文件
@property (nonatomic ,strong) AVCaptureMovieFileOutput *fileOutput;
//session:由他把输入输出结合在一起,并开始启动捕获设备(摄像头)
@property (nonatomic, strong) AVCaptureSession *session;
//图像预览层,实时显示捕获的图像
@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer;
上面的五个成员,就满足了我们上图模型中的各个位置。
初始化Camera
- (void)initCamera
{
self.recordPath = [self createRecordFilePath];
// AVCaptureDevicePositionFront 前置摄像头
self.device = [self cameraWithPosition:AVCaptureDevicePositionFront];
self.input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];
self.fileOutput = [[AVCaptureMovieFileOutput alloc] init];
self.session = [[AVCaptureSession alloc] init];
// 拿到的图像的大小可以自行设定
// AVCaptureSessionPreset320x240
// AVCaptureSessionPreset352x288
// AVCaptureSessionPreset640x480
// AVCaptureSessionPreset960x540
// AVCaptureSessionPreset1280x720
// AVCaptureSessionPreset1920x1080
// AVCaptureSessionPreset3840x2160
self.session.sessionPreset = AVCaptureSessionPreset640x480;
//输入输出设备结合
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:_fileOutput]) {
[self.session addOutput:_fileOutput];
}
//预览层的生成
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
CGFloat viewX = (_viewWidth - PREVIEW_WIDTH)/2;
CGFloat viewY = (_viewHeight - PREVIEW_HEIGHT)/2;
self.previewLayer.frame = CGRectMake( viewX, viewY, PREVIEW_WIDTH, PREVIEW_HEIGHT);
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:self.previewLayer];
//设备取景开始
[self.session startRunning];
}
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for ( AVCaptureDevice *device in devices )
if ( device.position == position ){
return device;
}
return nil;
}
上面的代码思路很清晰,大致的过程就是:
- 获取相机设备队象
- 从相机设备中获取输入流
- 创建输出流
- 创建会话
- 为会话添加输入,输出流
- 为预览层添加会话
- 启动会话
完成上面步骤后,我们就可以previewLayer中看到前置摄像头的画面了。
录制视频
- (void)recordMovie
{
AVCaptureConnection *captureConnection=[self.fileOutput connectionWithMediaType:AVMediaTypeVideo];
// 开启视频防抖模式
AVCaptureVideoStabilizationMode stabilizationMode = AVCaptureVideoStabilizationModeCinematic;
if ([self.input.device.activeFormat isVideoStabilizationModeSupported:stabilizationMode]) {
[captureConnection setPreferredVideoStabilizationMode:stabilizationMode];
}
// 预览图层和视频方向保持一致,这个属性设置很重要,如果不设置,那么出来的视频图像可以是倒向左边的。
captureConnection.videoOrientation=[_previewLayer connection].videoOrientation;
// 路径转换成 URL 要用这个方法,用 NSBundle 方法转换成 URL 的话可能会出现读取不到路径的错误
NSURL *fileUrl=[NSURL fileURLWithPath:_recordPath];
// 往路径的 URL 开始写入录像 Buffer ,边录边写
[self.fileOutput startRecordingToOutputFileURL:fileUrl recordingDelegate:self];
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections
{
NSLog(@"---- 开始录制 ----");
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
NSLog(@"---- 录制结束 ---- ");
}
#define VIDEOPREFIX @"zx_video_record_"
/**
Create the file path of record video. The name of file is created based on system timeInterval.
*/
- (NSString *)createRecordFilePath
{
// 获取时间戳
NSDate *datenow = [NSDate date];
NSInteger timeSp = [[NSNumber numberWithDouble:[datenow timeIntervalSince1970]] integerValue];
NSString *ts = [NSString stringWithFormat:@"%ld",(long)timeSp];
NSString *recordFilePath = [[[NSTemporaryDirectory() stringByAppendingString:VIDEOPREFIX]stringByAppendingString:ts]stringByAppendingString:@".mp4"];
return recordFilePath;
}
以上就是iOS中摄像头的基本使用。我们可以将摄像头获取的视频流,实时展示在预览Layer上。同时,也可以将视频流输出到文件中,完成录制。
如有问题,欢迎指正。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=cpjwfah0tqeo
网友评论