这篇文章主要为大家详细介绍了iOS AVCaptureSession实现视频录制功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了AVCaptureSession实现视频录制功能的具体代码,供大家参考,具体内容如下
#import "RecordingVideoViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
@interface RecordingVideoViewController ()<AVCaptureFileOutputRecordingDelegate>
//会话 负责输入和输出设备之间的数据传递
@property (strong,nonatomic) AVCaptureSession *captureSession;
//设备输入 负责从AVCaptureDevice获得输入数据
@property (strong,nonatomic) AVCaptureDeviceInput *videoCaptureDeviceInput;
@property (strong,nonatomic) AVCaptureDeviceInput *audioCaptureDeviceInput;
//视频输出流
@property (strong,nonatomic) AVCaptureMovieFileOutput *captureMovieFileOutput;
//相机拍摄预览图层
@property (strong,nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;
//自定义UI控件容器
@property (strong,nonatomic) UIView *viewContainer;
//聚焦图标
@property (strong,nonatomic) UIImageView *focusCursor;
//录制时长
@property (strong,nonatomic) UILabel *timeLabel;
//切换前后摄像头
@property (strong,nonatomic) UIButton *switchCameraBtn;
//改变焦距
@property (strong,nonatomic) UIButton *scaleBtn;
//计时器
@property (strong,nonatomic) NSTimer *timer;
@end
@implementation RecordingVideoViewController {
@private
NSInteger _num;
CGFloat _kCameraScale;
}
- (UIView *)viewContainer {
if (!_viewContainer) {
_viewContainer = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIButton *takeButton = [UIButton buttonWithType:UIButtonTypeCustom];
takeButton.backgroundColor = [UIColor redColor];
[takeButton setTitle:@"start" forState:UIControlStateNormal];
[takeButton addTarget:self action:@selector(takeButtonClick:) forControlEvents:UIControlEventTouchUpInside];
_timeLabel = [[UILabel alloc] init];
_timeLabel.textColor = [UIColor redColor];
_timeLabel.textAlignment = NSTextAlignmentCenter;
_timeLabel.font = [UIFont boldSystemFontOfSize:20];
_timeLabel.text = @"00:00";
_switchCameraBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_switchCameraBtn setTitle:@"switch" forState:UIControlStateNormal];
_switchCameraBtn.backgroundColor = [UIColor redColor];
[_switchCameraBtn addTarget:self action:@selector(switchCameraBtnClick) forControlEvents:UIControlEventTouchUpInside];
_scaleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_scaleBtn setTitle:@"1X" forState:UIControlStateNormal];
_scaleBtn.backgroundColor = [UIColor redColor];
[_scaleBtn addTarget:self action:@selector(scaleBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[_viewContainer addSubview:takeButton];
[_viewContainer addSubview:_timeLabel];
[_viewContainer addSubview:_scaleBtn];
[_viewContainer addSubview:_switchCameraBtn];
[takeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(60, 40));
make.centerX.mas_equalTo(_viewContainer);
make.bottom.mas_equalTo(_viewContainer).offset(-64);
}];
[_timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(_viewContainer);
make.height.mas_equalTo(@30);
make.top.mas_equalTo(_viewContainer);
}];
[_scaleBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(60, 40));
make.left.mas_equalTo(_viewContainer).offset(10);
make.top.mas_equalTo(_viewContainer);
}];
[_switchCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(60, 40));
make.top.mas_equalTo(_viewContainer);
make.right.mas_equalTo(_viewContainer).offset(-10);
}];
_focusCursor = [[UIImageView alloc] init];
kBorder(_focusCursor, 1, [UIColor yellowColor]);
_focusCursor.alpha = 0;
[_viewContainer addSubview:self.focusCursor];
[_focusCursor mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(40, 40));
make.center.mas_equalTo(_viewContainer);
}];
}
return _viewContainer;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"视频录制";
_kCameraScale = 1.0f;
//初始化会话对象
_captureSession = [[AVCaptureSession alloc] init];
if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
_captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
}
NSError *error = nil;
//获取视频输入对象
AVCaptureDevice *videoCaptureDevice = [self cameraDeviceWithPosition:(AVCaptureDevicePositionBack)];
if (!videoCaptureDevice) {
NSLog(@"获取后置摄像头失败!");
return;
}
_videoCaptureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoCaptureDevice error:&error];
if (error) {
NSLog(@"取得视频设备输入对象时出错");
return;
}
//获取音频输入对象
AVCaptureDevice *audioCatureDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
_audioCaptureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioCatureDevice error:&error];
if (error) {
NSLog(@"取得音频设备输入对象时出错");
return;
}
//初始化设备输出对象
_captureMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
//将设备输入添加到会话中
if ([_captureSession canAddInput:_videoCaptureDeviceInput]) {
[_captureSession addInput:_videoCaptureDeviceInput];
[_captureSession addInput:_audioCaptureDeviceInput];
//防抖功能
AVCaptureConnection *captureConnection = [_captureMovieFileOutput connectionWithMediaType:AVMediaTypeAudio];
if ([captureConnection isVideoStabilizationSupported]) {
captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}
}
//将设备输出添加到会话中
if ([_captureSession canAddOutput:_captureMovieFileOutput]) {
[_captureSession addOutput:_captureMovieFileOutput];
}
//创建视频预览图层
_captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
self.viewContainer.layer.masksToBounds = YES;
_captureVideoPreviewLayer.frame = self.viewContainer.bounds;
_captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:_captureVideoPreviewLayer];
//显示自定义控件
[self.view addSubview:self.viewContainer];
//添加点按聚焦手势
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapScreen:)];
[self.viewContainer addGestureRecognizer:tapGesture];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self.captureSession startRunning];
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self.captureSession stopRunning];
[self.timer invalidate];
self.timer = nil;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.captureVideoPreviewLayer setAffineTransform:CGAffineTransformMakeScale(1, 1)];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
//开始 + 暂停录制
- (void)takeButtonClick:(UIButton *)sender {
if ([self.captureMovieFileOutput isRecording]) {
[self.captureMovieFileOutput stopRecording];
[self.navigationController popViewControllerAnimated:YES];
} else {
AVCaptureConnection *captureConnection = [self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
captureConnection.videoOrientation = [self.captureVideoPreviewLayer connection].videoOrientation;
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"Movie.mov"];
NSLog(@"%@",filePath);
[self.captureMovieFileOutput startRecordingToOutputFileURL:[NSURL fileURLWithPath:filePath] recordingDelegate:self];
self.switchCameraBtn.hidden = YES;
sender.backgroundColor = [UIColor greenColor];
[sender setTitle:@"stop" forState:UIControlStateNormal];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
[self.timer setFireDate:[NSDate distantPast]];
}
}
//切换摄像头
- (void)switchCameraBtnClick {
AVCaptureDevicePosition currentPosition = self.videoCaptureDeviceInput.device.position;
AVCaptureDevicePosition toPosition;
if (currentPosition == AVCaptureDevicePositionUnspecified ||
currentPosition == AVCaptureDevicePositionFront) {
toPosition = AVCaptureDevicePositionBack;
} else {
toPosition = AVCaptureDevicePositionFront;
}
AVCaptureDevice *toCapturDevice = [self cameraDeviceWithPosition:toPosition];
if (!toCapturDevice) {
NSLog(@"获取要切换的设备失败");
return;
}
NSError *error = nil;
AVCaptureDeviceInput *toVideoDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:toCapturDevice error:&error];
if (error) {
NSLog(@"获取要切换的设备输入失败");
return;
}
//改变会话配置
[self.captureSession beginConfiguration];
[self.captureSession removeInput:self.videoCaptureDeviceInput];
if ([self.captureSession canAddInput:toVideoDeviceInput]) {
[self.captureSession addInput:toVideoDeviceInput];
self.videoCaptureDeviceInput = toVideoDeviceInput;
}
//提交会话配置
[self.captureSession commitConfiguration];
}
//点按手势
- (void)tapScreen:(UITapGestureRecognizer *)tap {
CGPoint point = [tap locationInView:self.viewContainer];
//将界面point对应到摄像头point
CGPoint cameraPoint = [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];
//设置聚光动画
self.focusCursor.center = point;
self.focusCursor.transform = CGAffineTransformMakeScale(1.5, 1.5);
self.focusCursor.alpha = 1.0f;
[UIView animateWithDuration:1 animations:^{
self.focusCursor.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
self.focusCursor.alpha = 0.0f;
}];
//设置聚光点坐标
[self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];
}
/**设置聚焦点*/
-(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{
AVCaptureDevice *captureDevice= [self.videoCaptureDeviceInput device];
NSError *error = nil;
//设置设备属性必须先解锁 然后加锁
if ([captureDevice lockForConfiguration:&error]) {
if ([captureDevice isFocusModeSupported:focusMode]) {
[captureDevice setFocusMode:focusMode];
}
if ([captureDevice isFocusPointOfInterestSupported]) {
[captureDevice setFocusPointOfInterest:point];
}
// //曝光
// if ([captureDevice isExposureModeSupported:exposureMode]) {
// [captureDevice setExposureMode:exposureMode];
// }
// if ([captureDevice isExposurePointOfInterestSupported]) {
// [captureDevice setExposurePointOfInterest:point];
// }
// //闪光灯模式
// if ([captureDevice isFlashModeSupported:AVCaptureFlashModeAuto]) {
// [captureDevice setFlashMode:AVCaptureFlashModeAuto];
// }
//加锁
[captureDevice unlockForConfiguration];
}else{
NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription);
}
}
//调整焦距
-(void)scaleBtnClick:(UIButton *)sender
{
_kCameraScale += 0.5;
if(_kCameraScale > 3.0) {
_kCameraScale = 1.0;
}
//改变焦距
AVCaptureDevice *videoDevice = self.videoCaptureDeviceInput.device;
NSError *error = nil;
if ([videoDevice lockForConfiguration:&error]) {
[videoDevice setVideoZoomFactor:_kCameraScale];
[videoDevice unlockForConfiguration];
[sender setTitle:[NSString stringWithFormat:@"%lgX",_kCameraScale] forState:UIControlStateNormal];
[CATransaction begin];
[CATransaction setAnimationDuration:0.25];
[self.captureVideoPreviewLayer setAffineTransform:CGAffineTransformMakeScale(_kCameraScale, _kCameraScale)];
[CATransaction commit];
} else {
NSLog(@"修改设备属性失败!")
}
}
#pragma mark -------- AVCaptureFileOutputRecordingDelegate ----------
- (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(@"录制结束");
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"保存视频到相簿过程中发生错误,错误信息:%@",error.localizedDescription);
}
}];
}
//录制计时
- (void)timeAction {
self.timeLabel.text = [NSString stringWithFormat:@"%.2ld:%.2ld",_num/60,_num%60];
_num ++;
}
/**取得指定位置的摄像头*/
- (AVCaptureDevice *)cameraDeviceWithPosition:(AVCaptureDevicePosition )position{
NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *camera in cameras) {
if ([camera position] == position) {
return camera;
}
}
return nil;
}
@end
参考代码:
#import "VideoTestViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);
@interface VideoTestViewController ()<AVCaptureFileOutputRecordingDelegate>//视频文件输出代理
@property (strong,nonatomic) AVCaptureSession *captureSession;//负责输入和输出设备之间的数据传递
@property (strong,nonatomic) AVCaptureDeviceInput *captureDeviceInput;//负责从AVCaptureDevice获得输入数据
@property (strong,nonatomic) AVCaptureMovieFileOutput *captureMovieFileOutput;//视频输出流
@property (strong,nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;//相机拍摄预览图层
@property (assign,nonatomic) BOOL enableRotation;//是否允许旋转(注意在视频录制过程中禁止屏幕旋转)
@property (assign,nonatomic) CGRect *lastBounds;//旋转的前大小
@property (assign,nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier;//后台任务标识
@property (strong,nonatomic) UIView *viewContainer;
@property (strong,nonatomic) UIButton *takeButton;//拍照按钮
@property (strong,nonatomic) UIImageView *focusCursor; //聚焦光标
@end
@implementation VideoTestViewController
#pragma mark - 控制器视图方法
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//初始化会话
_captureSession=[[AVCaptureSession alloc]init];
if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {//设置分辨率
_captureSession.sessionPreset=AVCaptureSessionPreset1280x720;
}
//获得输入设备
AVCaptureDevice *captureDevice=[self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];//取得后置摄像头
if (!captureDevice) {
NSLog(@"取得后置摄像头时出现问题.");
return;
}
//添加一个音频输入设备
AVCaptureDevice *audioCaptureDevice=[[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
NSError *error=nil;
//根据输入设备初始化设备输入对象,用于获得输入数据
_captureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:captureDevice error:&error];
if (error) {
NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription);
return;
}
AVCaptureDeviceInput *audioCaptureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:audioCaptureDevice error:&error];
if (error) {
NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription);
return;
}
//初始化设备输出对象,用于获得输出数据
_captureMovieFileOutput=[[AVCaptureMovieFileOutput alloc]init];
//将设备输入添加到会话中
if ([_captureSession canAddInput:_captureDeviceInput]) {
[_captureSession addInput:_captureDeviceInput];
[_captureSession addInput:audioCaptureDeviceInput];
AVCaptureConnection *captureConnection=[_captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
if ([captureConnection isVideoStabilizationSupported ]) {
captureConnection.preferredVideoStabilizationMode=AVCaptureVideoStabilizationModeAuto;
}
}
//将设备输出添加到会话中
if ([_captureSession canAddOutput:_captureMovieFileOutput]) {
[_captureSession addOutput:_captureMovieFileOutput];
}
//创建视频预览层,用于实时展示摄像头状态
_captureVideoPreviewLayer=[[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];
CALayer *layer=self.viewContainer.layer;
layer.masksToBounds=YES;
_captureVideoPreviewLayer.frame=layer.bounds;
_captureVideoPreviewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式
//将视频预览层添加到界面中
//[layer addSublayer:_captureVideoPreviewLayer];
[layer insertSublayer:_captureVideoPreviewLayer below:self.focusCursor.layer];
_enableRotation=YES;
[self addNotificationToCaptureDevice:captureDevice];
[self addGenstureRecognizer];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self.captureSession startRunning];
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self.captureSession stopRunning];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(BOOL)shouldAutorotate{
return self.enableRotation;
}
////屏幕旋转时调整视频预览图层的方向
//-(void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
// [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
//// NSLog(@"%i,%i",newCollection.verticalSizeClass,newCollection.horizontalSizeClass);
// UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// NSLog(@"%i",orientation);
// AVCaptureConnection *captureConnection=[self.captureVideoPreviewLayer connection];
// captureConnection.videoOrientation=orientation;
//
/
织梦狗教程
本文标题为:iOS AVCaptureSession实现视频录制功能


基础教程推荐
猜你喜欢
- Android中的webview监听每次URL变化实例 2023-01-23
- iOS开发教程之XLForm的基本使用方法 2023-05-01
- IOS应用内跳转系统设置相关界面的方法 2022-11-20
- IOS 播放系统提示音使用总结(AudioToolbox) 2023-03-01
- Android多返回栈技术 2023-04-15
- 解决Android Studio突然不显示logcat日志的问题 2023-02-04
- android studio按钮监听的5种方法实例详解 2023-01-12
- Android开发使用RecyclerView添加点击事件实例详解 2023-06-15
- Flutter手势密码的实现示例(附demo) 2023-04-11
- Flutter绘图组件之CustomPaint使用详解 2023-05-12