2011-08-08 65 views
13

我正在嘗試在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];

+0

我有同樣的問題。你找到了解決辦法嗎? –

+1

是的,儘管我也遇到了一些其他肖像模式組合問題。技巧是在AVMutableVideoCompositionLayerInstruction上設置變換。但是,正確的轉換不是資產的首選轉換。從首選轉換開始,並應用其他翻譯和翻轉。你會發現一些工作(作爲框架大小的函數)。不幸的是,正確的轉換對每個方向都是不同的基本上,組合中存在一個錯誤,我們通過定位輸出層來解決它。我確實得到它的工作。 – wombat57

回答

2

試試這個,添加其他指令以及。

///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]; 

讓我知道如何去!

MacMike

+0

不好(我曾嘗試過,將compositionVideoTrack.preferredTransform傳遞給passThroughLayer setTransform)。長寬比仍然是風景,並且沒有視頻框顯示(除了CALayer動畫)。似乎AVVideoCompositionCoreAnimationTool不處理矩陣。 – wombat57

+0

這可能適用於某些視頻,但不適用於我測試的視頻。無論哪種方式,這對我來說都很有幫助,因爲這似乎是正確的選擇。謝謝。 –

相關問題