私は、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];
私は同じ問題を抱えています。あなたはこれに対する解決策を見つけましたか? –
はい、ポートレートモードのコンポジションでも他の問題が発生しました。このトリックは、AVMutableVideoCompositionLayerInstructionで変換を設定します。しかし、正しい変換はアセットの優先変換ではありません。優先変換から始め、追加の翻訳と反転を適用します。あなたは(フレームサイズの関数として)動作するものを見つけるでしょう。残念なことに、正しい変換はすべての方向について異なります。基本的には、コンポジションにバグがあり、我々はエクスポートレイヤーを配置することでその問題を回避しようとしています。私はそれを働かせた。 – wombat57