2011-08-08 4 views
13

私は、CALayerをiOS 4.3のAVMutableComposition、AVMutableVideoComposition、AVVideoCompositionCoreAnimationToolを使用して、ポートレートモードのビデオ(書き出し時)に焼き付けようとしています。これはすべて風景で動作します。しかし、私が肖像画でビデオをキャプチャする場合、AVVideoCompositionCoreAnimationToolはビデオトラックのトランスフォームを無視しています。つまり、ポートレートモードのビデオでは、AVMutableCompositionTrack.preferredTransformを元のアセットビデオトラックのpreferredTransform値に設定しています。 AVVideoCompositionCoreAnimationToolを使用しない限り、これは機能し、ビデオはポートレートモードで出力されます。 AVVideoCompositionCoreAnimationToolとCALayerを追加するとすぐに、ファイルはランドスケープで出力されます。 (CALayerは正しく表示されますが、その背後にあるビデオは横にあり、ファイルの縦横比はオフです)。私は変換をCALayerに適用し、ACVideoCompositionに変換を設定しようとしました。これらのどちらも、作成されたファイルの向きを変更しません(まだ360x480ではなく480x369です)。 AVVideoCompositionCoreAnimationToolでポートレートモードのビデオをレンダリングする方法はありますか?AVVideoCompositionCoreAnimationToolと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]; 

と輸出に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]; 

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

このコードは、風景モードで動作し、私は行を削除する場合も、肖像画に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

これはおそらく一部の動画では動作しますが、テストした動画では動作しません。いずれにせよ、これは私にとって大きな助けとなる。なぜなら、これは正しい方法だと思われるからだ。ありがとう。 –

関連する問題