BSFramework 組件包:
- 2D穷遂、3D無限輪播圖組件
- 圖片視頻選擇、圖片視頻預(yù)覽千诬、圖片視頻拍攝組件
- GitHub 地址
- iOS 自定義相機(jī) 拍照+視頻錄制(二) 視頻篇
框架:<AVFoundation/AVFoundation.h>
大致流程:
- session 初始化
- device 初始化
- input耍目,output 初始化,并關(guān)聯(lián)device
- session 添加 input 和 output
- 初始化預(yù)覽層 AVCaptureVideoPreviewLayer
- session startRunning
- 點(diǎn)擊拍照, didFinishProcessingPhotoSampleBuffer 代理回調(diào)后徐绑,處理數(shù)據(jù)邪驮,生成照片
PS : 其中還含有一些攝像頭翻轉(zhuǎn),閃光燈等操作傲茄,但屬于額外功能毅访,不算流程,具體全部功能看源碼
一盘榨、使用 AVCaptureSession 進(jìn)行拍照
需要的屬性大致有
@property (nonatomic ,strong) AVCaptureSession *session;
@property (nonatomic ,strong) AVCaptureDevice *device;
@property (nonatomic ,strong) AVCaptureDeviceInput *deviceInput;//圖像輸入源
@property (nonatomic ,strong) AVCaptureOutput *outPut; //圖像輸出源
@property (nonatomic ,strong) AVPlayer *player;
@property (nonatomic ,strong) AVPlayerLayer *playerLayer;
@property (nonatomic ,strong) AVCaptureConnection *connection;
首先處理權(quán)限問題
#pragma mark - 相機(jī)授權(quán)
-(void)authorization{
//請求相機(jī)權(quán)限
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (status == AVAuthorizationStatusNotDetermined) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
[self authorization];
}else{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"" message:@"相機(jī)權(quán)限未開啟,請前往 手機(jī)-設(shè)置 開啟相機(jī)權(quán)限" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self.navigationController popViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}];
[controller addAction:action];
[self presentViewController:controller animated:YES completion:nil];
return;
}
});
}];
}else if (status == AVAuthorizationStatusDenied) {
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"" message:@"相機(jī)權(quán)限未開啟,請前往 手機(jī)-設(shè)置 開啟相機(jī)權(quán)限" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self.navigationController popViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}];
[controller addAction:action];
[self presentViewController:controller animated:YES completion:nil];
return;
}else if (status == AVAuthorizationStatusAuthorized){
[self configData];
[self initSubViews];
[self masonryLayout];
}
}
只有權(quán)限通過了喻粹,我才初始化 UI 界面,否則就 alert 提示草巡。
然后初始化 session 守呜,添加 device 、input山憨、output
-(void)configData{
self.session = [[AVCaptureSession alloc]init];
if ([self.session canSetSessionPreset:AVCaptureSessionPresetHigh]){
self.session.sessionPreset = AVCaptureSessionPresetHigh;
}else if ([self.session canSetSessionPreset:AVCaptureSessionPresetiFrame960x540]) {
self.session.sessionPreset = AVCaptureSessionPresetiFrame960x540;
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//如果不放在子線程里查乒,跳轉(zhuǎn)到相機(jī)的時候,會卡
[self addPicIO];
[self addVideoIO];
dispatch_async(dispatch_get_main_queue(), ^{
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.previewLayer.frame = CGRectMake(0, 30, SCREEN_WIDTH, SCREEN_HEIGHT - 30 - 150);
[self.view.layer insertSublayer:self.previewLayer atIndex:0];
[self.session startRunning];
});
});
}
#pragma mark 設(shè)置 拍照類型的輸入輸出源
-(void)addPicIO{
NSError *error = nil;
self.deviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:&error];
if (!error) {
if ([self.session canAddInput:self.deviceInput]) {
[self.session addInput:self.deviceInput];
}
if ([self.session canAddOutput:self.outPut]) {
[self.session addOutput:self.outPut];
}
}
}
點(diǎn)擊拍照處理
#pragma mark - action 交互事件
// 拍照
-(void)takePicture{
// 防止快速連點(diǎn)
if (self.bottomView.recordStatus == RECORD_STATUS_UNRECORD) {
return;
}
if (@available(iOS 10.0, *)) {
AVCapturePhotoOutput *outPut = (AVCapturePhotoOutput *)self.outPut;
AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey:AVVideoCodecJPEG}];
[outPut capturePhotoWithSettings:settings delegate:self];
}else{
// 兼容iOS 10以下機(jī)型郁竟,未測試玛迄,不清楚可不可以用
self.connection = [self.outPut connectionWithMediaType:AVMediaTypeVideo];
[self.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
AVCaptureStillImageOutput *outPut = (AVCaptureStillImageOutput *)self.outPut;
[outPut captureStillImageAsynchronouslyFromConnection:self.connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
[self.session stopRunning];
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:jpegData];
self.photoImageView.image = image;
self.photoImageView.hidden = NO;
}];
}
if ([self.delegate respondsToSelector:@selector(photoCameraTakeBtnClicked)]) {
[self.delegate photoCameraTakeBtnClicked];
}
}
代理回調(diào)處理
-(void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhotoSampleBuffer:(CMSampleBufferRef)photoSampleBuffer previewPhotoSampleBuffer:(CMSampleBufferRef)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(AVCaptureBracketedStillImageSettings *)bracketSettings error:(NSError *)error API_AVAILABLE(ios(10.0)){
if (photoSampleBuffer) {
[self.session stopRunning];
NSData *data = [AVCapturePhotoOutput JPEGPhotoDataRepresentationForJPEGSampleBuffer:photoSampleBuffer previewPhotoSampleBuffer:previewPhotoSampleBuffer];
UIImage *image = [UIImage imageWithData:data];
self.photoImageView.image = image;
self.photoImageView.hidden = NO;
}
}
PS : 此代理是 iOS 10 以后的方法,低于 iOS 10 需要使用 ↓↓↓
// 兼容iOS 10以下機(jī)型棚亩,未測試蓖议,不清楚可不可以用
self.connection = [self.outPut connectionWithMediaType:AVMediaTypeVideo];
[self.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
AVCaptureStillImageOutput *outPut = (AVCaptureStillImageOutput *)self.outPut;
[outPut captureStillImageAsynchronouslyFromConnection:self.connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
[self.session stopRunning];
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:jpegData];
self.photoImageView.image = image;
self.photoImageView.hidden = NO;
}];
友情鏈接