FFmpeg 在重复拆分、select、叠加时使用过多内存

FFmpeg uses too much memory when repeating split, select, overlay

我是 运行

ffmpeg -i input.mp4 -filter_complex_script script.txt output.mp4

使用以下最小示例脚本:

split[tmp],
select='between(t,1,2)',
select='between(n,0,1)',
[tmp]overlay=enable='between(t,1,2)':eof_action=repeat,
split[tmp],
select='between(t,3,4)',
select='between(n,0,1)',
[tmp]overlay=enable='between(t,3,4)':eof_action=repeat

我想做的是在某个位置拍摄 1 帧并重复一段时间,基本上是“暂停”视频,同时覆盖以保持相同的输出长度。在示例中,我做了两次:我正在使用 split[tmp] 来处理第二个输入流,select 位置 00:01 和 select='between(t,1,2)' 的时间,select 从该位置开始的第一帧 select='between(n,0,1)',最后将该帧覆盖在输入上。这在位置 00:03 处重复第二次。我已经对此进行了测试,它完全符合我的要求。

但是,在我的真实脚本中,我对流中的不同位置重复了大约 1000 次(并且持续时间短于 1 秒),这导致 运行 内存不足。我究竟做错了什么?我可以做些什么来优化?

ffmpeg 中的过滤器基本上在帧上运行,而不是在流上运行。因此每个 select 过滤器将评估每一帧,即使您知道开始时只有几帧符合 selection。这样做 1000 次并不浪费资源。

对于您的用例,您不需要其中的大部分内容。只有一个 select 过滤器可以。

select='if(eq(n,0),1,not((between(t,1.0,1.999)+between(t,3.0,3.999)+between(t,5.0,5.999))*eq(floor(t),floor(prev_selected_t))))'

这将保留范围 [1-1.999]、[3-3.999] 和 [5-5.999] 之外的所有帧以及这些范围内的第一帧。如果您的输出格式需要恒定的帧速率,ffmpeg 将复制帧以填补时间戳间隙。