更新 AVPlayerItem 上的 AVMutableVideoComposition 比视频帧率更快

Update AVMutableVideoComposition on AVPlayerItem faster than video framerate

我正在尝试使用 AVMutableVideoCompositionapplyingCIFiltersWithHandler 初始化程序预览应用于视频的 CIFilter

我有几个滑块可以更改过滤器中的值,这些滑块会反映在 AVPlayer 中。唯一的问题是移动滑块和应用我的更改的视频的下一帧之间存在明显的滞后。

如果我使用更高帧率的视频,applier 块会被更频繁地调用,延迟不会很明显。

我尝试过在滑块移动时重新创建并替换当前 AVPlayerItem 上的 AVMutableVideoComposition,但是在播放视频时这看起来很不稳定。 (如果视频暂停,效果很好。https://developer.apple.com/library/archive/qa/qa1966/_index.html

知道如何在不编写可以使帧无效的自定义视频播放器的情况下做到这一点吗?

这是我设法找到的一个不错的解决方案。

我注意到在帧处理块中休眠实际上似乎提高了感知性能。

AVMutableVideoComposition 必须建立一个帧缓冲区,我看到的延迟是缓冲区 运行 在具有新过滤器值的帧出现之前就已经用完了。在帧处理块中休眠可防止缓冲区填满,从而使更改立即显示出来。

我第一百万次查看了 AVMutableVideoComposition 的文档,并在 sourceTrackIDForFrameTiming.

的文档中找到了这个 gem

If an empty edit is encountered in the source asset’s track, the compositor composes frames as needed up to the frequency specified in frameDuration property. Otherwise the frame timing for the video composition is derived from the source asset's track with the corresponding ID.

我之前曾尝试在合成上设置 frameDuration,但无法使其运行速度超过视频的帧速率。如果我将 sourceTrackIDForFrameTiming 设置为 kCMPersistentTrackID_Invalid 它实际上可以让我加快帧速率。

通过将帧速率设置得非常高 (1000 fps),phone 永远不会填满缓冲区,从而使更改立即出现。

composition.sourceTrackIDForFrameTiming = kCMPersistentTrackID_Invalid

let frameRateTooHighForPhone = CMTime(value: 1, timescale: 1000)
composition.frameDuration = frameRateTooHighForPhone

它比理想的要复杂一些,但它不是一个糟糕的解决方案。

兰德尔,非常感谢你发帖。上面的 frameDuration hack 修复了我在 enabling/disabling 层时看到的延迟;所以,看来我正朝着正确的方向前进。

我现在需要弄清楚的问题是,为什么使用这个 frameDuration hack 似乎也会在视频处理中引入故障和处理挂起的副作用。有时效果很好,但通常视频会在几秒钟后停止,而音轨会继续播放。如果没有 hack,回放是稳定的,但合成滞后。有了 hack,变化似乎是瞬间发生的,视频播放有大约 10% 的机会稳定——否则会挂起。 (如果我擦洗得足够多,它似乎会以某种方式自我修复,当它修复时,宇宙感觉就像一个更好的地方。)

我对使用 AVMutableVideoComposition 和 AVVideoCompositing 协议还很陌生,关于我的使用的文档似乎很少,所以我发布了这个回复,以防有人有更多宝贵的信息与我分享.