【问题标题】:AV Foundation animation never starts playingAV Foundation 动画从不开始播放
【发布时间】:2014-02-13 16:34:30
【问题描述】:

我正在尝试加载视频,在其上添加动画,然后将其导出, 但动画永远不会在导出的视频中开始播放。 它只是按原样显示图像“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");
            }
        };
    }];
}

【问题讨论】:

    标签: ios animation core-animation avfoundation


    【解决方案1】:

    我不确定我做了什么。 我从头开始重写了整个代码并添加了

    animation.removedOnCompletion = NO;
    

    到所有动画,现在它可以工作了。

    【讨论】:

      【解决方案2】:

      文档说明:

      您使用 AVVideoCompositionCoreAnimationTool 对象来合并 视频合成中的核心动画。

      任何动画都将在视频的时间线上进行解释,而不是 实时,因此您应该:

      1. 将动画的 beginTime 属性设置为 AVCoreAnimationBeginTimeAtZero 而不是 0(CoreAnimation 用 CACurrentMediaTime 替换);
      2. 在动画上将 removedOnCompletion 设置为 NO,这样它们就不会被自动删除;
      3. 避免使用与 UIView 对象关联的图层。

      https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVVideoCompositionCoreAnimationTool_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40009744-CH1-DontLinkElementID_1

      为什么要添加

      animation.removedOnCompletion = NO;
      

      按照您对自己问题的回答中的说明进行操作。虽然我不能 100% 确定这里发生了什么,但如果我不得不猜测,我会说核心动画经过预处理,然后与视频层合成。如果你删除它,它会在视频合成发生之前被删除。

      在将 CALayers 和动画与合成一起使用时,如果我希望它们“关闭”,我必须将它们设置为不透明度为 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];
      

      基本上就是这样,只需以秒为单位设置开始和持续时间。它在帧和时间之间获得“有趣”的跟踪,但你可以做到。我使用了大量的动画层,它们都连接到一个层中,都具有多个时序。最大的麻烦就是跟踪什么是什么,什么时候开始。

      【讨论】:

      • 两秒后要添加动画怎么办?我可以在 AVCoreAnimationBeginTimeAtZero 中添加几秒钟吗?我试过 flipAnimation.beginTime = CACurrentMediaTime() + 1;但没有运气。
      • 您需要自己计算时间并将其添加到动画中。我认为您不能在合成视频的上下文中使用 CACurrentMediaTime 。我会在答案中为您添加一些细节。
      猜你喜欢
      • 2011-11-14
      • 1970-01-01
      • 2018-05-30
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多