<图形图像,动画,多媒体> 读书笔记 --- 录制与编辑视频
使用UIImagePickerController 进行录制
#import "ViewController.h" #import <MobileCoreServices/MobileCoreServices.h> #import <QuartzCore/QuartzCore.h> @interface ViewController () <UIImagePickerControllerDelegate,UINavigationControllerDelegate> - (IBAction)videoRecod:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)videoRecod:(id)sender { if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init]; imagePickerController.delegate = self; imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; imagePickerController.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeMovie, nil]; //录制质量设定 imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; //仅仅同意最多录制30秒时间 imagePickerController.videoMaximumDuration = 30.0f; [self presentViewController:imagePickerController animated:YES completion:nil]; } else { NSLog(@"摄像头不可用。"); } } - (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker { [self dismissViewControllerAnimated:YES completion:nil]; } - (void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info { NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL]; NSString *tempFilePath = [url path]; if ( UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(tempFilePath) ) { //video:didFinishSavingWithError:contextInfo: 必须保存成这类回调 UISaveVideoAtPathToSavedPhotosAlbum( tempFilePath, self, @selector(video:didFinishSavingWithError:contextInfo:), (__bridge void *)(tempFilePath)); } [self dismissViewControllerAnimated:YES completion:nil]; } - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(NSString *)contextInfo { NSString *title; NSString *message; if (!error) { title = @"视频保存"; message = @"视频已经保存到设备的相机胶卷中"; } else { title = @"视频失败"; message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { NSLog(@"选择器将要显示。"); } - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { NSLog(@"选择器显示结束。
"); }
使用AVFoundation
AVCaptureSession,捕获会话,是为了实现从摄像头和麦克风捕获数据,须要使用AVCaptureSession对象协调输入输出数据
AVCaptureDevice,捕获设备,代表输入一个设备,比如摄像头和麦克风
AVCaptureDeviceInput,捕获会话的一个输入数据源
AVCaptureOutput,捕获会话的一个输出目标,比如输出的视频文件和静态图片
AVCaptureMovieFileOutput,是AVCaptureOutput的子类,通过它能够将捕获的数据输出到QuickTime视频文件里(MOV)
AVCaptureVideoPreviewLayer,是CALayer子类,能够使用它来显示录制的视频
AVCaptureConnection,捕获连接,在一个捕获会话中输入和输出之间的连接
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface ViewController () <AVCaptureFileOutputRecordingDelegate> { BOOL isRecording; } @property (weak, nonatomic) IBOutlet UILabel *label; @property (weak, nonatomic) IBOutlet UIButton *button; @property (strong, nonatomic) AVCaptureSession *session; @property (strong, nonatomic) AVCaptureMovieFileOutput *output; - (IBAction)recordPressed:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.session = [[AVCaptureSession alloc] init]; self.session.sessionPreset = AVCaptureSessionPresetMedium; AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error = nil; AVCaptureDeviceInput *camera = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:&error]; AVCaptureDevice *micDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; AVCaptureDeviceInput *mic = [AVCaptureDeviceInput deviceInputWithDevice:micDevice error:&error]; if (error || !camera || !mic) { NSLog(@"Input Error"); } else { //增加捕获音频视频 [self.session addInput:camera]; [self.session addInput:mic]; } self.output = [[AVCaptureMovieFileOutput alloc] init]; if ([self.session canAddOutput:self.output]) { [self.session addOutput:self.output];//输出 } AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; previewLayer.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); [self.view.layer insertSublayer:previewLayer atIndex:0]; [self.session startRunning]; isRecording = NO; self.label.text = @""; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (![self.session isRunning]) { [self.session startRunning]; } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self.session isRunning]) { [self.session stopRunning]; } } - (IBAction)recordPressed:(id)sender { if (!isRecording) { [self.button setTitle:@"停止" forState:UIControlStateNormal]; self.label.text = @"录制中..."; isRecording = YES; NSURL *fileURL = [self fileURL]; [self.output startRecordingToOutputFileURL:fileURL recordingDelegate:self]; } else { [self.button setTitle:@"录制" forState:UIControlStateNormal]; self.label.text = @"停止"; [self.output stopRecording]; isRecording = NO; } } - (NSURL *) fileURL { NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"movie.mov"]; NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath]; NSFileManager *manager = [[NSFileManager alloc] init]; if ([manager fileExistsAtPath:outputPath]) { [manager removeItemAtPath:outputPath error:nil]; } return outputURL; } #pragma mark-- AVCaptureFileOutputRecordingDelegate托付协议实现方法 - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { if (error == nil) { ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) { if (error) { NSLog(@"写入错误。") ; } }]; } }
使用UIVideoEditorController
#import "ViewController.h" @interface ViewController () <UIVideoEditorControllerDelegate,UINavigationControllerDelegate> - (IBAction)editButtonPress:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)editButtonPress:(id)sender { NSBundle *bundle = [NSBundle mainBundle]; NSString *moviePath = [bundle pathForResource:@"YY" ofType:@"mp4"]; //推断设备是否支持编辑视频 if ([UIVideoEditorController canEditVideoAtPath:moviePath]){ UIVideoEditorController *videoEditor = [[UIVideoEditorController alloc] init]; videoEditor.delegate = self; videoEditor.videoPath = moviePath; [self presentViewController:videoEditor animated:YES completion:NULL]; } else { NSLog(@"不能编辑这个视频"); } } - (void)videoEditorController:(UIVideoEditorController *)editor didSaveEditedVideoToPath:(NSString *)editedVideoPath{ [editor dismissViewControllerAnimated:YES completion:NULL]; if ( UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(editedVideoPath) ) { UISaveVideoAtPathToSavedPhotosAlbum(editedVideoPath, self, @selector(video:didFinishSavingWithError:contextInfo:), (__bridge void *)(editedVideoPath)); } } - (void)videoEditorController:(UIVideoEditorController *)editor didFailWithError:(NSError *)error{ NSLog(@"编辑视频出错"); NSLog(@"Video editor error occurred = %@", error); [editor dismissViewControllerAnimated:YES completion:NULL]; } - (void)videoEditorControllerDidCancel:(UIVideoEditorController *)editor{ NSLog(@"视频编辑取消"); [editor dismissViewControllerAnimated:YES completion:NULL]; } - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(NSString *)contextInfo { NSString *title; NSString *message; if (!error) { title = @"视频保存"; message = @"视频已经保存到设备的相机胶卷中"; } else { title = @"视频失败"; message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; }
个人感言,事实上视频我之前做过,也有类似文章,在国外的一些站点上全然也能找到比这更好的更有技术含量的代码和文章,只是总之,算是一个学习记录吧~
原书:http://item.jd.com/11522516.html