著急的朋友直接翻到最下面的GitHub鏈接
先說(shuō)一下思路
- 創(chuàng)建捕獲會(huì)話AVCaptureSession.
- 創(chuàng)建捕獲輸入設(shè)備(輸入設(shè)備有兩個(gè):視頻輸入AVCaptureDeviceInput *videoInput;音頻輸入AVCaptureDeviceInput *audioInput)
- 創(chuàng)建捕獲視頻文件輸入AVCaptureMovieFileOutput.
- 將輸入、輸出加入到捕獲會(huì)話。
- 創(chuàng)建錄像預(yù)覽圖層AVCaptureVideoPreviewLayer.
==這里只放主要代碼,詳細(xì)的看demo,小視頻本人已封裝好,使用不到5行代碼就可以實(shí)現(xiàn)小視頻功能==
1.創(chuàng)建各種捕獲對(duì)象加入到捕獲會(huì)話中
- (void)zh_buildSession {
// 捕獲會(huì)話
_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(@"攝像頭設(shè)備創(chuàng)建失敗");
return;
}
if ([_captureSession canAddInput:videoInput]) {
[_captureSession addInput:videoInput];
_videoInput = videoInput;
} else {
NSLog(@"會(huì)話無(wú)法加入攝像頭");
return;
}
// 麥克風(fēng)
NSError *audioError = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:&audioError];
if (!audioInput || audioError) {
NSLog(@"麥克風(fēng)設(shè)備創(chuàng)建失敗");
return;
}
if ([_captureSession canAddInput:audioInput]) {
[_captureSession addInput:audioInput];
} else {
NSLog(@"會(huì)話無(wú)法加入麥克風(fēng)");
return;
}
// 視頻輸出
_output = [[AVCaptureMovieFileOutput alloc] init];
// 設(shè)置錄制模式
AVCaptureConnection *captureConnection = [_output connectionWithMediaType:AVMediaTypeVideo];
// 設(shè)置防抖
if ([captureConnection isVideoStabilizationSupported]) {
captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}
if ([_captureSession canAddOutput:_output]) {
[_captureSession addOutput:_output];
} else {
NSLog(@"會(huì)話無(wú)法加入輸出設(shè)備");
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.創(chuàng)建3個(gè)操作按鈕(錄像、切換攝像頭、取消),這步要在創(chuàng)建捕捉會(huì)話后面,否則按鈕就添加到了預(yù)覽圖層下面
- (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.封裝錄像時(shí)的按鈕,錄像時(shí)轉(zhuǎn)動(dòng)圓環(huán)
// 繪制轉(zhuǎn)動(dòng)圓環(huán)
- (void)zh_circleAnimation {
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.frame = _animationLayer.bounds;
[_animationLayer addSublayer:circleLayer];
_circleLayer = circleLayer; // 指向這個(gè)layer用來(lái)刪除
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.封裝小視頻錄制完的預(yù)覽播放
- (instancetype)initWithFrame:(CGRect)frame url:(NSURL *)url {
self = [super initWithFrame:frame];
if (self) {
self.userInteractionEnabled = YES;
// 監(jiān)聽播放完成通知,用來(lái)重復(fù)播放
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(zh_playFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
// 創(chuàng)建播放器
_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];
// 創(chuàng)建返回按鈕
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];
// 創(chuàng)建使用按鈕
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];
// 移動(dòng)
[self zh_moveButton:cancelBtn value:(-50 * zScaleWidth - cancelBtn.frame.size.width)]; // 左移需要多加一個(gè)按鈕的距離
[self zh_moveButton:confirmBtn value:50 * zScaleWidth];
}
return self;
}