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];
Tengo el mismo problema. ¿Ha encontrado una solución para esto? –
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