首页 > 解决方案 > 如何从两个视频和一个包含框架中的 imageView 创建一个新视频?

问题描述

我有一个父视图,其中包含两个带有 AVPlayerLayers 的视图和一个 UIImageView。我想将所有这些组合成一个新视频,该视频将捕获父视图的所有内容。

我查看了 ReplayKit,但没有捕获 AVPlayer 的内容;它不允许我访问视频;它捕获整个屏幕而不是特定的视图或框架。

我的一般方法是逐帧遍历视频,捕获帧的图像,将它们设置在我覆盖在 playerLayer 上的 imageView 中,然后使用UIGraphicsGetImageFromCurrentImageContext-- 捕获父视图的图像,然后制作视频在所有这些图像中。

我尝试了一些 AVFoundation 选项,但总体而言它们的性能并不是那么好。以下是我尝试过的一些选项,总是尝试上述模式。

  1. 只需使用videoPlayer.seek(to: frame)-- 设置视频帧,但这种方法非常慢:每 15 秒视频大约需要 42 秒才能以这种方式遍历每一帧。

  2. 与 异步获取所有视频帧AVAssetImageGenerator.generateCGImagesAsynchronously,然后遍历上述模式中的那些。这是非常占用内存的,因为我对两个视频的每一帧都有一个图像。我可以分块工作以避免内存崩溃,但总体而言,这种方法仍然相当慢,而且这种批处理复杂性并不比第一种方法好多少。

  3. 同时使用 获取每个帧AVAssetImageGenerator.copyCGImage(at: frame, actualTime: nil),但这并不比第一个选项快。

  4. 使用 anAVAssetReader并使用 -- 遍历每一帧copyNextSampleBuffer,对上述任何选项都没有真正的改进。

我可能会做一些事情来优化处理,但我认为它们不能解决上面提到的基本问题。例如,我可能会降低视频质量,或者修剪它,因为某些视频在其帧中不可见,或者降低帧速率,但如果可能的话,我宁愿避免这些。

在这一点上,我想我可能不得不使用 Metal。有什么建议么?

标签: iosswiftavfoundation

解决方案


这会很困难,因为您要做的是添加一个钩子,通过从视图中实时捕获原始图像缓冲区的流,来抓取已经渲染的 GPU 的合成结果。这在 CPU/GPU 或内存使用方面几乎没有效率。如果您能以某种方式访问​​ GPU 的本机 API 以更直接的方式获取合成的原始缓冲区,您可能会成功,但这很尴尬。

更自然的做法是——在获得所需材料(视频、图像等)后立即进行正确的视频合成,然后将处理后的结果显示给用户并根据需要进行操作(转储)数据作为文件等)。

总之,尝试谷歌“ios 视频合成”。AFAIK,AVFoundation 提供相关功能。您可能还想研究一些这样的库,减少自己编写所有低级代码的麻烦。


推荐阅读