最近在學習使用iOS自帶的API進行視頻壓縮,所以就從視頻拍攝開始學起,因為曾經(jīng)想直接對已有視頻進行壓縮,無奈總是失敗,經(jīng)研究發(fā)現(xiàn)不可以直接調用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];
}
好了,到這里就已經(jīng)將拍攝好的視頻存儲在了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];
}];
}
}
做幾點說明,在視頻拍攝的時候有個參數(shù)是來設置拍攝質量的,三種取值UIImagePickerControllerQualityTypeHigh,Medium,Low,但是經(jīng)過測試發(fā)現(xiàn)這三個參數(shù)對拍攝效果并無多大影響,壓縮的時候也有一個參數(shù)三個取值(針對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;
}此方法可以獲取視頻文件的時長。
|