捕捉视频帧
Posted 小敏的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了捕捉视频帧相关的知识,希望对你有一定的参考价值。
通常视频应用程序使用一个缩略图来表示给定的视频,使用CoreMedia框架生成缩略图。
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface ViewController : UIViewController<AVCaptureFileOutputRecordingDelegate> @property (strong, nonatomic) AVCaptureSession *captureSession; @property (strong, nonatomic) AVCaptureDeviceInput *videoInput; @property (strong, nonatomic) AVCaptureDeviceInput *audioInput; @property (strong, nonatomic) AVCaptureStillImageOutput *stillImageOutput; @property (strong, nonatomic) AVCaptureMovieFileOutput *movieOutput; @property (weak, nonatomic) IBOutlet UIButton *captureButton; @property (weak, nonatomic) IBOutlet UISegmentedControl *modeControl; @property (weak, nonatomic) IBOutlet UIImageView *thumbnailImageView; - (IBAction)capture:(id)sender; - (IBAction)updateMode:(id)sender; @end
#import "ViewController.h" @interface ViewController () @end @implementation ViewController @synthesize captureButton; @synthesize modeControl; @synthesize thumbnailImageView; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.captureSession = [[AVCaptureSession alloc] init]; //Optional: self.captureSession.sessionPreset = AVCaptureSessionPresetMedium; AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil]; self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:nil]; self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *stillImageOutputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; [self.stillImageOutput setOutputSettings:stillImageOutputSettings]; self.movieOutput = [[AVCaptureMovieFileOutput alloc] init]; // Setup capture session for taking pictures [self.captureSession addInput:self.videoInput]; [self.captureSession addOutput:self.stillImageOutput]; AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; UIView *aView = self.view; previewLayer.frame = CGRectMake(0, 70, self.view.frame.size.width, self.view.frame.size.height-140); [aView.layer addSublayer:previewLayer]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } - (void) captureStillImage { AVCaptureConnection *stillImageConnection = [self.stillImageOutput.connections objectAtIndex:0]; if ([stillImageConnection isVideoOrientationSupported]) [stillImageConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; [[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if (imageDataSampleBuffer != NULL) { NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; UIImage *image = [[UIImage alloc] initWithData:imageData]; [library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error) { UIAlertView *alert; if (!error) { alert = [[UIAlertView alloc] initWithTitle:@"Photo Saved" message:@"The photo was successfully saved to you photos library" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; } else { alert = [[UIAlertView alloc] initWithTitle:@"Error Saving Photo" message:@"The photo was not saved to you photos library" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; } [alert show]; } ]; } else NSLog(@"Error capturing still image: %@", error); }]; } - (NSURL *) tempFileURL { NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"]; NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath]; NSFileManager *manager = [[NSFileManager alloc] init]; if ([manager fileExistsAtPath:outputPath]) { [manager removeItemAtPath:outputPath error:nil]; } return outputURL; } - (IBAction)capture:(id)sender { if (self.modeControl.selectedSegmentIndex == 0) { // Picture Mode [self captureStillImage]; } else { // Video Mode if (self.movieOutput.isRecording == YES) { [self.captureButton setTitle:@"Capture" forState:UIControlStateNormal]; [self.movieOutput stopRecording]; } else { [self.captureButton setTitle:@"Stop" forState:UIControlStateNormal]; [self.movieOutput startRecordingToOutputFileURL:[self tempFileURL] recordingDelegate:self]; } } } - (IBAction)updateMode:(id)sender { [self.captureSession stopRunning]; if (self.modeControl.selectedSegmentIndex == 0) { if (self.movieOutput.isRecording == YES) { [self.movieOutput stopRecording]; } // Still Image Mode [self.captureSession removeInput:self.audioInput]; [self.captureSession removeOutput:self.movieOutput]; [self.captureSession addOutput:self.stillImageOutput]; } else { // Video Mode [self.captureSession removeOutput:self.stillImageOutput]; [self.captureSession addInput:self.audioInput]; [self.captureSession addOutput:self.movieOutput]; // Set orientation of capture connections to portrait NSArray *array = [[self.captureSession.outputs objectAtIndex:0] connections]; for (AVCaptureConnection *connection in array) { connection.videoOrientation = AVCaptureVideoOrientationPortrait; } } [self.captureButton setTitle:@"Capture" forState:UIControlStateNormal]; [self.captureSession startRunning]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.captureSession startRunning]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self.captureSession stopRunning]; } - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { BOOL recordedSuccessfully = YES; if ([error code] != noErr) { // A problem occurred: Find out if the recording was successful. id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey]; if (value) recordedSuccessfully = [value boolValue]; // Logging the problem anyway: NSLog(@"A problem occurred while recording: %@", error); } if (recordedSuccessfully) { [self createThumbnailForVideoURL:outputFileURL]; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) { UIAlertView *alert; if (!error) { alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"The movie was successfully saved to you photos library" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; } else { alert = [[UIAlertView alloc] initWithTitle:@"Error Saving Video" message:@"The movie was not saved to you photos library" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; } [alert show]; } ]; } } -(void)createThumbnailForVideoURL:(NSURL *)videoURL { AVURLAsset *myAsset = [[AVURLAsset alloc] initWithURL:videoURL options:[NSDictionary dictionaryWithObject:@"YES" forKey:AVURLAssetPreferPreciseDurationAndTimingKey]]; AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:myAsset]; imageGenerator.appliesPreferredTrackTransform = YES; //Makes sure images are correctly rotated. Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]); CMTime half = CMTimeMakeWithSeconds(durationSeconds/2.0, 600); NSArray *times = [NSArray arrayWithObjects: [NSValue valueWithCMTime:half], nil]; [imageGenerator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) { if (result == AVAssetImageGeneratorSucceeded) { self.thumbnailImageView.image = [UIImage imageWithCGImage:image]; } else if (result == AVAssetImageGeneratorFailed) { NSLog(@"Failed with error: %@", [error localizedDescription]); } }]; } @end
以上是关于捕捉视频帧的主要内容,如果未能解决你的问题,请参考以下文章