iOS學習筆記27-網路攝影機

來源:互聯網
上載者:User

iOS學習筆記27-網路攝影機
一、網路攝影機

在iOS中,手機網路攝影機的使用有以下兩種方法:
1. UIImagePickerController拍照和視頻錄製
* 優點:使用方便,功能強大
* 缺點:高度封裝性,無法實現一些自訂工作
2. AVFoundation架構實現
* 優點:靈活性強,提供了很多現成的輸入裝置和輸出裝置,還有很多底層的內容可以供開發人員使用
* 缺點:需要和底層打交道,學習難度大,使用複雜

我們平常使用UIImagePickerController就基本可以滿足了,功能確實強大,但它也有不好的一點,那就是由於它的高度封裝性,如果要進行某些自訂工作就比較複雜,例如如果要做出一款類似於美顏相機的拍照介面就比較難以實現,這個時候就要考慮AVFoundation架構實現。

二、UIImagePickerController

UIImagePickerController繼承於UINavigationController,屬於UIKit架構,可以實現圖片選取、拍照、錄製視頻等功能,使用起來十分方便。

1. 常用屬性:
@property (nonatomic) UIImagePickerControllerSourceType sourceType;/* 拾取源類型枚舉 */typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {    UIImagePickerControllerSourceTypePhotoLibrary,//照片庫    UIImagePickerControllerSourceTypeCamera,//網路攝影機    UIImagePickerControllerSourceTypeSavedPhotosAlbum//相簿};/*   媒體類型,預設情況下此數組包含kUTTypeImage,表示拍照  如果要錄影,必須設定為kUTTypeVideo(視頻不帶聲音)或kUTTypeMovie(視頻帶聲音)*/@property (nonatomic,copy) NSArray *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. 代理方法:
/* 媒體擷取完成會調用 */- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)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. 下面是具體執行個體代碼:
#import "ViewController.h"#import @interface ViewController () @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 *)pickerdidFinishPickingMediaWithInfo:(NSDictionary *)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



功能十分強大,基本滿足一般的需求,使用起來也很簡單。

三、AVFoundation的拍照錄影首先瞭解下AVFoundation做拍照和錄影的相關類: AVCaptureSession
媒體捕捉會話,負責把捕獲到的音視頻資料輸出到輸出裝置上,一個會話可以有多個輸入輸出。 AVCaptureVideoPervieewLayer
相機拍攝預覽圖層,是 CALayer的子類,即時查看拍照或錄影效果。
AVCaptureDevice
輸入裝置,包括麥克風、網路攝影機等,可以設定一些物理裝置的屬性 AVCaptureDeviceInput
裝置輸入資料管理對象,管理輸入資料 AVCaptureOutput
裝置輸出資料管理對象,管理輸出資料,通常使用它的子類:
AVCaptureAudioDataOutput//輸出音頻管理對象,輸出資料為NSDataAVCaptureStillImageDataOutput//輸出圖片管理對象,輸出資料為NSDataAVCaptureVideoDataOutput//輸出視頻管理對象,輸出資料為NSData/* 輸出檔案管理對象,輸出資料以檔案形式輸出 */AVCaptureFileOutput  {//子類            AVCaptureAudioFileOutput   //輸出是音頻檔案        AVCaptureMovieFileOutput   //輸出是視頻檔案}

拍照或錄影的一般步驟為:建立 AVCaptureSession對象 使用 AVCaptureDevice的類方法獲得要使用的裝置 利用輸入裝置 AVCaptureDevice建立並初始化 AVCaptureDeviceInput對象 初始化輸出資料管理對象,看具體輸出什麼資料決定使用哪個 AVCaptureOutput子類 將 AVCaptureDeviceInputAVCaptureOutput添加到媒體會話管理對象 AVCaptureSession中 建立視頻預覽圖層 AVCaptureVideoPreviewLayer並指定媒體會話,添加圖層到顯示容器中 調用媒體會話 AVCaptureSessionstartRunning方法開始捕獲, stopRunning方法停止捕捉 將 捕獲的音頻或視頻資料輸出到指定檔案拍照使用執行個體如下:
#import "ViewController.h"#import @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);    }}
四、iOS音頻視頻使用總結


以上的表格中,我沒有全部都講,我主要講AVFoundation架構,裡面還有非常多的內容可以學習,這個架構是非常強大,有時間也可以再深入去學習。
iOS對於多媒體支援相當靈活和完善,具體開發過程到底如何選擇,以上的表格僅供參考。

代碼Demo點這裡:LearnDemo裡面的CaptureDemo

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.