在我的 iOS 应用程序的 UI 中,我显示了一个复杂的层次结构CALayer
s。其中一层是AVPlayerLayer
显示视频CIFilter
实时应用(使用AVVideoComposition(asset:, applyingCIFiltersWithHandler:)
).
现在我想将此图层合成导出到视频文件。里面有两个工具AVFoundation
这似乎有帮助:
A: AVVideoCompositionCoreAnimationTool
它允许在(可能是动画的)内渲染视频CALayer
等级制度
B: AVVideoComposition(asset:, applyingCIFiltersWithHandler:)
,我也在 UI 中使用它来应用CIFilter
s 到视频资产。
但是,这两个工具不能同时使用:如果我启动一个AVAssetExportSession
结合了这些工具,AVFoundation
抛出一个NSInvalidArgumentException
:
期望视频合成仅包含AVCoreImageFilterVideoCompositionInstruction
我尝试按如下方式解决此限制:
解决方法1
1) 使用设置导出AVAssetReader
and AVAssetWriter
2) 从资产读取器获取样本缓冲区并应用CIFilter
,将结果保存在CGImage
.
3) 设置CGImage
as the content
层层次结构中视频层的位置。现在,图层层次结构“看起来像”最终视频的一帧。
4)获取数据CVPixelBuffer
对于资产编写器使用的每个帧CVPixelBufferGetBaseAddress
并创建一个CGContext
与该数据。
5)使用以下命令将我的图层渲染到该上下文CALayer.render(in ctx: CGContext)
.
此设置有效,但速度非常慢 - 导出 5 秒的视频有时需要一分钟。它看起来像CoreGraphics
调用是这里的瓶颈(我猜这是因为通过这种方法,组合发生在 CPU 上?)
解决方法2
另一种方法可能是分两步完成此操作:首先,保存源视频,并将滤镜应用于文件,如下所示B,然后使用该视频文件将视频嵌入到图层合成中,如下所示A。然而,由于它使用两次传递,我想这并没有达到应有的效率。
Summary
将该视频导出到文件的好方法是什么(最好一次性导出)?我该如何使用CIFilter
s and AVVideoCompositionCoreAnimationTool
同时地?是否有一种本地方式来设置“管道”AVFoundation
它结合了这些工具?