iOS 10 AVFoundation录制采集视频

//
//  YLPlayerViewController.m
//  YLPlayer
//
//  Created by 谭 on 2019/7/5.
//  Copyright © 2019 Bksx-cp. All rights reserved.
//

#import "YLPlayerViewController.h"
#import 
#import 
#import 
#import "Masonry.h"

@interface YLPlayerViewController ()
/*
    调配银饰品输入输出之间的数据流
 */
@property (nonatomic,strong) AVCaptureSession *captureSession;
/*
    捕获的视频数据预览图层
 */
@property (nonatomic,strong) AVCaptureVideoPreviewLayer *previewLayer;
/*
    输出数据文件
 */
@property (nonatomic,strong) AVCaptureMovieFileOutput *captureMovieFileOutput;
/*
    捕获会话中特定捕获输入对和捕获输出对象之间的连接
 */
@property (nonatomic,strong) AVCaptureConnection *captureConnection;
/*
    输入输出设备
 */
@property (nonatomic,strong) AVCaptureDevice *captureDevice;
/*
    设备输入数据源
 */
@property (nonatomic,strong) AVCaptureDeviceInput *captureDeviceInput;
/*
    音频设备
 */
@property (nonatomic,strong) AVCaptureDevice *captureAudioDevice;
/*
    音频输入设备
 */
@property (nonatomic,strong) AVCaptureDeviceInput *captureAudioDeviceInput;
/*
    控制播放器的播放,暂停,播放速度
 */
@property (nonatomic,strong) AVPlayer *player;
/*
    管理资源对象,提供播放数据源
 */
@property (nonatomic,strong) AVPlayerItem *playerItem;
/*
    负责显示视频,如果没有添加该类,只有声音没有画面
 */
@property (nonatomic,strong) AVPlayerLayer *playerLayer;
@property (nonatomic, strong) UIButton *beginButton;
@property (nonatomic, strong) UILabel *timeLabel;
@property (nonatomic, strong) UIButton *replayButton;
@property (nonatomic, strong) UIButton *saveButton;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSInteger timerInteger;
@property (nonatomic, strong) NSURL *videoUrl;
@property (nonatomic, assign) BOOL canSave;
@property (nonatomic, assign) BOOL isPlaying;



@end

@implementation YLPlayerViewController

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
    
    [self.captureSession startRunning];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    self.navigationController.navigationBarHidden = NO;
    if ([self.captureSession isRunning]){
        [self.captureSession stopRunning];
    }
    
    if ([self.timer isValid]){
        [self.timer invalidate];
        self.timer = nil;
    }
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.timerInteger = 0;
    self.view.backgroundColor = [UIColor whiteColor];
    
    //获取授权状态
    [self getActhorStatus];
    
    [self setupUI];
    
}

- (void)beginVideoConfiguration{
    
    //开启上下文
    [self addSession];
    
    [self.captureSession beginConfiguration];
    //开启视频
    [self addVideo];
    //开启音频
    [self addAudio];
    //开始设置预览图层
    [self AddPreviewLayer];
    //提交
    [self.captureSession commitConfiguration];
    //开始绘画 不等于录制
    [self.captureSession startRunning];
}

//
- (void)addSession{
    self.captureSession = [[AVCaptureSession alloc]init];
    //设置清晰度
    if ([self.captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]){
        [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];
    } else{
        [self.captureSession setSessionPreset:AVCaptureSessionPreset1280x720];
    }
    
}
// 视频
- (void)addVideo{
    AVCaptureDeviceDiscoverySession *disSession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
    
    NSArray *devices = disSession.devices;
    for(AVCaptureDevice *device in devices){
        if(device.position == AVCaptureDevicePositionBack){
            self.captureDevice = device;
        }
    }
    [self addVideoInput];// add
    [self addVideoOutput];//add
    
}

- (void)addVideoInput{
    NSError *error ;
    self.captureDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:self.captureDevice error:&error];
    if(error){
        return ;
    }
    // 添加视频输入
    if([self.captureSession canAddInput:self.captureDeviceInput]){
        [self.captureSession addInput:self.captureDeviceInput];
    }
}

