问题:
我使用AVFoundation创建视频时,无法使视频正确地显示在一个CALayer
中,以适合指定的尺寸。
示例:
这是视频应该呈现给用户的样子(在应用程序中):
但是,当导出视频时,结果如下所示:
详情
你可以看到,它应该是一个方形视频,绿色背景,视频适合指定框架。但是,生成的视频不适合用于包含它的CALayer
(请看视频应该被拉伸到的黑色空间)。有时视频会填充图层,但超出范围(宽度或高度过大),并且通常不能保持视频的自然比例。
代码
CGRect displayedFrame = [self adjustedVideoBoundsFromVideo:gifVideo];//the cropped frame
CGRect renderFrame = [self renderSizeForGifVideo:gifVideo]; //the full rendersize
AVAsset * originalAsset = self.videoAsset;
AVAssetTrack * videoTrack = [[originalAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableComposition * mainComposition = [AVMutableComposition composition];
AVMutableCompositionTrack * compositionTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, originalAsset.duration) ofTrack:videoTrack atTime:kCMTimeZero error:nil];
CALayer * parentLayer = [CALayer layer];
CALayer * backgroundLayer = [CALayer layer];
CALayer * videoLayer = [CALayer layer];
parentLayer.frame = renderFrame;
backgroundLayer.frame = parentLayer.bounds;
backgroundLayer.backgroundColor = self.backgroundColor.CGColor;
videoLayer.frame = displayedFrame;
[parentLayer addSublayer:backgroundLayer];
[parentLayer addSublayer:videoLayer];
AVMutableVideoComposition * videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.frameDuration = CMTimeMake(1, 30);
videoComposition.renderSize = CGSizeMake(renderFrame.size.width, renderFrame.size.height);
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool
videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
AVMutableVideoCompositionInstruction * instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mainComposition.duration);
AVMutableVideoCompositionLayerInstruction * layerInstruction = [AVMutableVideoCompositionLayerInstruction
videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = @[layerInstruction];
videoComposition.instructions = @[instruction];
NSString* videoName = @"myNewGifVideo.mp4";
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
{
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
AVAssetExportSession * exporter = [[AVAssetExportSession alloc] initWithAsset:mainComposition presetName:AVAssetExportPresetHighestQuality];
exporter.videoComposition = videoComposition;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.outputURL = exportUrl;
[exporter exportAsynchronouslyWithCompletionHandler:^
{
dispatch_async(dispatch_get_main_queue(), ^{
self.finalVideo = exportUrl;
[self.delegate shareManager:self didCreateVideo:self.finalVideo];
if (completionBlock){
completionBlock();
}
});
}];
我尝试过的方法:
我尝试了调整videoLayer
的frame
、bounds
和contentGravity
,但都没有用。
我尝试在AVMutableVideoCompositionLayerInstruction
中添加transform
来将视频缩放到displayRect
的大小(可以选择许多不同的视频,它们的宽度和高度是可变的。每个视频在生成的视频中显示不同,没有一个正确的)。有时候转换会使一个维度正确(通常是宽度),但会搞砸另一个维度。如果我稍微以不同的方式裁剪/缩放视频,它就永远无法保持一个维度的一致性。
我尝试更改videoComposition
的renderSize
,但这会破坏正方形裁剪。
我似乎做不好。如何使视频完美填充videoLayer
与displayedFrame
帧(最后注意:视频的naturalSize
与displayedFrame
不同,这就是我尝试转换它的原因)?