ffmpeg:是否可以替换可变帧率视频中的帧?

ffmpeg: Is it possible to replace frames in a variable frame-rate video?

用于视频处理的机器学习算法通常处理帧(图像)而不是视频。

在我的工作中,我使用 ffmpeg 将特定场景转储为一系列 .png 文件,以某种方式处理它们(去噪、去模糊、着色、注释、修复等),将结果输出到一个相等的.png 文件的数量,然后用新帧更新原始视频。

这适用于恒定帧率 (CFR) 视频。我转储图像 (例如,从 1:47 开始的 50 帧序列):

ffmpeg -i input.mp4 -vf "select='gte(t,107)*lt(selected_n,50)'" -vsync passthrough '107+%06d.png'

然后在编辑图像后,我替换了原件 (对于 12.5fps CFR 视频):

ffmpeg -i input.mp4 -itsoffset 107 -framerate 25/2 -i '107+%06d.png' -filter_complex "[0]overlay=eof_action=pass" -vsync passthrough -c:a copy output.mp4

但是,我处理的许多视频都是可变帧率 (VFR),这带来了一些挑战。

一个简单的解决方案是将 VFR 视频转换为 CFR,ffmpeg 无论如何都想这样做,但我想知道是否可以避免这种情况。原因是 CFR 需要要么丢帧 - 因为 ML 视频处理的目的通常是改善输出,我想避免这种情况 - 或重复帧 - 但我现在正在使用的升级算法使用数据的前一帧和下一帧 - 如果前一帧或下一帧是重复的,则...没有用于放大的数据。

使用-vsync passthrough,我曾希望我可以简单地删除-framerate选项,并按原样保留原始帧,但结果命令:

ffmpeg -i input.mp4 -itsoffset 107 -i '107+%06d.png' -filter_complex "[0]overlay=eof_action=pass" -vsync passthrough -c:a copy output.mp4

使用ffmpeg的default of 25fps,掉帧很多。有没有可靠的方法来替换 VFR 视频中的帧?

是的,可以做到,但是很复杂。覆盖视频与底层视频具有完全相同的帧时间戳对于此过程的可靠运行至关重要。生成这样的 VFR 视频片段覆盖需要从源视频中捕获帧时间戳以生成精确定时的替换片段。

该过程的简短版本是将上述命令替换为以下命令以提取图像:

ffmpeg -i input.mp4 -vf "select='gte(t,107)*lt(selected_n,50)',showinfo" -vsync passthrough '107+%06d.png' 2>&1 | 'sed s/\r/\n/g' | showinfo2concat.py --prefix="107+" >concat.txt

这需要一个可以下载的脚本here。编辑图像后,更新源视频:

ffmpeg -i input.mp4 -f concat -safe 0 -i concat.txt -filter_complex"[1]settb=1/90000,setpts=9644455+PTS*25/90000[o];[0:v:0][o]overlay=eof_action=pass" -vsync passthrough -r 90000 output.mp4

其中90000是(时基的倒数),9644455是要替换的第一帧的PTS。

有关这些命令的实际作用的更多详细信息,请参阅 source