iPhone:编程压缩录制的video分享?
在录制video之前调用摄像机视图时,我已经实现了重叠视图。
pickerController.cameraOverlayView =myOverlay;
录制video并通过电子邮件等共享录像和保存video到相册都工作正常。
如果我使用video质量作为“高质量”,那么录制的video已经变成了巨大的尺寸。 例如,如果我以高质量录制video30秒,录制的video已经变成30-40Mb左右。
pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
如何在共享前压缩高质量录制的video,例如苹果如何使用内置的录像机?
请指导我解决这个问题。
谢谢!
更新:
这是我最近试图,但仍然没有成功:我想要压缩录制到didFinishPickingMediaWithInfo录制的video,并存储在相同的相册实际videopath本身,而不是其他任何地方。 我testing了相同的video压缩到非常小的尺寸时,我从照片库中select,但从摄像头拍摄,并通过didFinishPickingMediaWithInfo传来的相同的video不压缩,虽然我使用下面的AVAssetExportSession代码。
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) { NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; NSString *urlPath = [videoURL path]; if ([[urlPath lastPathComponent] isEqualToString:@"capturedvideo.MOV"]) { if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (urlPath)) { [self copyTempVideoToMediaLibrary :urlPath]; } else { NSLog(@"Video Capture Error: Captured video cannot be saved...didFinishPickingMediaWithInfo()"); } } else { NSLog(@"Processing soon to saved photos album...else loop of lastPathComponent..didFinishPickingMediaWithInfo()"); } } [self dismissModalViewControllerAnimated:YES]; } - (void)copyTempVideoToMediaLibrary :(NSString *)videoURL { dispatch_queue_t mainQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(mainQueue, ^{ ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease]; ALAssetsLibraryWriteVideoCompletionBlock completionBlock = ^(NSURL *assetURL, NSError *error) { NSLog(@"Saved URL: %@", assetURL); NSLog(@"Error: %@", error); if (assetURL != nil) { AVURLAsset *theAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:videoURL] options:nil]; NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:theAsset]; AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:theAsset presetName:AVAssetExportPresetLowQuality]; [exportSession setOutputURL:[NSURL URLWithString:videoURL]]; [exportSession setOutputFileType:AVFileTypeQuickTimeMovie]; [exportSession exportAsynchronouslyWithCompletionHandler:^ { switch ([exportSession status]) { case AVAssetExportSessionStatusFailed: NSLog(@"Export session faied with error: %@", [exportSession error]); break; default: //[self mediaIsReady]; break; } }]; } }; [library writeVideoAtPathToSavedPhotosAlbum:[NSURL URLWithString:videoURL] completionBlock:completionBlock]; }); }
如果您想压缩video以进行远程共享,并保持iPhone本地存储的原始质量,则应查看AVAssetExportSession或AVAssetWriter 。
另请阅读iOSpipe理资产的方式 。
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler { [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil]; AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil]; AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality]; exportSession.outputURL = outputURL; exportSession.outputFileType = AVFileTypeQuickTimeMovie; [exportSession exportAsynchronouslyWithCompletionHandler:^(void) { handler(exportSession); [exportSession release]; }]; } - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; NSURL *outputURL = [NSURL fileURLWithPath:@"/Users/josh/Desktop/output.mov"]; [self convertVideoToLowQuailtyWithInputURL:videoURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession) { if (exportSession.status == AVAssetExportSessionStatusCompleted) { printf("completed\n"); } else { printf("error\n"); } }]; }
我猜这个video已经被h264编解码器压缩了。 但是您可以尝试使用AVFoundation从相机捕获video文件。 但是我怀疑你最终会得到相同的文件大小。
以下是iPhone 4上录制的10秒video文件的一些统计信息,具有不同的质量预设。
high (1280х720) = ~14MB = ~11Mbit/s 640 (640х480) = ~4MB = ~3.2Mbit/s medium (360х480) = ~1MB = ~820Kbit/s low (144х192) = ~208KB = ~170Kbit/s
pickerController.videoQuality = UIImagePickerControllerQualityTypeMedium;
这些都是您可以从中select的值。
UIImagePickerControllerQualityTypeHigh = 0, UIImagePickerControllerQualityType640x480 = 3, UIImagePickerControllerQualityTypeMedium = 1, // default value UIImagePickerControllerQualityTypeLow = 2
试试这几行:
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil]; AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil]; AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset: urlAsset presetName:AVAssetExportPresetLowQuality]; session.outputURL = outputURL; session.outputFileType = AVFileTypeQuickTimeMovie; [session exportAsynchronouslyWithCompletionHandler:^(void) { handler(session); }];
使用swift编程压缩video
不要忘记添加 – 导入AssetsLibrary
func convertVideoWithMediumQuality(inputURL : NSURL){ let VideoFilePath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("mergeVideo\(arc4random()%1000)d").URLByAppendingPathExtension("mp4").absoluteString if NSFileManager.defaultManager().fileExistsAtPath(VideoFilePath) { do { try NSFileManager.defaultManager().removeItemAtPath(VideoFilePath) } catch { } } let savePathUrl = NSURL(string: VideoFilePath)! let sourceAsset = AVURLAsset(URL: inputURL, options: nil) let assetExport: AVAssetExportSession = AVAssetExportSession(asset: sourceAsset, presetName: AVAssetExportPresetMediumQuality)! assetExport.outputFileType = AVFileTypeQuickTimeMovie assetExport.outputURL = savePathUrl assetExport.exportAsynchronouslyWithCompletionHandler { () -> Void in switch assetExport.status { case AVAssetExportSessionStatus.Completed: dispatch_async(dispatch_get_main_queue(), { do { let videoData = try NSData(contentsOfURL: savePathUrl, options: NSDataReadingOptions()) print("MB - \(videoData.length / (1024 * 1024))") } catch { print(error) } }) case AVAssetExportSessionStatus.Failed: self.hideActivityIndicator(self.view) print("failed \(assetExport.error)") case AVAssetExportSessionStatus.Cancelled: self.hideActivityIndicator(self.view) print("cancelled \(assetExport.error)") default: self.hideActivityIndicator(self.view) print("complete") } } }
我发现了一个很好的自定义类( SDAVAssetExportSession )来做video压缩。 你可以从这个链接下载。
下载后,将SDAVAssetExportSession.h和SDAVAssetExportSession.m文件添加到您的项目中,然后下面的代码将帮助执行压缩。 在下面的代码中,您可以通过指定分辨率和比特率来压缩video
#import "SDAVAssetExportSession.h" - (void)compressVideoWithInputVideoUrl:(NSURL *) inputVideoUrl { /* Create Output File Url */ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *finalVideoURLString = [documentsDirectory stringByAppendingPathComponent:@"compressedVideo.mp4"]; NSURL *outputVideoUrl = ([[NSURL URLWithString:finalVideoURLString] isFileURL] == 1)?([NSURL URLWithString:finalVideoURLString]):([NSURL fileURLWithPath:finalVideoURLString]); // Url Should be a file Url, so here we check and convert it into a file Url SDAVAssetExportSession *compressionEncoder = [SDAVAssetExportSession.alloc initWithAsset:[AVAsset assetWithURL:inputVideoUrl]]; // provide inputVideo Url Here compressionEncoder.outputFileType = AVFileTypeMPEG4; compressionEncoder.outputURL = outputVideoUrl; //Provide output video Url here compressionEncoder.videoSettings = @ { AVVideoCodecKey: AVVideoCodecH264, AVVideoWidthKey: @800, //Set your resolution width here AVVideoHeightKey: @600, //set your resolution height here AVVideoCompressionPropertiesKey: @ { AVVideoAverageBitRateKey: @45000, // Give your bitrate here for lower size give low values AVVideoProfileLevelKey: AVVideoProfileLevelH264High40, }, }; compressionEncoder.audioSettings = @ { AVFormatIDKey: @(kAudioFormatMPEG4AAC), AVNumberOfChannelsKey: @2, AVSampleRateKey: @44100, AVEncoderBitRateKey: @128000, }; [compressionEncoder exportAsynchronouslyWithCompletionHandler:^ { if (compressionEncoder.status == AVAssetExportSessionStatusCompleted) { NSLog(@"Compression Export Completed Successfully"); } else if (compressionEncoder.status == AVAssetExportSessionStatusCancelled) { NSLog(@"Compression Export Canceled"); } else { NSLog(@"Compression Failed"); } }]; }
取消压缩使用下面的代码行
[compressionEncoder cancelExport]; //Video compression cancel