我正在嘗試在iOS 4.3上使用AVMutableComposition,AVMutableVideoComposition和AVVideoCompositionCoreAnimationTool將CALayer烤成肖像模式視頻(導出時)。這一切都適用於風景。但是,如果我以縱向捕捉視頻,AVVideoCompositionCoreAnimationTool會忽略視頻軌道上的變換。也就是說,對於縱向模式視頻,我將AVMutableCompositionTrack.preferredTransform設置爲來自原始資產視頻軌道的preferredTransform值。只要我不使用AVVideoCompositionCoreAnimationTool,它就可以工作,並且視頻以縱向模式出現。只要我添加一個AVVideoCompositionCoreAnimationTool和CALayer,然而,該文件出現在橫向。 (CALayer顯示正確,但背後的視頻位於其旁邊,並且文件的寬高比爲關閉)。我嘗試將轉換應用於CALayer,並在ACVideoComposition中設置轉換。這些都不會改變生成的文件的方向(它仍然是480x369,而不是360x480)。有沒有辦法使用AVVideoCompositionCoreAnimationTool渲染肖像模式視頻?AVVideoCompositionCoreAnimationTool和CALayer在縱向模式下?
首先,我建立了一個AVMutableComposition和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;
而一個CALayer的一個標題
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];
最後我想補充的CALayer到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];
並出口!
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;
}
}];
此代碼工作在橫向模式,以及在肖像,如果我刪除行videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
我有同樣的問題。你找到了解決辦法嗎? –
是的,儘管我也遇到了一些其他肖像模式組合問題。技巧是在AVMutableVideoCompositionLayerInstruction上設置變換。但是,正確的轉換不是資產的首選轉換。從首選轉換開始,並應用其他翻譯和翻轉。你會發現一些工作(作爲框架大小的函數)。不幸的是,正確的轉換對每個方向都是不同的基本上,組合中存在一個錯誤,我們通過定位輸出層來解決它。我確實得到它的工作。 – wombat57