簡體   English   中英

在AVAssetExportSession中鏈接多個CAAnimation

[英]Chaining multiple CAAnimation in a AVAssetExportSession

我正在嘗試導出帶有CALayer覆蓋和隨時間鏈接的多個附加CAAnimation的視頻文件。 為此,我正在使用AVVideoCompositionCoreAnimationTool

我的CABasicAnimation通過偏移它們的beginTime來鏈接。 animationDidStop(_:finished:)我更新了相應CALayer animationDidStop(_:finished:)屬性。

我從下面的代碼示例中刪除了大部分樣板...


/* 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一起使用時, AVVideoCompositionCoreAnimationTool animationDidStop(_:finished:) ,但順序是隨機的。 導致動畫屬性的最終狀態錯誤。

最奇怪的是,如果我在animationDidStop(_:finished:)放置一個斷點,它將起作用!

另一個令人不安的結果是:如果我刪除委托,它仍然可以工作……可能是由於fillMode所致。 但我無法完全解釋。

在現實生活中,動畫是在CATransaction中相對於牆上時鍾運行的。 他們有一個開始,一個中間和一個結束。 動畫服務器會在運行循環的每一轉實時檢查情況,並根據需要推進幀。

但是,使用AVSynchronizedLayer或AVVideoCompositionCoreAnimationTool時,無需使用掛鍾。 沒有動畫服務器。 動畫被凍結,其幀通過計算被映射到視頻的時間碼。 因此,基於事務的技術不起作用。 您所擁有的只是各個框架。

就像您正確說的那樣,在這種情況下,填充模式很有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM