iOS開發 AVFoundation 自定義視訊錄製

敖老黑發表於2018-01-03

圖片來自網路

最近一頓瘋狂加班啊,年前一頓加,寫了好幾個版本的更新。然而到現在都沒有上線,真蛋疼。

迴歸正題啊,通過學習本章的內容,你將學會本章內容。

##一 、第一步當然還是繪製一個介面,很簡單一個view 一個錄製按鈕

18禁

匯入幾個標頭檔案和遵守幾個協議 #import <AVFoundation/AVFoundation.h> #import "RAFileManager.h" //這是個操作檔案的工具類 不多做介紹 #import <AssetsLibrary/AssetsLibrary.h> //這貨iOS8過期了。。。 PHPhoto看起來比這個好用多了

遵守一個協議

  <AVCaptureFileOutputRecordingDelegate>   //這玩意必須遵守不然拿不到視訊哦
複製程式碼

##二、初始化相機硬體等 這個步驟跟拍照的步驟大部分是一樣的,兩處區別 : ####1、輸出不一樣:拍照部分用的是AVCaptureStillImageOutput,視訊錄製需要的是AVCaptureMovieFileOutput ####2、輸入硬體不一樣:拍照只需要攝像頭捕捉影像的輸入,視訊錄製的話還需要一個音訊的輸入(畢竟我們們這AV是有聲的哈)。

建立如下屬性

      @property (nonatomic) dispatch_queue_t sessionQueue;
      /**
複製程式碼

*  AVCaptureSession物件來執行輸入裝置和輸出裝置之間的資料傳遞  / @property (nonatomic, strong) AVCaptureSession session; /**  *  視訊輸入裝置   / @property (nonatomic, strong) AVCaptureDeviceInput videoInput; /**   *  聲音輸入 / @property (nonatomic, strong) AVCaptureDeviceInput audioInput; /**   *  視訊輸出流  / @property(nonatomic,strong)AVCaptureMovieFileOutput movieFileOutput; /   *  預覽圖層   / @property (nonatomic, strong) AVCaptureVideoPreviewLayer previewLayer; /**   *  記錄錄製時間   / @property (nonatomic, strong) NSTimer timer;

什麼?這些屬性都是幹啥的?猛戳這裡--->AVFoundation自定義相機

之後初始化相機,連線硬體和軟體。

- (void)initAVCaptureSession{
複製程式碼

self.session = [[AVCaptureSession alloc] init];          //這裡根據需要設定  可以設定4K     self.session.sessionPreset = AVCaptureSessionPreset1280x720;          NSError *error;          AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];          //更改這個設定的時候必須先鎖定裝置,修改完後再解鎖,否則崩潰     [device lockForConfiguration:nil];     //設定閃光燈為自動     [device setFlashMode:AVCaptureFlashModeAuto];     [device unlockForConfiguration];          self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error];          self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:nil];          if (error) {         NSLog(@"%@",error);     }

self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];          if ([self.session canAddInput:self.videoInput]) {         [self.session addInput:self.videoInput];     }          if ([self.session canAddInput:self.audioInput]) {                  [self.session addInput:self.audioInput];     }          if ([self.session canAddOutput:self.movieFileOutput]) {                  [self.session addOutput:self.movieFileOutput];     }          //初始化預覽圖層     self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];    
    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];          self.previewLayer.frame = CGRectMake(0, 0,KMainScreenW, KMainScreenH);     self.backView.layer.masksToBounds = YES;     [self.backView.layer insertSublayer:self.previewLayer atIndex:0];      }

記得在viewDidLoad裡面呼叫一下。viewWillAppear裡面開啟session ,viewWillDisappear裡面關閉session

相機開啟了一定要關閉,相機開啟了一定要關閉,相機開啟了一定要關閉,重要的事情說三遍

##三、開啟錄製方法和結束錄製方法 - (void)startVideoRecorder{          AVCaptureConnection *movieConnection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];     AVCaptureVideoOrientation avcaptureOrientation = AVCaptureVideoOrientationPortrait;     [movieConnection setVideoOrientation:avcaptureOrientation];     [movieConnection setVideoScaleAndCropFactor:1.0];      NSURL *url = [[RAFileManager defaultManager] filePathUrlWithUrl:[self getVideoSaveFilePathString]];

if (![self.movieFileOutput isRecording]) {         [self.movieFileOutput startRecordingToOutputFileURL:url recordingDelegate:self];

}

}

- (void)stopVideoRecorder{
複製程式碼

  if ([self.movieFileOutput isRecording]) {
複製程式碼

[self.movieFileOutput stopRecording];     }    
}

##四、最後寫個按鈕點選開始錄製呼叫上面方法就好並且實現delegate。注意判斷是否有使用相機,麥克風的許可權。如果沒有許可權,你還剛好沒判斷。。。那麼恭喜你。。崩潰了。

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
    
    //判斷最小時間的哈
複製程式碼

if (CMTimeGetSeconds(captureOutput.recordedDuration) < VIDEO_RECORDER_MIN_TIME) {                  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"視訊時間過短" message:nil delegate:self     cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];         [alert show];         return;     }                NSLog(@"%s-- url = %@ ,recode = %f , int %lld kb", func, outputFileURL, CMTimeGetSeconds(captureOutput.recordedDuration), captureOutput.recordedFileSize / 1024);          ALAssetsLibrary *lib = [[ALAssetsLibrary alloc] init];     [lib writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) {              }]; }

向相簿寫入視訊的時候也要注意許可權。

######DLC:

獲取視訊截圖的方法

- (UIImage *)videoSnap:(NSString *)videoPath{
複製程式碼

NSURL *url = [NSURL fileURLWithPath:videoPath];     AVAsset *asset = [AVAsset assetWithURL:url];     AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];     CMTime snaptime = CMTimeMake(10, 10);     CMTime time2;        CGImageRef cgImageRef = [generator copyCGImageAtTime:snaptime actualTime:&time2 error:nil];          UIImage *tempImage = [UIImage imageWithCGImage:cgImageRef];      //這裡取完圖片記得搞下圖片的方向,在這裡我就不寫了。     return tempImage; }

這個方法第一個時間是指的圖片建立的時間, 第二個actualTime 是指向圖片正式生成時間的指標,實際生成時間這個引數可以傳NULL,如果你不關心它是什麼時候誕生的。 但是第一個時間不能傳入空,必須告訴它你要在哪一個時間點生成一張截圖 - (nullable CGImageRef)copyCGImageAtTime:(CMTime)requestedTime actualTime:(nullable CMTime *)actualTime error:(NSError * __nullable * __nullable)outError CF_RETURNS_RETAINED;

獲取到截圖之後記得處理下方向。

最後: ######1、硬體之間關係介紹戳這裡AVFoundation自定義相機 ######2、文章演示demo戳這裡 AVFoundation自定義視訊錄製demo ######文章演示demo戳這裡 AVFoundation自定義視訊錄製demo ######文章演示demo戳這裡 AVFoundation自定義視訊錄製demo 重要的事情還是要說三遍,雖然寫的不怎麼樣,如果你們要用還是希望能仔細看一看,別上來就私聊 留言要demo。

######3、要轉載的看官們也不要問了,註明出處就行了。隨便轉。 ######4、文章有什麼問題請留言指出,歡迎交流。

相關文章