I'm trying to export an animation for my custom CALayer with a custom property via AVExportSession, please find the setup below:
class CustomAnimatable: CALayer
{
@NSManaged var brightness: CGFloat
override init(layer: Any) {
super.init(layer: layer);
if let l = layer as? CustomAnimatable {
self.brightness = l.brightness;
}
}
override func action(forKey event: String) -> CAAction?
{
if event == "brightness" {
let animation = CABasicAnimation(keyPath: event);
animation.fromValue = presentation()?.brightness ?? self.brightness;
return animation;
}
return super.action(forKey: event);
}
override class func needsDisplay(forKey key: String) -> Bool
{
if key == "brightness" {
return true;
}
return super.needsDisplay(forKey: key);
}
override func display()
{
print("\(self) \(presentation()?.brightness) \(self.brightness)")
}
}
Here's the export session pre-setup:
func render()
{
......
let parentLayer = CALayer();
let videoLayer = CALayer();
let animationLayer = CustomAnimatable()
parentLayer.frame = frame;
videoLayer.frame = frame;
animationLayer.frame = frame;
parentLayer.addSublayer(videoLayer);
parentLayer.addSublayer(animationLayer);
CATransaction.begin()
CATransaction.setAnimationDuration(2.2);
CATransaction.setDisableActions(true);
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear))
let anim = CABasicAnimation(keyPath: "brightness");
anim.fromValue = 1.0;
anim.fillMode = kCAFillModeBoth;
anim.beginTime = AVCoreAnimationBeginTimeAtZero;
anim.repeatCount = 1;
anim.toValue = 0.0;
anim.isRemovedOnCompletion = false;
animationLayer.add(anim, forKey: "anim")
CATransaction.commit()
let videoComposition = AVMutableVideoComposition();
videoComposition.renderSize = CGSize(width: width, height: height);
videoComposition.instructions = [mainInstruction];
videoComposition.frameDuration = CMTimeMake(1, 30);
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer);
....
}
The issue is that the brightness
value in the resulting video goes from 1 to 0 without animation. If I attempt to animate CALayer
's native properties, e.g. opacity
- the exported animation video is totally fine, the opacity smoothly fades from 1 to 0.
Am I doing it wrong for custom property?
Things I've considered:
- wrapping the explicit animation into
CATransaction
to disable implicit actions - setting animation begin time to
AVCoreAnimationBeginTimeAtZero
andisRemovedOnCompletion
to false as per "Editing Media with AV Foundation" session (Core Animation Gotchas section)
I'm a bit confused by the fact that native CALayer properties animate fine, thus the export session setup seems to be correct.
Besides that, if I add the custom layer to a view and animate the brightness
property - it also animates fine. So the issue seems to be specific to rendering custom property animation w/ AVExportSession.