着急的朋友直接翻到最下面的GitHub链接
先说一下思路
- 创建捕获会话AVCaptureSession.
- 创建捕获输入设备(输入设备有两个:视频输入AVCaptureDeviceInput *videoInput;音频输入AVCaptureDeviceInput *audioInput)
- 创建捕获视频文件输入AVCaptureMovieFileOutput.
- 将输入、输出加入到捕获会话。
- 创建录像预览图层AVCaptureVideoPreviewLayer.
==这里只放主要代码,详细的看demo,小视频本人已封装好,使用不到5行代码就可以实现小视频功能==
1.创建各种捕获对象加入到捕获会话中
- (void)zh_buildSession {
// 捕获会话
_captureSession = [[AVCaptureSession alloc] init];
if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
[_captureSession setSessionPreset:AVCaptureSessionPresetHigh];
}
// 捕捉输入
// 摄像头
NSError *videoError = nil;
AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:&videoError];
if (!videoInput || videoError) {
NSLog(@"摄像头设备创建失败");
return;
}
if ([_captureSession canAddInput:videoInput]) {
[_captureSession addInput:videoInput];
_videoInput = videoInput;
} else {
NSLog(@"会话无法加入摄像头");
return;
}
// 麦克风
NSError *audioError = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:&audioError];
if (!audioInput || audioError) {
NSLog(@"麦克风设备创建失败");
return;
}
if ([_captureSession canAddInput:audioInput]) {
[_captureSession addInput:audioInput];
} else {
NSLog(@"会话无法加入麦克风");
return;
}
// 视频输出
_output = [[AVCaptureMovieFileOutput alloc] init];
// 设置录制模式
AVCaptureConnection *captureConnection = [_output connectionWithMediaType:AVMediaTypeVideo];
// 设置防抖
if ([captureConnection isVideoStabilizationSupported]) {
captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}
if ([_captureSession canAddOutput:_output]) {
[_captureSession addOutput:_output];
} else {
NSLog(@"会话无法加入输出设备");
return;
}
// 添加录像图层
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
_previewLayer.frame = CGRectMake(0.f, 0.f, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; // 填充模式
[self.view.layer addSublayer:_previewLayer];
}
2.创建3个操作按钮(录像、切换摄像头、取消),这步要在创建捕捉会话后面,否则按钮就添加到了预览图层下面
- (void)zh_buildUI {
// 切换摄像头
_switchCameraBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_switchCameraBtn setImage:[UIImage imageNamed:@"video_camera_0104"] forState:UIControlStateNormal];
[_switchCameraBtn sizeToFit];
_switchCameraBtn.frame = CGRectMake(self.view.frame.size.width - 15.f - _switchCameraBtn.frame.size.width, 30.f, _switchCameraBtn.frame.size.width, _switchCameraBtn.frame.size.height);
[_switchCameraBtn addTarget:self action:@selector(zh_switchCameraButtonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_switchCameraBtn];
// 录像按钮
_recordBtn = [ZHRecordButton buttonWithType:UIButtonTypeCustom];
CGFloat recordBtnW = 60.f;
_recordBtn.frame = CGRectMake(self.view.frame.size.width / 2 - recordBtnW / 2, self.view.frame.size.height - recordBtnW - recordBtnW, recordBtnW, recordBtnW);
_recordBtn.zh_delegate = self;
[_recordBtn addTarget:self action:@selector(zh_startRecording:) forControlEvents:UIControlEventTouchDown];
[_recordBtn addTarget:self action:@selector(zh_endRecord:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_recordBtn];
// 取消按钮
_cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelBtn setImage:[UIImage imageNamed:@"video_close_0104"] forState:UIControlStateNormal];
[_cancelBtn sizeToFit];
_cancelBtn.center = _recordBtn.center;
_cancelBtn.frame = CGRectMake(_recordBtn.frame.origin.x - 50.f * zScaleWidth - _cancelBtn.frame.size.width, _cancelBtn.frame.origin.y, _cancelBtn.frame.size.width, _cancelBtn.frame.size.height);
[_cancelBtn addTarget:self action:@selector(zh_cancelButtonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_cancelBtn];
}
3.封装录像时的按钮,录像时转动圆环
// 绘制转动圆环
- (void)zh_circleAnimation {
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.frame = _animationLayer.bounds;
[_animationLayer addSublayer:circleLayer];
_circleLayer = circleLayer; // 指向这个layer用来删除
circleLayer.fillColor = [UIColor clearColor].CGColor;
circleLayer.strokeColor = [UIColor greenColor].CGColor;
circleLayer.lineWidth = 3.f;
CGFloat radius = _animationLayer.bounds.size.width / 2 - circleLayer.lineWidth / 2;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:circleLayer.position radius:radius startAngle:-M_PI / 2 endAngle:M_PI * 3 / 2 clockwise:true];
circleLayer.path = path.CGPath;
CABasicAnimation *checkAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
checkAnimation.duration = 10;
checkAnimation.fromValue = @(0.0f);
checkAnimation.toValue = @(1.0f);
[checkAnimation setValue:@"checkAnimation" forKey:@"animationName"];
[circleLayer addAnimation:checkAnimation forKey:nil];
}
4.封装小视频录制完的预览播放
- (instancetype)initWithFrame:(CGRect)frame url:(NSURL *)url {
self = [super initWithFrame:frame];
if (self) {
self.userInteractionEnabled = YES;
// 监听播放完成通知,用来重复播放
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(zh_playFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
// 创建播放器
_playerItem = [AVPlayerItem playerItemWithURL:url];
_player = [AVPlayer playerWithPlayerItem:_playerItem];
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
_playerLayer.frame = self.layer.bounds;
_playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.layer addSublayer:_playerLayer];
[_player play];
// 创建返回按钮
UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
cancelBtn.tag = 1000;
[cancelBtn setImage:[UIImage imageNamed:@"video_return_0104"] forState:UIControlStateNormal];
CGFloat cancelBtnW = 60.f;
cancelBtn.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
cancelBtn.frame = CGRectMake(cancelBtn.frame.origin.x, self.frame.size.height - cancelBtnW * 2, cancelBtnW, cancelBtnW);
[cancelBtn addTarget:self action:@selector(zh_buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:cancelBtn];
// 创建使用按钮
UIButton *confirmBtn = [UIButton buttonWithType:UIButtonTypeCustom];
confirmBtn.tag = 1001;
[confirmBtn setImage:[UIImage imageNamed:@"video_success_0104"] forState:UIControlStateNormal];
[confirmBtn sizeToFit];
confirmBtn.frame = cancelBtn.frame;
[confirmBtn addTarget:self action:@selector(zh_buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:confirmBtn];
// 移动
[self zh_moveButton:cancelBtn value:(-50 * zScaleWidth - cancelBtn.frame.size.width)]; // 左移需要多加一个按钮的距离
[self zh_moveButton:confirmBtn value:50 * zScaleWidth];
}
return self;
}
最后附上GitHub