2011-08-08 14 views
13

Estoy intentando hornear un CALayer en un video de modo retrato (en la exportación) usando una composición AVMutableComposition, una composición AVMutableVideo y una herramienta AVVideoCompositionCoreAnimationTool en iOS 4.3. Todo esto funciona en el paisaje. Sin embargo, si capturo video en vertical, AVVideoCompositionCoreAnimationTool está ignorando la transformación en la pista de video. Es decir, para video en modo retrato, estoy configurando AVMutableCompositionTrack.preferredTransform en el valor de Transform preferido de la pista de video de activos original. Siempre que no use una AVVideoCompositionCoreAnimationTool, esto funciona, y el video sale en modo retrato. Tan pronto como agregue un AVVideoCompositionCoreAnimationTool y CALayer, sin embargo, el archivo sale en formato horizontal. (El CALayer aparece correctamente, pero el video detrás está de lado y la relación de aspecto del archivo está desactivada). Intenté aplicar la transformación al CALayer y establecer una transformación en ACVideoComposition. Ninguno de estos cambia la orientación del archivo producido (todavía es 480x369, no 360x480). ¿Hay alguna manera de reproducir video en modo retrato con AVVideoCompositionCoreAnimationTool?AVVideoCompositionCoreAnimationTool y CALayer en modo vertical?

Primero creó una AVMutableComposition y AVMutableVideoComposition

AVMutableComposition *composition = [AVMutableComposition composition]; 
AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:url options:nil]; 
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]); 
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 

CGSize videoSize = CGSizeApplyAffineTransform(clipVideoTrack.naturalSize, clipVideoTrack.preferredTransform); 
videoSize.width = fabs(videoSize.width); 
videoSize.height = fabs(videoSize.height); 

CMTime titleDuration = CMTimeMakeWithSeconds(5, 600); 
CMTimeRange titleRange = CMTimeRangeMake(kCMTimeZero, titleDuration); 

[compositionVideoTrack insertTimeRange:titleRange ofTrack:nil atTime:kCMTimeZero error:nil]; 
[compositionVideoTrack insertTimeRange:timeRange ofTrack:clipVideoTrack atTime:titleDuration error:nil]; 
compositionVideoTrack.preferredTransform = clipVideoTrack.preferredTransform; 

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [composition duration]); 
AVAssetTrack *videoTrack = [[composition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];  
passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer]; 
videoComposition.instructions = [NSArray arrayWithObject:passThroughInstruction];  
videoComposition.frameDuration = CMTimeMake(1, 30); 
videoComposition.renderSize = videoSize; 
videoComposition.renderScale = 1.0; 

Y un CALayer con un título

CALayer *animationLayer = [CALayer layer]; 
animationLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height); 

CATextLayer *titleLayer = [CATextLayer layer]; 
titleLayer.string = [effect valueForKey:@"title"]; 
titleLayer.font = [effect valueForKey:@"font"]; 
titleLayer.fontSize = 30; 

titleLayer.alignmentMode = kCAAlignmentCenter; 
titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height/6); 

[animationLayer addSublayer:titleLayer]; 
titleLayer.anchorPoint = CGPointMake(0.5, 0.5); 
titleLayer.position = CGPointMake(CGRectGetMidX(layer.bounds), CGRectGetMidY(layer.bounds));  

CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
fadeAnimation.fromValue = [NSNumber numberWithFloat:1.0]; 
fadeAnimation.toValue = [NSNumber numberWithFloat:0.0]; 
fadeAnimation.additive = NO; 
fadeAnimation.removedOnCompletion = NO; 
fadeAnimation.beginTime = 3.5; 
fadeAnimation.duration = 1.0; 
fadeAnimation.fillMode = kCAFillModeBoth; 
[titleLayer addAnimation:fadeAnimation forKey:nil]; 

Finalmente agrego el CALayer a la AVMutableVideoComposition

CALayer *parentLayer = [CALayer layer]; 
CALayer *videoLayer = [CALayer layer]; 

parentLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height); 
parentLayer.anchorPoint = CGPointMake(0, 0); 
parentLayer.position = CGPointMake(0, 0); 

videoLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height); 
[parentLayer addSublayer:videoLayer]; 
videoLayer.anchorPoint = CGPointMake(0.5, 0.5); 
videoLayer.position = CGPointMake(CGRectGetMidX(parentLayer.bounds), CGRectGetMidY(parentLayer.bounds)); 
[parentLayer addSublayer:layer];  
animationLayer.anchorPoint = CGPointMake(0.5, 0.5); 
animationLayer.position = CGPointMake(CGRectGetMidX(parentLayer.bounds), CGRectGetMidY(parentLayer.bounds)); 
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 

y exportación!

AVAssetExportSession *exportSession = [[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality] autorelease]; 
exportSession.videoComposition = videoComposition; 

NSURL *segmentFileURL = //some local URL 
exportSession.outputFileType = @"com.apple.quicktime-movie"; 
exportSession.outputURL = segmentFileURL; 


[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
    switch ([exportSession status]) { 
     case AVAssetExportSessionStatusFailed: 
      Log(@"Export failed: %@", [exportSession error]); 
      break; 
     case AVAssetExportSessionStatusCancelled: 
      Log(@"Export canceled"); 
      break; 
     case AVAssetExportSessionStatusCompleted: 
      Log(@"Export done"); 
      break; 
    } 
}]; 

Este código funciona en modo horizontal, y también en el retrato Si quito la línea videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

+0

Tengo el mismo problema. ¿Ha encontrado una solución para esto? –

+1

Sí, aunque me encontré con un montón de otros problemas con las composiciones de modo retrato también. El truco consiste en establecer la transformación en AVMutableVideoCompositionLayerInstruction. Sin embargo, la transformación correcta no es la transformación preferida del activo. Comience con la transformación preferida y aplique traducciones adicionales y voltea. Encontrarás algo que funcione (en función del tamaño del marco). Lamentablemente, la transformación correcta es diferente para cada orientación. Básicamente, hay un error en la composición, y estamos trabajando a su alrededor mediante el posicionamiento de la capa de exportación. Lo hice funcionar. – wombat57

Respuesta

2

Prueba esto y añadir sus otras instrucciones también.

///turn video 90 degrees 
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack]; 
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(degreesToRadians(90.0)); 
CGAffineTransform rotateTranslate = CGAffineTransformTranslate(rotationTransform,320,0); 
[passThroughLayer setTransform:rotateTranslate atTime:kCMTimeZero]; 

¡Avísame cómo te va!

MacMike

+0

No es bueno (lo había intentado antes, pasando compositionVideoTrack.preferredTransform a passThroughLayer setTransform). La relación de aspecto sigue siendo apaisada, y no se muestran los cuadros de video (además de la animación CALayer). Parece que AVVideoCompositionCoreAnimationTool no maneja la matriz. – wombat57

+0

Esto probablemente funciona en algunos videos, pero no en los que probé. De cualquier manera, es de gran ayuda para mí, ya que este parece ser el camino correcto a seguir. Gracias. –

Cuestiones relacionadas