hacer - iPhone: comprime programáticamente el video grabado para compartir?
como hacer video con iphone (6)
Implementé una vista de superposición al llamar a la vista de cámara antes de grabar el video.
pickerController.cameraOverlayView =myOverlay;
Grabar video y guardar el video en el álbum después de grabar el video y compartirlo por correo electrónico, etc. todo funciona bien.
Si utilizo la calidad de video como "Alta calidad", entonces el video grabado se ha convertido en un gran tamaño. Por ejemplo, si grabo video durante 30 segundos con alta calidad, el video grabado se ha convertido en alrededor de 30 a 40 mb.
pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
¿Cómo programo comprimir el video grabado de alta calidad antes de compartirlo, como lo hace Apple con la grabadora de video incorporada?
Por favor, guíame para resolver esto.
¡Gracias!
ACTUALIZADO:
Esto es lo que estoy intentando recientemente, pero todavía no es exitoso: quiero comprimir el video grabado que llega a didFinishPickingMediaWithInfo y almacenar en el mismo álbum de fotos la propia ruta de video, no en ningún otro lado. Probé que el mismo video se comprime a un tamaño muy pequeño cuando selecciono desde la biblioteca de fotos, pero el mismo video tomado de la cámara y que vino a través de didFinishPickingMediaWithInfo no se comprime, aunque utilicé el código AVAssetExportSession a continuación.
- (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];
});
}
Componiendo programáticamente video con usar swift
Y no olvides agregar - 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")
}
}
}
Encontré una excelente clase personalizada ( SDAVAssetExportSession ) para hacer la compresión de video. Puedes descargarlo desde este SDAVAssetExportSession .
Después de la descarga, agregue los archivos SDAVAssetExportSession.hy SDAVAssetExportSession.m a su proyecto. Luego, el siguiente código ayudará a hacer la compresión. En el código a continuación, puede comprimir video especificando resolución y tasa 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 la compresión Use debajo de la línea de código
[compressionEncoder cancelExport]; //Video compression cancel
Pruebe estas pocas líneas:
[[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);
}];
Si desea comprimir el video para compartirlo a distancia y mantener la calidad original para el almacenamiento local en el iPhone, debe buscar en AVAssetExportSession o AVAssetWriter .
También lea sobre cómo iOS administra los 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");
}
}];
}
Supongo que el video ya está comprimido por el códec h264. Pero puede intentar usar AVFoundation para capturar los archivos de video de la cámara. Pero sospecho que terminarás con los mismos tamaños de archivo.
Aquí hay algunas estadísticas del archivo de video de 10 segundos grabado en el iPhone 4 con diferentes presets de calidad.
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;
Estos son todos los valores que puede elegir.
UIImagePickerControllerQualityTypeHigh = 0,
UIImagePickerControllerQualityType640x480 = 3,
UIImagePickerControllerQualityTypeMedium = 1, // default value
UIImagePickerControllerQualityTypeLow = 2