2011-08-08 8 views
13

iOS 4.3에서 AVMutableComposition, AVMutableVideoComposition 및 AVVideoCompositionCoreAnimationTool을 사용하여 CALayer를 세로 모드 비디오 (내보내기시)로 베이크하려고합니다. 이 모든 것이 가로로 작동합니다. 그러나 비디오를 세로로 캡처하면 AVVideoCompositionCoreAnimationTool이 비디오 트랙의 변환을 무시합니다. 즉, 세로 모드 비디오의 경우 AVMutableCompositionTrack.preferredTransform을 원래 에셋 비디오 트랙의 preferredTransform 값으로 설정합니다. AVVideoCompositionCoreAnimationTool을 사용하지 않는 한이 방법이 작동하며 비디오가 세로 모드로 나옵니다. 그러나 AVVideoCompositionCoreAnimationTool과 CALayer를 추가하자마자 파일이 가로로 나옵니다. (CALayer는 올바르게 표시되지만 뒤에있는 비디오는 측면에 있으며 파일의 가로 세로 비율은 꺼져 있습니다.) CALayer에 변환을 적용하고 ACVideoComposition에 변형을 설정해 보았습니다. 이들 중 어느 것도 제작 된 파일의 방향을 변경하지 않습니다 (여전히 360x480이 아닌 480x369입니다). AVVideoCompositionCoreAnimationTool을 사용하여 세로 모드 비디오를 렌더링하는 방법이 있습니까?AVVideoCompositionCoreAnimationTool 및 세로 모드의 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]; 

마지막으로 나는 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]; 

그리고 수출에의 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를 설정!

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

이 코드는 가로 모드에서 작동하고, 또한 세로 I 라인 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

이것은 아마도 일부 비디오에서는 작동하지만 테스트 한 비디오에서는 작동하지 않습니다. 어느 쪽이든, 그것은 나에게 큰 도움이됩니다. 왜냐하면 이것이 올바른 방법 일 것 같기 때문입니다. 감사. –