iPhone: Programaticamente compactando vídeos gravados para compartilhar?

Implementei uma visualização de sobreposição ao chamar a visualização da câmera antes de gravar o vídeo.

pickerController.cameraOverlayView =myOverlay; 

Gravação de vídeo e salvar o vídeo no álbum depois de gravar o vídeo e compartilhar via e-mail etc. tudo funciona bem.

Se eu usar a qualidade de vídeo como “Alta qualidade”, o vídeo gravado terá um tamanho enorme. Por exemplo, se eu gravar vídeo por 30 segundos com alta qualidade, o vídeo gravado se tornou em torno de 30 – 40 mb.

 pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; 

Como faço para programar para compactar o vídeo gravado de alta qualidade antes de compartilhá-lo, como a Apple faz com o gravador de vídeo embutido?

Por favor me guie para resolver isso.

Obrigado!

ATUALIZADA:

Isso é o que eu estou tentando recentemente, mas ainda não tenho sucesso: eu quero comprimir o vídeo gravado que vem para didFinishPickingMediaWithInfo e armazenar no próprio caminho do próprio vídeo álbum de fotos em si, em nenhum outro lugar. Eu testei o mesmo vídeo é comprimido para tamanho muito pequeno quando eu escolho da biblioteca de fotos, mas o mesmo vídeo tirado da câmera e veio via didFinishPickingMediaWithInfo não é compactado, embora eu usei o código AVAssetExportSession abaixo.

 - (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]; }); } 

Se você quiser compactar o vídeo para compartilhamento remoto e manter a qualidade original do armazenamento local no iPhone, consulte o AVAssetExportSession ou o AVAssetWriter .

Leia também como o iOS gerencia o Assets .

 - (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"); } }]; } 

Eu acho que o vídeo já está comprimido pelo codec h264. Mas você pode tentar usar o AVFoundation para capturar os arquivos de vídeo da câmera. Mas eu suspeito que você vai acabar com o mesmo tamanho de arquivo.

Aqui estão algumas statistics para o arquivo de vídeo de 10 segundos gravado no iPhone 4 com pressões de qualidade diferentes.

 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; 

Estes são todos os valores que você pode escolher.

 UIImagePickerControllerQualityTypeHigh = 0, UIImagePickerControllerQualityType640x480 = 3, UIImagePickerControllerQualityTypeMedium = 1, // default value UIImagePickerControllerQualityTypeLow = 2 

Tente estas poucas linhas:

  [[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); }]; 

Programaticamente comprimindo vídeo usando o swift

E não se esqueça de adicionar – importar 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") } } } 

Eu encontrei uma excelente class personalizada ( SDAVAssetExportSession ) para fazer a compression de vídeo. Você pode baixá-lo neste link .

Após o download, adicione os arquivos SDAVAssetExportSession.h e SDAVAssetExportSession.m em seu projeto. Em seguida, o código abaixo ajudará a fazer a compactação. No código abaixo, você pode compactar vídeo especificando resolução e taxa de bits

 #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"); } }]; } 

Para cancelar a compression use abaixo da linha de código

  [compressionEncoder cancelExport]; //Video compression cancel