转载自:http://blog.csdn.net/lookyou111/article/details/25625609
最近在学习使用iOS自带的API进行视频压缩,所以就从视频拍摄开始学起,因为曾经想直接对已有视频进行压缩,无奈总是失败,经研究发现不可以直接调用PC中的视频文件进行压缩,否则直接AVAssetExportSessionStatusFailed。所以只可以用真机测试并调用不iPhone中的视频。废话不多说,上代码:
使用UIImagePickerController即可完成视频的拍摄,并存入自定义的目录中
方法如下
- (IBAction)start:(id)sender { UIImagePickerController *ipc = [[UIImagePickerController alloc] init]; ipc.sourceType = UIImagePickerControllerSourceTypeCamera;//sourcetype有三种分别是camera,photoLibrary和photoAlbum NSArray *availableMedia = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];//Camera所支持的Media格式都有哪些,共有两个分别是@"public.image",@"public.movie" ipc.mediaTypes = [NSArray arrayWithObject:availableMedia[1]];//设置媒体类型为public.movie [self presentViewController:ipc animated:YES completion:nil]; ipc.videoMaximumDuration = 30.0f;//30秒 ipc.delegate = self;//设置委托 [ipc release]; }
关于上面提到的ipc.sourceType的三种取值,camera指的是调用相机进行拍摄,而photoLibrary指的是手机中的所有图片,photoAlbum指的是单纯指的是相册中的图片。其余的不做过多解释。
然后在如下委托方法中进行拍摄完毕的一些处理
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { sourceURL = [[info objectForKey:UIImagePickerControllerMediaURL] retain]; fileLenLabel.text = [NSString stringWithFormat:@"%f s", [self getVideoLength:sourceURL]];//这个url为什么可以呢,因为这里必须这样 fileSizeLabel.text = [NSString stringWithFormat:@"%f kb", [self getFileSize:[[sourceURL absoluteString] substringFromIndex:16]]];//文件并没有存储在sourceURL所指的地方,因为这里自己加上了所以要将这段字符串去掉,这个Label是测试时工程中用到的显示所拍摄文件大小的标签 NSLog([[sourceURL absoluteString] substringFromIndex:16]); [self dismissViewControllerAnimated:YES completion:nil]; }
好了,到这里就已经将拍摄好的视频存储在了sourceURL中。下面进行压缩处理
- (IBAction)convert:(id)sender {//转换时文件不能已存在,否则出错 AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:sourceURL options:nil]; NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset]; if ([compatiblePresets containsObject:resultQuality]) { AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:resultQuality]; NSDateFormatter *formater = [[NSDateFormatter alloc] init];//用时间给文件全名,以免重复,在测试的时候其实可以判断文件是否存在若存在,则删除,重新生成文件即可 [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"]; resultPath = [[NSHomeDirectory() stringByAppendingFormat:@"/Documents/output-%@.mp4", [formater stringFromDate:[NSDate date]]] retain]; NSLog(resultPath); [formater release]; exportSession.outputURL = [NSURL fileURLWithPath:resultPath]; exportSession.outputFileType = AVFileTypeMPEG4; [exportSession exportAsynchronouslyWithCompletionHandler:^(void) { switch (exportSession.status) { case AVAssetExportSessionStatusUnknown: NSLog(@"AVAssetExportSessionStatusUnknown"); break; case AVAssetExportSessionStatusWaiting: NSLog(@"AVAssetExportSessionStatusWaiting"); break; case AVAssetExportSessionStatusExporting: NSLog(@"AVAssetExportSessionStatusExporting"); break; case AVAssetExportSessionStatusCompleted: NSLog(@"AVAssetExportSessionStatusCompleted"); break; case AVAssetExportSessionStatusFailed: NSLog(@"AVAssetExportSessionStatusFailed"); break; } [exportSession release]; }]; } }
做几点说明,在视频拍摄的时候有个参数是来设置拍摄质量的,三种取值UIImagePickerControllerQualityTypeHigh,Medium,Low,但是经过测试发现这三个参数对拍摄效果并无多大影响,压缩的时候也有一个参数三个取值(针对iPhone的只有三个,还有针对其它设备的不同分辨率如640*480等,但是他们并不适用于iPhone,还有一些针对PC的)这三个取值分别是AVAssetExportPresetMediumQuality,Highest,Low,其中Highest与Medium自我感觉并多大差异,清晰度相当,压缩后的文件大小也几乎一样,但是Low要小的多,一分中的视频如果用Medium(或Highest)大小是5M多点,如果是Low则为600KB左右,但是Low要相对模糊许多。一般选取Medium即可。
这里再对如何获取文件的大小以及视频的时长做一点小解释
- (CGFloat) getFileSize:(NSString *)path { NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease]; float filesize = -1.0; if ([fileManager fileExistsAtPath:path]) { NSDictionary *fileDic = [fileManager attributesOfItemAtPath:path error:nil];//获取文件的属性 unsigned long long size = [[fileDic objectForKey:NSFileSize] longLongValue]; filesize = 1.0*size/1024; } return filesize; }
此方法可以获取文件的大小,返回的是单位是KB。
- (CGFloat) getVideoLength:(NSURL *)URL { NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:URL options:opts]; float second = 0; second = urlAsset.duration.value/urlAsset.duration.timescale; return second; }
此方法可以获取视频文件的时长。