CALayer.contents在AVMutableComposition中不能正确渲染
我有一个非常简单的方法,用一个静态背景图像来生成一个video,该静态背景图像覆盖了整个video的组成部分,以及一个位于video底部的较小的,部分透明的图像(水印风格)。
背景图像正确呈现,看起来与图像查看器中的完全相同。 然而,应该在video底部呈现的图像是倾斜/扭曲的。
源代码可以在这里下载到GitHub上。
我的代码的预期输出(所需video输出的样机):
我的代码的实际输出(从iOS模拟器部分截图):
正如您所看到的,页脚图像呈45度倾斜并呈波浪状。
以下是我目前用来生成video的代码。 我已经尝试过所有可能的contentGravity组合,但没有运气。 我见过的其他每个例子都只是将CGImageRef设置为图层的contents
然后将bounds
, position
和anchorPoint
为适当的值。 我还没有看到其他任何设置其他属性的例子。 我已经阅读了几乎所有的AVFoundation的文件,看看是否有设置,我错过了,但我还没有遇到任何明显的事情。
任何build议将不胜感激。 谢谢!
接口声明:
CGSize _renderingSize; float _displayDuration; AVMutableComposition *mutableComposition; AVMutableVideoComposition *videoComposition; AVMutableCompositionTrack *mutableCompositionVideoTrack; AVAssetExportSession *exporter;
ViewDidLoad设置:
_renderingSize = CGSizeMake(640, 360); _displayDuration = 2.0;
渲染代码块:
mutableComposition = [AVMutableComposition composition]; mutableCompositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; videoComposition = [AVMutableVideoComposition videoComposition]; videoComposition.renderSize = _renderingSize; videoComposition.frameDuration = CMTimeMake(1, 30); CALayer *parentLayer = [CALayer layer]; CALayer *videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height); videoLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height); [parentLayer addSublayer:videoLayer]; videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; NSString *path = [[NSBundle mainBundle] pathForResource:@"blank_1080p" ofType:@"mp4"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAsset *asset = [AVAsset assetWithURL:url]; AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; [mutableCompositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,CMTimeMakeWithSeconds(_displayDuration, 600)) ofTrack:track atTime:kCMTimeZero error:nil]; CALayer *imageLayer = [CALayer layer]; imageLayer.bounds = parentLayer.frame; imageLayer.anchorPoint = CGPointMake(0.5, 0.5); imageLayer.position = CGPointMake(CGRectGetMidX(imageLayer.bounds), CGRectGetMidY(imageLayer.bounds)); imageLayer.contents = (id)[UIImage imageNamed:@"background.png"].CGImage; imageLayer.contentsGravity = kCAGravityResizeAspectFill; [parentLayer addSublayer:imageLayer]; UIImage *testImage = [UIImage imageNamed:@"bannerTextLayer.png"]; CALayer *footerLayer = [CALayer layer]; footerLayer.bounds = CGRectMake(0, 0, 540, 40); footerLayer.anchorPoint = CGPointMake(0.5, 0.5); footerLayer.position = CGPointMake(CGRectGetMidX(footerLayer.bounds), CGRectGetMidY(footerLayer.bounds)); footerLayer.contents = (id)testImage.CGImage; footerLayer.contentsGravity = kCAGravityResizeAspectFill; [parentLayer addSublayer:footerLayer]; AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(_displayDuration, 600)); videoComposition.instructions = @[instruction]; exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality]; exporter.outputURL = videoURL ; exporter.videoComposition = videoComposition; exporter.outputFileType= AVFileTypeMPEG4; exporter.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(_displayDuration, 600)); exporter.shouldOptimizeForNetworkUse = YES; [exporter exportAsynchronouslyWithCompletionHandler:^(void){ switch (exporter.status) { case AVAssetExportSessionStatusFailed:{ NSLog(@"Fail: %@", exporter.error); break; } case AVAssetExportSessionStatusCompleted:{ NSLog(@"Success"); dispatch_async(dispatch_get_main_queue(), ^{ if (self.moviePlayer) [self.moviePlayer.view removeFromSuperview]; self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL]; self.moviePlayer.view.frame = CGRectMake(0, 0, 320, 180); [self.moviePlayer setControlStyle:MPMovieControlStyleNone]; [self.previewView addSubview:self.moviePlayer.view]; [self.moviePlayer play]; }); break; } default: break; } }];
iOS模拟器7.0及以上版本有使用AVExportSession渲染video的这个错误。 如果你将在实际的设备上testing这个,输出将是你想要的,它不会歪斜。