AVFoundation二维码扫描和录制视频

之前使用过AVFoundation实现二维码扫描的功能,当初第一次接触这个框架,只是搜索资料,实现功能就草草了事了,最近要实现视频的录制功能,又用到了这个框架,而且发现,步骤跟实现二维码的时候十分相似,所以来总结一下。

使用AVFoundation拍照和录制视频的一般步骤如下:

  1. 创建AVCaptureSession对象。
  2. 使用AVCaptureDevice的静态方法获得需要使用的设备,例如拍照和录像就需要获得摄像头设备,录音就要获得麦克风设备。
  3. 利用输入设备AVCaptureDevice初始化AVCaptureDeviceInput对象。
  4. 初始化输出数据管理对象,如果要拍照就初始化AVCaptureStillImageOutput对象;如果拍摄视频就初始化AVCaptureMovieFileOutput对象。
  5. 将数据输入对象AVCaptureDeviceInput、数据输出对象AVCaptureOutput添加到媒体会话管理对象AVCaptureSession中。
  6. 创建视频预览图层AVCaptureVideoPreviewLayer并指定媒体会话,添加图层到显示容器中,调用AVCaptureSession的startRuning方法开始捕获。
  7. 将捕获的音频或视频数据输出到指定文件。

录制视频

@property (weak, nonatomic) IBOutlet UIView *viewContainer;
@property (weak, nonatomic) IBOutlet UIButton *videoButton;

@property (strong, nonatomic) AVCaptureSession *captureSession;
@property (strong, nonatomic) AVCaptureDevice *audioDevice;
@property (strong, nonatomic) AVCaptureDevice *captureDevice;
@property (strong, nonatomic) AVCaptureDeviceInput *audioDeviceInput;
@property (strong, nonatomic) AVCaptureDeviceInput *captureDeviceInput;
@property (strong, nonatomic) AVCaptureMovieFileOutput *captureMovieOutput; //视频输出流
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *capturePreviewLayer; // 相机预览化图层
    // 初始化会话
    if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {
        // 设置分辨率
        self.captureSession.sessionPreset = AVCaptureSessionPreset640x480;
    }
    
    // 获取输入数据 视频和音频
    NSError *error;
    self.captureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.captureDevice error:&error];
    if (error) {
        NSLog(@"Error Description:%@", error.localizedDescription);
    }

    self.audioDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.audioDevice error:&error];
    if (error) {
        NSLog(@"Error Description:%@", error.localizedDescription);
    }
    
    // 初始化输出对象
    self.captureMovieOutput = [[AVCaptureMovieFileOutput alloc] init];
    
    // 将设备输入添加到会话
    if ([self.captureSession canAddInput:self.captureDeviceInput] && [self.captureSession canAddInput:self.audioDeviceInput]) {
        [self.captureSession addInput:self.audioDeviceInput];
        [self.captureSession addInput:self.captureDeviceInput];
        
        AVCaptureConnection *captureConnection = [self.captureMovieOutput connectionWithMediaType:AVMediaTypeVideo];
        if ([captureConnection isVideoStabilizationSupported]) {
            captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
        }
    }
    
    // 将设备输出添加到会话中
    if ([self.captureSession canAddOutput:self.captureMovieOutput]) {
        [self.captureSession addOutput:self.captureMovieOutput];
    }
    
    // 创建预览化图层
    self.capturePreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    CALayer *layer = self.viewContainer.layer;
    self.capturePreviewLayer.frame = layer.bounds;
    // 填充模式
    self.capturePreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [layer insertSublayer:self.capturePreviewLayer below:self.videoButton.layer];
#pragma mark - Getter And Setter
- (AVCaptureSession *)captureSession{
    if (_captureSession == nil) {
        _captureSession = [[AVCaptureSession alloc] init];
    }
    return _captureSession;
}

- (AVCaptureDevice *)audioDevice{
    if (_audioDevice == nil) {
        _audioDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
    }
    return _audioDevice;
}

- (AVCaptureDevice *)captureDevice{
    if (_captureDevice == nil) {
        NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for (AVCaptureDevice *camera in cameras) {
            if ([camera position] == AVCaptureDevicePositionBack) {
                return camera;
            }
        }
    }
    return _captureDevice;
}

二维码扫描

    // 初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    // captureDevice创建输出流
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    if (!input) {
        NSLog(@"%@",[error localizedDescription]);
        return;
    }
    // 创建媒体数据输出流
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    // 实例化捕捉会话
    _caputureSession = [[AVCaptureSession alloc] init];
    // 输入流,输出流添加到会话
    [_caputureSession addInput:input];
    [_caputureSession addOutput:output];
    // 设置代理
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    // 设置输出媒体数据类型为QRCode
    [output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeInterleaved2of5Code, nil]];
    // 实例化预览图层
    _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_caputureSession];
    // 设置图层填充方式
    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
//    _videoPreviewLayer.frame = _viewPreview.layer.bounds;
    _videoPreviewLayer.frame = [UIScreen mainScreen].bounds;
    // 添加到预览图层
    [_viewPreview.layer addSublayer:_videoPreviewLayer];
    // 扫描范围
//    CGSize size = _viewPreview.bounds.size;
    CGSize size = [UIScreen mainScreen].bounds.size;
    CGRect cropRect = CGRectMake(_videoPreviewLayer.bounds.size.width/2 - (105/375.0)*SCREEN_WIDTH, (200/667.5)*SCREEN_HEIGHT, (210/375.0)*SCREEN_WIDTH, (210/667.5)*SCREEN_HEIGHT);
    [output setRectOfInterest:CGRectMake(cropRect.origin.y/size.height, cropRect.origin.x/size.width, cropRect.size.height/size.height, cropRect.size.width/size.width)];
    // 扫描框
    _boxView = [[UIView alloc] initWithFrame:_videoPreviewLayer.frame];
    _boxView.backgroundColor = [UIColor clearColor];
    UIImageView *scanView = [[UIImageView alloc] initWithFrame:_boxView.frame];
    scanView.image = [UIImage imageNamed:@"device_QR_scanning"];
    [_boxView addSubview:scanView];
    [_viewPreview addSubview:_boxView];
    // 开始扫描
    [_caputureSession startRunning];

你可能感兴趣的:(AVFoundation二维码扫描和录制视频)