在iOS中,手機攝像頭的使用有如下兩種方法:git
UIImagePickerController
拍照和視頻錄製
AVFoundation
框架實現咱們日常使用UIImagePickerController
就基本能夠知足了,功能確實強大,但它也有很差的一點,那就是因爲它的高度封裝性,若是要進行某些自定義工做就比較複雜,例如若是要作出一款相似於美顏相機的拍照界面就比較難以實現,這個時候就要考慮AVFoundation
框架實現。github
UIImagePickerController
繼承於UINavigationController
,屬於UIKit
框架,能夠實現圖片選取、拍照、錄製視頻等功能,使用起來十分方便。數組
1. 經常使用屬性:session
@property (nonatomic) UIImagePickerControllerSourceType sourceType;/* 拾取源類型枚舉 */ typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) { UIImagePickerControllerSourceTypePhotoLibrary,//照片庫 UIImagePickerControllerSourceTypeCamera,//攝像頭 UIImagePickerControllerSourceTypeSavedPhotosAlbum//相簿 }; /* 媒體類型,默認狀況下此數組包含kUTTypeImage,表示拍照 若是要錄像,必須設置爲kUTTypeVideo(視頻不帶聲音)或kUTTypeMovie(視頻帶聲音) */ @property (nonatomic,copy) NSArray<NSString *> *mediaTypes; @property (nonatomic) NSTimeInterval videoMaximumDuration;//視頻最大錄製時長,默認10s @property (nonatomic) UIImagePickerControllerQualityType videoQuality;//視頻質量 typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) { UIImagePickerControllerQualityTypeHigh = 0, //高清 UIImagePickerControllerQualityTypeMedium, //中等,適合WiFi傳輸 UIImagePickerControllerQualityTypeLow, //低質量,適合蜂窩網傳輸 UIImagePickerControllerQualityType640x480, //640*480 UIImagePickerControllerQualityTypeIFrame1280x720, //1280*720 UIImagePickerControllerQualityTypeIFrame960x540, //960*540 }; @property (nonatomic) BOOL showsCameraControls;/* 是否顯示攝像頭控制面板,默認爲YES */ @property (nonatomic,strong) UIView *cameraOverlayView;/* 攝像頭上覆蓋的視圖 */ @property (nonatomic) CGAffineTransform cameraViewTransform;/* 攝像頭形變 */ @property (nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode;/* 攝像頭捕捉模式 */ typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) { UIImagePickerControllerCameraCaptureModePhoto,//拍照模式 UIImagePickerControllerCameraCaptureModeVideo//視頻錄製模式 }; @property (nonatomic) UIImagePickerControllerCameraDevice cameraDevice;/* 攝像頭設備 */ typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) { UIImagePickerControllerCameraDeviceRear,//前置攝像頭 UIImagePickerControllerCameraDeviceFront//後置攝像頭 }; @property (nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode;/* 閃光燈模式 */ typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) { UIImagePickerControllerCameraFlashModeOff = -1,//關閉閃光燈 UIImagePickerControllerCameraFlashModeAuto = 0,//閃光燈自動,默認 UIImagePickerControllerCameraFlashModeOn = 1//打開閃光燈 };
2. 經常使用對象方法:框架
- (void)takePicture; //拍照 - (BOOL)startVideoCapture;//開始錄製視頻 - (void)stopVideoCapture;//中止錄製視頻
3. 代理方法:ide
/* 媒體獲取完成會調用 */ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info; /* 取消獲取會調用 */ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
4. 擴展函數,用於保存到相簿:函數
/* 保存圖片到相簿 */ void UIImageWriteToSavedPhotosAlbum( UIImage *image,//保存的圖片UIImage id completionTarget,//回調的執行者 SEL completionSelector, //回調方法 void *contextInfo//回調參數信息 ); //上面通常保存圖片的回調方法爲: - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo; /* 判斷是否能保存視頻到相簿 */ BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath); /* 保存視頻到相簿 */ void UISaveVideoAtPathToSavedPhotosAlbum( NSString *videoPath, //保存的視頻文件路徑 id completionTarget, //回調的執行者 SEL completionSelector,//回調方法 void *contextInfo//回調參數信息 ); //上面通常保存視頻的回調方法爲: - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
5. 使用攝像頭的步驟:學習
- 建立
UIImagePickerController
對象
MobileCoreServices.framework
中UIImagePickerController
,一般以模態彈出形式打開6. 下面是具體實例代碼:atom
#import "ViewController.h" #import <MobileCoreServices/MobileCoreServices.h> @interface ViewController () <UIImagePickerControllerDelegate,UINavigationControllerDelegate> @property (strong, nonatomic) UIImagePickerController *pickerController;//拾取控制器 @property (strong, nonatomic) IBOutlet UIImageView *showImageView;//顯示圖片 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化拾取控制器 [self initPickerController]; } /* 初始化拾取控制器 */ - (void)initPickerController{ //建立拾取控制器 UIImagePickerController *pickerController = [[UIImagePickerController alloc] init]; //設置拾取源爲攝像頭 pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; //設置攝像頭爲後置 pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; pickerController.editing = YES;//設置運行編輯,便可以點擊一些拾取控制器的控件 pickerController.delegate = self;//設置代理 self.pickerController = pickerController; } #pragma mark - UI點擊 /* 點擊拍照 */ - (IBAction)imagePicker:(id)sender { //設定拍照的媒體類型 self.pickerController.mediaTypes = @[(NSString *)kUTTypeImage]; //設置攝像頭捕捉模式爲捕捉圖片 self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; //模式彈出拾取控制器 [self presentViewController:self.pickerController animated:YES completion:nil]; } /* 點擊錄像 */ - (IBAction)videoPicker:(id)sender { //設定錄像的媒體類型 self.pickerController.mediaTypes = @[(NSString *)kUTTypeMovie]; //設置攝像頭捕捉模式爲捕捉視頻 self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; //設置視頻質量爲高清 self.pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; //模式彈出拾取控制器 [self presentViewController:self.pickerController animated:YES completion:nil]; } #pragma mark - 代理方法 /* 拍照或錄像成功,都會調用 */ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info { //從info取出此時攝像頭的媒體類型 NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {//若是是拍照 //獲取拍照的圖像 UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; //保存圖像到相簿 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); } else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {//若是是錄像 //獲取錄像文件路徑URL NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL]; NSString *path = url.path; //判斷能不能保存到相簿 if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) { //保存視頻到相簿 UISaveVideoAtPathToSavedPhotosAlbum(path, self, @selector(video:didFinishSavingWithError:contextInfo:), nil); } } //拾取控制器彈回 [self dismissViewControllerAnimated:YES completion:nil]; } /* 取消拍照或錄像會調用 */ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { NSLog(@"取消"); //拾取控制器彈回 [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - 保存圖片或視頻完成的回調 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSLog(@"保存圖片完成"); self.showImageView.image = image; self.showImageView.contentMode = UIViewContentModeScaleToFill; } - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSLog(@"保存視頻完成"); } @end
功能十分強大,基本知足通常的需求,使用起來也很簡單。url
首先了解下AVFoundation作拍照和錄像的相關類:
AVCaptureSession
:
媒體捕捉會話,負責把捕獲到的音視頻數據輸出到輸出設備上,一個會話能夠有多個輸入輸出。
AVCaptureVideoPervieewLayer
:CALayer
的子類,實時查看拍照或錄像效果。 AVCaptureDevice
:AVCaptureDeviceInput
:AVCaptureOutput
:AVCaptureAudioDataOutput//輸出音頻管理對象,輸出數據爲NSData AVCaptureStillImageDataOutput//輸出圖片管理對象,輸出數據爲NSData AVCaptureVideoDataOutput//輸出視頻管理對象,輸出數據爲NSData /* 輸出文件管理對象,輸出數據以文件形式輸出 */ AVCaptureFileOutput {//子類 AVCaptureAudioFileOutput //輸出是音頻文件 AVCaptureMovieFileOutput //輸出是視頻文件 }
拍照或錄像的通常步驟爲:
- 建立
AVCaptureSession
對象
AVCaptureDevice
的類方法得到要使用的設備AVCaptureDevice
建立並初始化AVCaptureDeviceInput
對象AVCaptureOutput
子類AVCaptureDeviceInput
、AVCaptureOutput
添加到媒體會話管理對象AVCaptureSession
中AVCaptureVideoPreviewLayer
並指定媒體會話,添加圖層到顯示容器中AVCaptureSession
的startRunning
方法開始捕獲,stopRunning
方法中止捕捉拍照使用實例以下:
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewController () @property (strong, nonatomic) AVCaptureSession *session;//媒體管理會話 @property (strong, nonatomic) AVCaptureDeviceInput *captureInput;//輸入數據對象 @property (strong, nonatomic) AVCaptureStillImageOutput *imageOutput;//輸出數據對象 @property (strong, nonatomic) AVCaptureVideoPreviewLayer *captureLayer;//視頻預覽圖層 @property (strong, nonatomic) IBOutlet UIButton *captureBtn;//拍照按鈕 @property (strong, nonatomic) IBOutlet UIButton *openCaptureBtn;//打開攝像頭按鈕 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initCapture]; self.openCaptureBtn.hidden = NO; self.captureBtn.hidden = YES; } /* 初始化攝像頭 */ - (void)initCapture{ //1. 建立媒體管理會話 AVCaptureSession *session = [[AVCaptureSession alloc] init]; self.session = session; //判斷分辨率是否支持1280*720,支持就設置爲1280*720 if( [session canSetSessionPreset:AVCaptureSessionPreset1280x720] ) { session.sessionPreset = AVCaptureSessionPreset1280x720; } //2. 獲取後置攝像頭設備對象 AVCaptureDevice *device = nil; NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *camera in cameras) { if (camera.position == AVCaptureDevicePositionBack) {//取得後置攝像頭 device = camera; } } if(!device) { NSLog(@"取得後置攝像頭錯誤"); return; } //3. 建立輸入數據對象 NSError *error = nil; AVCaptureDeviceInput *captureInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error]; if (error) { NSLog(@"建立輸入數據對象錯誤"); return; } self.captureInput = captureInput; //4. 建立輸出數據對象 AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *setting = @{ AVVideoCodecKey:AVVideoCodecJPEG }; [imageOutput setOutputSettings:setting]; self.imageOutput = imageOutput; //5. 添加輸入數據對象和輸出對象到會話中 if ([session canAddInput:captureInput]) { [session addInput:captureInput]; } if ([session canAddOutput:imageOutput]) { [session addOutput:imageOutput]; } //6. 建立視頻預覽圖層 AVCaptureVideoPreviewLayer *videoLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; self.view.layer.masksToBounds = YES; videoLayer.frame = self.view.bounds; videoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; //插入圖層在拍照按鈕的下方 [self.view.layer insertSublayer:videoLayer below:self.captureBtn.layer]; self.captureLayer = videoLayer; } #pragma mark - UI點擊 /* 點擊拍照按鈕 */ - (IBAction)takeCapture:(id)sender { //根據設備輸出得到鏈接 AVCaptureConnection *connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo]; //經過鏈接得到設備輸出的數據 [self.imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { //獲取輸出的JPG圖片數據 NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; UIImage *image = [UIImage imageWithData:imageData]; UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);//保存到相冊 self.captureLayer.hidden = YES; self.captureBtn.hidden = YES; self.openCaptureBtn.hidden = NO; [self.session stopRunning];//中止捕捉 }]; } /* 點擊打開攝像頭按鈕 */ - (IBAction)openCapture:(id)sender { self.captureLayer.hidden = NO; self.captureBtn.hidden = NO; self.openCaptureBtn.hidden = YES; [self.session startRunning];//開始捕捉 } @end
錄像的操做差很少,下面代碼是以上面代碼爲基礎進行修改:
- 比拍照多了一個音頻輸入,改變輸出數據對象的類
1. 獲取音頻輸入數據對象以及視頻輸出數據對象
//獲取麥克風設備對象 AVCaptureDevice *device = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio].firstObject; if(!device) { NSLog(@"取得麥克風錯誤"); return; } //建立輸入數據對象 NSError *error = nil; AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error]; if (error) { NSLog(@"建立輸入數據對象錯誤"); return; } //建立視頻文件輸出對象 AVCaptureMovieFileOutput *movieOutput = [[AVCaptureMovieFileOutput alloc] init]; self.movieOutput = movieOutput;
2. 添加進媒體管理會話中
if([session canAddInput:captureInput]) { [session addInput:captureInput]; [session addInput:audioInput]; //添加防抖動功能 AVCaptureConnection *connection = [movieOutput connectionWithMediaType:AVMediaTypeVideo]; if ([connection isVideoStabilizationSupported]) { connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; } } if ([session canAddOutput:movieOutput]) { [session addOutput:movieOutput]; }
3. 點擊錄像按鈕
if (!self.movieOutput.isRecording) { NSString *outputPath = [NSTemporaryDirectory() stringByAppendingString:@"myMovie.mov"]; NSURL *url = [NSURL fileURLWithPath:outputPath];//記住是文件URL,不是普通URL //開始錄製並設置代理監控錄製過程,錄製文件會存放到指定URL路徑下 [self.movieOutput startRecordingToOutputFileURL:url recordingDelegate:self]; } else { [self.movieOutput stopRecording];//結束錄製 }
4. 處理錄製代理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(@"完成錄製"); NSString *path = outputFileURL.path; //保存錄制視頻到相簿 if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) { UISaveVideoAtPathToSavedPhotosAlbum(path, nil, nil, nil); } }
以上的表格中,我沒有所有都講,我主要講AVFoundation
框架,裏面還有很是多的內容能夠學習,這個框架是很是強大,有時間也能夠再深刻去學習。
iOS對於多媒體支持至關靈活和完善,具體開發過程到底如何選擇,以上的表格僅供參考。
代碼Demo點這裏:LearnDemo裏面的CaptureDemo
做者:執着丶執念 連接:https://www.jianshu.com/p/f00c5031dccd 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。