在AVAssetExportSession中链接多个CAAnimation

问题描述 投票:-1回答:1

我试图导出一个视频文件与CALayer叠加和多个附加CAAnimation链接随着时间的推移。为此,我使用AVVideoCompositionCoreAnimationTool

我的CABasicAnimation被抵消他们的beginTime链接。在animationDidStop(_:finished:)里面我更新了相应的CALayer的动画属性。

我从下面的代码示例中删除了大部分样板文件......


/* AnimationChainer is A simple class whose instance will
 * update a CALayer's model to reflect the final state of
 * the animation. a translation on the y-axis in this case. */

class AnimationChainer: NSObject, CAAnimationDelegate {

  func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    let val = anim.value(forKey: "yTranslation") as! CGFloat
    let layer = anim.value(forKey: "layer") as! CALayer
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.transform = CATransform3DMakeTranslation(0.0, val, 0.0)
    CATransaction.commit()
  }

}

/* animation setup - a layer going up by 200pt then back to original pos. */

let chainer: AnimationChainer!
let interval = 2
let movingLayer = CALayer()

let translateOnceAnimation = CABasicAnimation(keyPath: "transform.translation.y")
translateOnceAnimation.duration = 0.4
translateOnceAnimation.fromValue = 0
translateOnceAnimation.byValue = -200
translateOnceAnimation.isRemovedOnCompletion = false
translateOnceAnimation.fillMode = .forwards
translateOnceAnimation.setValue(-200, forKey: "yTranslation")
translateOnceAnimation.setValue(movingLayer, forKey: "layer")
translateOnceAnimation.delegate = chainer
translateOnceAnimation.beginTime = AVCoreAnimationBeginTimeAtZero

let translateTwiceAnimation = CABasicAnimation(keyPath: "transform.translation.y")
translateTwiceAnimation.duration = 0.4
translateTwiceAnimation.fromValue = -200
translateTwiceAnimation.byValue = 200
translateTwiceAnimation.isRemovedOnCompletion = false
translateTwiceAnimation.fillMode = .forwards
translateTwiceAnimation.setValue(0.0, forKey: "yTranslation")
translateTwiceAnimation.setValue(movingLayer, forKey: "layer")
translateTwiceAnimation.delegate = chainer
translateTwiceAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + interval

movingLayer.add(translateOnceAnimation, forKey: nil)
movingLayer.add(translateTwiceAnimation, forKey: nil)

let parentLayer = CALayer()
parentLayer.addSublayer(movingLayer)

/* end of animation setup */

let compo: AVMutableComposition!
let videoCompo: AVMutableVideoComposition!
let videoLayer: CALayer!

videoCompo.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)

let exporter = AVAssetExportSession(asset: compo, presetName: AVAssetExportPresetHighestQuality)
exporter?.videoComposition = videoCompo
exporter?.exportAsynchronously {
  self.exportDidFinish(exporter!)
}

当我在视图控制器的根视图上绑定动画层时,它很有效。但每当我使用它与AVVideoCompositionCoreAnimationTool时,animationDidStop(_:finished:)被调用,但是以随机顺序。导致动画属性的最终状态错误。

最奇怪的是,如果我在animationDidStop(_:finished:)中放置一个断点,它就可以了!

另一个令人不安的结果是:如果我删除委托它仍然有效...可能是由于fillMode。但我无法完全解释。

ios cocoa-touch avfoundation core-animation
1个回答
1
投票

在现实生活中,动画在CATransaction中运行,与壁钟相对应。它们有一个开头,一个中间和一个结尾。动画服务器在runloop的每个转弯处实时检查情况,并根据需要推进帧。

但是使用AVSynchronizedLayer或AVVideoCompositionCoreAnimationTool时,不涉及挂钟;没有动画服务器。动画被冻结,其帧通过计算映射到视频的时间码。因此,基于交易的技术不起作用;你所拥有的就是各个框架。

正如您所说,填充模式在这种情况下是一个很大的帮助。

© www.soinside.com 2019 - 2024. All rights reserved.