- (void)addVideoOutput{
    self.captureMovieFileOutput = [[AVCaptureMovieFileOutput alloc]init];
    if([self.captureSession canAddOutput:self.captureMovieFileOutput]){
        [self.captureSession addOutput:self.captureMovieFileOutput];
        
    }
    //设置链接管理对象
    
    //设置链接管理对象
    AVCaptureConnection *captureConnection = [self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    self.captureConnection = captureConnection;
    //
    captureConnection.videoScaleAndCropFactor = captureConnection.videoMaxScaleAndCropFactor;
    //视频稳定设置
    if ([captureConnection isVideoStabilizationSupported]){
        captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
}

//音频
- (void)addAudio{
    NSError *error;
    self.captureAudioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    self.captureAudioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureAudioDevice error:&error];
    if (error){
        return ;
    }
    
    if ([self.captureSession canAddInput:self.captureAudioDeviceInput]){
        [self.captureSession addInput:self.captureAudioDeviceInput];
    }
}

// 捕获视频预览图层
- (void)AddPreviewLayer{
    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect]; //设置视频播放的拉伸方式
    self.previewLayer.frame = self.view.frame;
    [self.view.layer addSublayer:self.previewLayer];
}



- (void)setupUI
{
    //开始录制按钮
    UIButton *beginButton = [UIButton buttonWithType:UIButtonTypeCustom];
    beginButton.backgroundColor = [UIColor clearColor];
    [beginButton setTitle:@"开始录制" forState:UIControlStateNormal];
    beginButton.layer.borderColor = [UIColor blueColor].CGColor;
    beginButton.layer.borderWidth = 1.0;
    [beginButton setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal];
    [beginButton addTarget:self action:@selector(beginButtonDidClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:beginButton];
    self.beginButton = beginButton;
    
    [beginButton sizeToFit];
    [beginButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view).offset(-30.0);
        make.centerX.equalTo(self.view);
    }];
    
    //计时标志
    UILabel *timeLabel = [[UILabel alloc] init];
    timeLabel.text = @"0";
    timeLabel.textAlignment = NSTextAlignmentCenter;
    timeLabel.backgroundColor = [UIColor clearColor];
    timeLabel.textColor = [UIColor redColor];
    timeLabel.font = [UIFont boldSystemFontOfSize:20.0];
    [self.view addSubview:timeLabel];
    self.timeLabel = timeLabel;
    
    [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view);
        make.bottom.equalTo(self.beginButton.mas_top).offset(-15.0);
        make.height.equalTo(@25);
        make.width.equalTo(@120);
    }];
    
    //重播按钮
    UIButton *replayButton = [UIButton buttonWithType:UIButtonTypeCustom];
    replayButton.backgroundColor = [UIColor clearColor];
    [replayButton setTitle:@"预览播放" forState:UIControlStateNormal];
    replayButton.layer.borderColor = [UIColor blueColor].CGColor;
    replayButton.layer.borderWidth = 1.0;
    [replayButton setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal];
    [replayButton addTarget:self action:@selector(replayButtonDidClick) forControlEvents:UIControlEventTouchUpInside];
    replayButton.hidden = YES;
    [self.view addSubview:replayButton];
    self.replayButton = replayButton;
    
    [replayButton sizeToFit];
    [replayButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.beginButton.mas_left).offset(-30.0);
        make.centerY.equalTo(self.beginButton);
    }];
    
    //保存按钮
    UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeCustom];
    saveButton.backgroundColor = [UIColor clearColor];
    [saveButton setTitle:@"保存" forState:UIControlStateNormal];
    saveButton.layer.borderColor = [UIColor blueColor].CGColor;
    saveButton.layer.borderWidth = 1.0;
    [saveButton setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal];
    [saveButton addTarget:self action:@selector(saveButtonDidClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:saveButton];
    self.saveButton = saveButton;
    
    [saveButton sizeToFit];
    [saveButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.beginButton.mas_right).offset(30.0);
        make.centerY.equalTo(self.beginButton);
    }];
}

