我正在尝试加载视频,在其上添加动画然后将其导出, 但动画永远不会在导出的视频中播放。 它只显示图像" dogge_icon.png"原样。
我尝试过不同类型的动画,不确定我做错了什么。 任何帮助将不胜感激。
代码:
-(void) createCompositionWithPicture {
AVMutableComposition* composition = [AVMutableComposition composition];
NSString *videoPath = [[NSBundle mainBundle] pathForResource:@"Movie" ofType:@"m4v"];
NSLog(@"Path: %@", videoPath);
NSURL *videoURL = [[NSURL alloc] initFileURLWithPath:videoPath];
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];
// Create an AVMutableVideoCompositionLayerInstruction for the video track.
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
// Setup video composition
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height);
videoComposition.frameDuration = CMTimeMake(1, 30);
mainInstruction.layerInstructions = [NSArray arrayWithObject:videolayerInstruction];
videoComposition.instructions = [NSArray arrayWithObject:mainInstruction];
NSLog(@"Width: %f Height: %f", videoTrack.naturalSize.width, videoTrack.naturalSize.height);
// Setup animation layer
UIImage* image = [UIImage imageNamed:@"dogge_icon.png"];
CALayer *animationLayer = [CALayer layer];
animationLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height);
[animationLayer setMasksToBounds:YES];
[animationLayer setContents: (id)image.CGImage];
// Add animation
CABasicAnimation *animation =
[CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.duration=5.0;
animation.autoreverses=YES;
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:2.0f];
animation.repeatCount=10;
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[animationLayer addAnimation:animation forKey:@"scale"];
NSLog(@"animationLayer animations: %@", [animationLayer animationKeys]);
// Build layer hierarchy
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
videoLayer.frame = CGRectMake(0, 0, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:animationLayer];
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool
videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
// Export
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
NSString *exportVideoPath = [STPFileUtilities getPathToFileIn: NSDocumentDirectory WithName: @"composition.mov"];
[STPFileUtilities deleteFileIfExists:exportVideoPath];
NSURL *exportURL = [NSURL fileURLWithPath:exportVideoPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.videoComposition = videoComposition;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusFailed:{
NSLog(@"FAIL: %@", exportSession.error);
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog (@"SUCCESS");
}
};
}];
}
答案 0 :(得分:2)
我不确定我做了什么。 我从头开始重写了整个代码并添加了
animation.removedOnCompletion = NO;
所有动画现在都有效。
答案 1 :(得分:1)
文档说明:
使用AVVideoCompositionCoreAnimationTool对象进行合并 视频合成中的核心动画。
任何动画都将在视频的时间轴上解释,而不是 实时,所以你应该:
- 将动画的beginTime属性设置为AVCoreAnimationBeginTimeAtZero而不是0(CoreAnimation替换为CACurrentMediaTime);
- 将动画上的removedOnCompletion设置为NO,这样就不会自动删除;
- 避免使用与UIView对象关联的图层。
醇>
因此添加
的原因animation.removedOnCompletion = NO;
按照您对自己问题的回答中的说明工作。虽然我不是100%肯定这里发生了什么,但如果我不得不猜测,我会说核心动画是经过预处理然后与视频层合成的。如果删除它,则在视频合成发生之前将其删除。
当使用带有合成的CALayers和Animations时,如果我想让它们“关闭”,我必须将它们设置为0不透明度以隐藏它们。
如何在特定时间开始动画。
以下示例(未经测试)实质上是将整个图层设置为透明(不透明度为0.0)。在2秒(startTime)时,它开始动画并在3秒内将不透明度从0.5减少到1.0(半透明到完全不透明)。它应该在结束时“关闭” - 它将默认返回到它的初始化(完全透明)值。
float startTime = 2.0f;
float duration = 3.0f;
CALayer layerToAnimate = [CALayer layer];
layerToAnimate.opacity = 0.0;
// Just turn it on then off.
CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[myAnimation setBeginTime: startTime];
[myAnimation setDuration: duration];
[myAnimation setFromValue:[NSNumber numberWithFloat:0.5]];
[myAnimation setToValue:[NSNumber numberWithFloat:1.0]];
[myAnimation setRemovedOnCompletion:NO];
[layerToAnimate addAnimation:myAnimation forKey:@"myUniqueAnimationKey"];
// NB You may not need to be specific on track ID. I like to do so to use to sort layers in to the proper order.
AVVideoCompositionCoreAnimationTool *aniTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithAdditionalLayer:_layerToAnimate asTrackID:intTrackID];
基本上就是这样,只需设置开始和持续时间,以秒为单位。它可以在帧和时间之间进行“有趣”的跟踪,但是你可以做到。我使用大量的动画层连接到一个层,所有动画层都有多个时间。最大的麻烦就是跟踪什么是什么以及何时发生。