美文网首页
Camera Without Fear——iOS

Camera Without Fear——iOS

作者: oceanLong | 来源:发表于2018-06-26 11:00 被阅读17次

    前言

    摄像头是移动设备的重要工具。随着移动端技术的发展,摄像头作为移动设备的图像采集工具,也变得越来越重要。不论是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

    相关文章

      网友评论

          本文标题:Camera Without Fear——iOS

          本文链接:https://www.haomeiwen.com/subject/rdqskftx.html