2011-02-17 18 views
8

Estoy buscando la manera correcta de exportar la secuencia de mis imágenes a un video quicktime.CoreAnimation, AVFoundation y capacidad de hacer exportar video

Sé que AV Foundation tiene la capacidad de fusionar o recombinar videos y también de agregar pistas de audio para crear un único elemento de video.

Ahora ... mi objetivo es un poco diferente. Yo crearía un video desde cero. Tengo un conjunto de UIImage y necesito renderizarlos todos en un solo video. Leí toda la documentación de Apple sobre AV Foundation y encontré la clase AVVideoCompositionCoreAnimationTool que tiene la capacidad de tomar una CoreAnimation y volver a codificarla como un video. También revisé el proyecto AVEditDemo provisto por Apple, pero parece que algo no funciona en mi proyecto.

Aquí mis pasos:

1) que crean la capa de CoreAnimation

CALayer *animationLayer = [CALayer layer]; 
[animationLayer setFrame:CGRectMake(0, 0, 1024, 768)]; 

CALayer *backgroundLayer = [CALayer layer]; 
[backgroundLayer setFrame:animationLayer.frame]; 
[backgroundLayer setBackgroundColor:[UIColor blackColor].CGColor]; 

CALayer *anImageLayer = [CALayer layer]; 
[anImageLayer setFrame:animationLayer.frame]; 

CAKeyframeAnimation *changeImageAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; 
[changeImageAnimation setDelegate:self]; 
changeImageAnimation.duration = [[albumSettings transitionTime] floatValue] * [uiImagesArray count]; 
changeImageAnimation.repeatCount = 1; 
changeImageAnimation.values = [NSArray arrayWithArray:uiImagesArray]; 
changeImageAnimation.removedOnCompletion = YES; 
[anImageLayer addAnimation:changeImageAnimation forKey:nil]; 

[animationLayer addSublayer:anImageLayer]; 

2) De lo que una instancia del AVComposition

AVMutableComposition *composition = [AVMutableComposition composition]; 
composition.naturalSize = CGSizeMake(1024, 768); 

CALayer *wrapLayer = [CALayer layer]; 
wrapLayer.frame = CGRectMake(0, 0, 1024, 768); 
CALayer *videoLayer = [CALayer layer]; 
videoLayer.frame = CGRectMake(0, 0, 1024, 768); 
[wrapLayer addSublayer:animationLayer]; 
[wrapLayer addSublayer:videoLayer]; 

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 


AVMutableVideoCompositionInstruction *videoCompositionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
videoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMake([imagesFilePath count] * [[albumSettings transitionTime] intValue] * 25, 25)); 

AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction]; 
videoCompositionInstruction.layerInstructions = [NSArray arrayWithObject:layerInstruction]; 

videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:wrapLayer]; 
videoComposition.frameDuration = CMTimeMake(1, 25); // 25 fps 
videoComposition.renderSize = CGSizeMake(1024, 768); 
videoComposition.instructions = [NSArray arrayWithObject:videoCompositionInstruction]; 

3) puedo exportar el video para documentar la ruta

AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetLowQuality]; 
session.videoComposition = videoComposition; 

NSString *filePath = nil; 
filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
filePath = [filePath stringByAppendingPathComponent:@"Output.mov"];  

session.outputURL = [NSURL fileURLWithPath:filePath]; 
session.outputFileType = AVFileTypeQuickTimeMovie; 

[session exportAsynchronouslyWithCompletionHandler:^ 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSLog(@"Export Finished: %@", session.error); 
     if (session.error) { 
      [[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL]; 
     } 
    }); 
}]; 

A y de la exportación de un obtener este error:

exportación Acabado: error de dominio = Código AVFoundationErrorDomain = -11822 "No se puede abrir" UserInfo = 0x49a97c0 {. NSLocalizedFailureReason = Este formato de medios no es compatible, NSLocalizedDescription = No se puede abrir}

me pareció la documentación en el interior: AVErrorInvalidSourceMedia = -11.822,

AVErrorInvalidSourceMedia La operación no se pudo completar debido a que algunos medios de origen no podían ser leídos.

Estoy totalmente seguro de que la construcción de CoreAnimation hecha por mí es correcta porque la convertí en una capa de prueba y pude ver el progreso de la animación correctamente.

¿Alguien me puede ayudar a entender dónde está mi error?

+0

prueba a publicar en los foros de desarrolladores de Apple, o presentar una informe de error con Apple. Es posible que puedan decirte lo que estás haciendo mal. –

Respuesta

4

tal vez usted necesita una película falsa que contiene el marco totalmente negro para llenar la capa de vídeo y, a continuación, añadir un CALayer a manpiulate las imágenes

+0

Esto es lo que terminé teniendo que hacer. –

+0

Lo mismo aquí. Lo bueno es que no es necesario que cubra todo lo que está intentando hacer. Estoy usando 1 segundo de video negro (que está oculto por CALayers de todos modos), pero exportando longitudes mucho más largas. – jpswain

+0

Cualquier idea con respecto a las imágenes de exportación como película con efecto de transición. Lo sé, por favor dígame ... Gracias. –

4

I found the AVVideoCompositionCoreAnimationTool class that have the ability to take a CoreAnimation and reencode it as a video

Según entendí, solo pudo tomar CoreAnimation y agregarlo a un video existente. Acabo de consultar los documentos, y los únicos métodos disponibles también requieren una capa de video.

EDITAR: sí. Excavando en documentos y videos de WWDC, creo que debería usar AVAssetWriter en su lugar y anexar imágenes al escritor. Algo así como:

AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:somePath] fileType:AVFileTypeQuickTimeMovie error:&error]; 

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:320], AVVideoWidthKey, [NSNumber numberWithInt:480], AVVideoHeightKey, nil]; 
AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; 

[videoWriter addInput:writerInput]; 

[videoWriter startWriting]; 
[videoWriter startSessionAtSourceTime:CMTimeMakeWithSeconds(0, 30)] 
[writerInput appendSampleBuffer:sampleBuffer]; 
[writerInput markAsFinished]; 
[videoWriter endSessionAtSourceTime:CMTimeMakeWithSeconds(60, 30)]; 
[videoWriter finishWriting]; 
+0

Creo que tienes razón. Voy a ver más en esto. Estoy tratando de guardar una secuencia de imágenes. – Franky

+0

En el contexto de escribir un 'UIImage' o' CGImageRef', ¿qué es 'sampleBuffer'? ¿Solo píxeles de imagen sin procesar? Hecho con 'CMSampleBufferCreateForImageBuffer'? – bcattle

+0

@bcattle haga su pregunta como una nueva pregunta, no como un comentario. – Adam

Cuestiones relacionadas