#pragma mark --用户权限
- (void)getActhorStatus{
    //判断相机和麦克风权限
    NSString *mediaType = AVMediaTypeVideo;//读取媒体类型
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取谁呗授权状态
    if (authStatus == AVAuthorizationStatusAuthorized || authStatus == AVAuthorizationStatusRestricted){
        NSString *errorStr = @"应用相机权限,请在设置中启用";
        [self showAlertViewWithMessage:errorStr];
        return;
    }
    
    mediaType = AVMediaTypeAudio;// 音频
    authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
        NSString *errorStr = @"麦克风权限首先,请在设置中启用";
        [self showAlertViewWithMessage:errorStr];
        return;
    }
    
    [self beginVideoConfiguration];
}

- (void)showAlertViewWithMessage:(NSString *)message
{
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ensureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    
    [alertVC addAction:ensureAction];
    [alertVC addAction:cancelAction];
    
    [self presentViewController:alertVC animated:YES completion:nil];
}

- (void)loadTimer{
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}

//视频保存
- (void)saveVideo:(NSURL *)outputFileURL{
    //判断是否有相册权限
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusRestricted || status == PHAuthorizationStatusDenied){
        NSString *errorStr = @"没有使用相册的权限,请设置";
        [self showAlertViewWithMessage:errorStr];
        return;
    }
    
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputFileURL];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (success){
            NSLog(@"success");
        }
        if (error){
            NSLog(@"保存视频失败:%@",error);
            [self.saveButton setTitle:@"保存失败" forState: UIControlStateNormal];
            [self.saveButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
            self.replayButton.hidden = YES;
        }else{
            NSLog(@"保存视频到相册成功");
            [self.saveButton setTitle:@"保存成功" forState: UIControlStateNormal];
            [self.saveButton setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
            self.replayButton.hidden = NO;
        }
    }];

}

- (NSURL *)outPutFileURL{
    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), @"outPut.mov"]];
    return url;
}

//创建预览视图
- (void)createPlayView{
    NSLog(@"%@",self.videoUrl);
    [self.previewLayer removeFromSuperlayer];
    self.playerItem = [AVPlayerItem playerItemWithURL:self.videoUrl];
    self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    self.playerLayer.frame = self.view.frame;
    self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    CALayer *layer = self.view.layer;
    layer.masksToBounds = true;
    [layer addSublayer:_playerLayer];
}

//开始录制按钮
- (void)beginButtonDidClick:(UIButton *)button{
    button.enabled = NO;
    NSLog(@"开始录制按钮");
    [self loadTimer];
    [self.captureMovieFileOutput startRecordingToOutputFileURL:[self outPutFileURL] recordingDelegate:self];
}

//重播按钮
- (void)replayButtonDidClick{
    NSLog(@"重新播放按钮");
    self.replayButton.enabled = NO;
    [self createPlayView];
    
    [self.view bringSubviewToFront:self.saveButton];
    [self.view bringSubviewToFront:self.replayButton];
    [self.view bringSubviewToFront:self.beginButton];
    
    [self.player play];
}

//保存按钮
- (void)saveButtonDidClick{
    NSLog(@"保存按钮");
    
    self.saveButton.enabled = NO;
    if (self.timer){
        [self.timer invalidate];
    }
    self.canSave = YES;
    [self.captureSession stopRunning];
    [self.captureMovieFileOutput stopRecording];
}

//定时器
- (void)timerRun{
    NSInteger seconds = self.timerInteger % 60;
    NSInteger minutes = (self.timerInteger / 60) % 60;
    NSInteger hours = self.timerInteger / 3600;
    
    self.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld",hours, minutes, seconds];
    self.timerInteger ++;
}

#pragma mark - AVCaptureFileOutputRecordingDelegate
- (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections{
    
    NSLog(@"--开始录制--");
    
}

-(void)captureOutput:(AVCaptureFileOutput *)output didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
    NSLog(@"--录制结束-- %@-- %@--",outputFileURL,output.outputFileURL);
    
    if (outputFileURL.absoluteString.length == 0 &&output.outputFileURL.absoluteString.length){
        return;
    }
    
    if (self.canSave){
        self.videoUrl = outputFileURL;
        self.canSave = NO;
        [self saveVideo:self.videoUrl];
    }
    

    
}
@end

你可能感兴趣的:(iOS 10 AVFoundation录制采集视频)