通过 AVExportSession 导出带有隐式动画的 CALayer
Posted
技术标签:
【中文标题】通过 AVExportSession 导出带有隐式动画的 CALayer【英文标题】:Exporting CALayer with implicit animation via AVExportSession 【发布时间】:2017-11-08 13:47:20 【问题描述】:我正在尝试通过 AVExportSession 为我的自定义 CALayer 导出一个带有自定义属性的动画,请在下面找到设置:
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)")
这是导出会话的预设置:
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);
....
问题是生成的视频中的 brightness
值在没有动画的情况下从 1 变为 0。如果我尝试为CALayer
的原生属性设置动画,例如opacity
- 导出的动画视频完全没问题,不透明度从1平滑渐变到0。
我对自定义属性做错了吗?
我考虑过的事情:
将显式动画包装到CATransaction
以禁用隐式操作
根据“Editing Media with AV Foundation”会话(核心动画陷阱部分)将动画开始时间设置为 AVCoreAnimationBeginTimeAtZero
和 isRemovedOnCompletion
为 false
我对原生 CALayer 属性的动画效果感到有些困惑,因此导出会话设置似乎是正确的。
除此之外,如果我将自定义层添加到视图并为 brightness
属性设置动画 - 它的动画效果也很好。所以这个问题似乎是特定于使用 AVExportSession 渲染自定义属性动画。
【问题讨论】:
【参考方案1】:我不完全确定您为什么在 parentLayer?
中同时添加了 videoLayer
和 animationLayer
类。
parentLayer.addSublayer(videoLayer);
parentLayer.addSublayer(animationLayer);
使用下面的代码希望对你有帮助!
parentLayer.addSublayer(videoLayer);
videoLayer.addSublayer(animationLayer);
【讨论】:
我以与 Apples 示例相同的方式构建图层组合(其他教程建议采用相同的方式)。请参阅此处github.com/master-nevi/WWDC-2010/blob/… 无论如何更改动画层的父级不会改变结果 - 原生 CALayeropacity
渲染良好,自定义属性没有动画。以上是关于通过 AVExportSession 导出带有隐式动画的 CALayer的主要内容,如果未能解决你的问题,请参考以下文章