Ffmpeg压静态帧多的影片时对动态部分丢帧过多

视频是ppt,几乎全是静态帧和少量的局部动画,还有更少的翻页动画

现在的问题是翻页动画的场景丢帧过多以至于看上去很不平滑,很卡

最开始用的参数只有-cq,发现单用cq的话会导致CFR
-c:v h264_nvenc -cq 42

后来加了-vsync vfr 强制VFR也没改善

试过-r 60或是-fv fps=60,导致文件大小翻倍,得不偿失,而且压制时间明显增加了50%不止

发现只要把源文件减掉开头第一个关键帧之前的部分就好了,太奇怪了,整个文件30分钟左右,只差这么一点?

AI回覆您:

你的问题是使用 FFmpeg 压缩以静态画面为主的影片(例如 PPT 录制的影片)时,动态部分(翻页动画)丢帧严重,导致画面不流畅。 虽然你尝试了 -vsync vfr,但效果不佳,而提高帧率 (-r 60-vf fps=60) 又会导致档案大小大幅增加。 你还发现移除影片开头一小段就能解决问题,这暗示了问题可能出在影片的编码或关键帧设定上。

以下是一些可能的解决方案和建议,从简单到复杂:

1. 尝试不同的编码器和参数:

  • x264 (CPU 编码): 虽然速度较慢,但 x264 通常能提供更好的压缩效率和画质。 你可以尝试以下参数:
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset slow -x264-params "keyint=240:min-keyint=240:scenecut=0" output.mp4
  • -crf 23: 恒定品质因子 (CRF),值越小,品质越高,档案越大。 你可以根据需要调整这个值 (18-28 都是可接受的范围)。

  • -preset slow: 设定编码预设值,slow 会花费更多时间,但压缩率更高。

  • keyint=240:min-keyint=240:scenecut=0: 这部分非常重要!它强制每 240 帧 (约 4 秒,假设帧率为 60fps) 插入一个 I 关键帧,并且关闭场景切换检测 (scenecut=0)。 对于静态画面佔比很高的影片,这可以避免在静态画面中插入太多关键帧,从而提高压缩效率,并在动态部分保留更多帧。 你可以根据你的影片长度和帧率调整 keyintmin-keyint 的值。

  • x265 (CPU 编码,HEVC 编码): HEVC 编码比 H.264 更高效,但需要更强大的处理器。

ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset slow -x265-params "keyint=240:min-keyint=240:scenecut=0" output.mp4
  • -crf 28: x265 的 CRF 值,通常比 x264 高一些才能达到相同的视觉品质。
  • NVENC (GPU 编码,如果你的显卡支援): 如果你有支援 NVENC 的 NVIDIA 显卡,它可以加速编码过程。 但 NVENC 的品质可能不如 x264 或 x265。 你可以尝试调整 -cq 值。

2. 分析影片结构:

使用 ffprobe 分析你的影片,查看关键帧的位置和分布:

ffprobe input.mp4

这可以帮助你了解影片的编码方式,以及关键帧是否过于频繁地插入。 如果关键帧分布不均匀,可能是导致动态部分丢帧的原因。

3. 使用两遍编码:

两遍编码可以让编码器更好地分配比特率,提高压缩效率。 这需要更多时间,但通常能获得更好的结果。 在 x264 和 x265 中都可以使用两遍编码。 (需要额外参数,请参考 FFmpeg 文件)

4. 处理开头关键帧问题:

你提到移除开头一小段影片就能解决问题,这很奇怪。 这可能表示影片开头的编码存在问题,例如第一个关键帧的时间戳记错误。 你可以尝试使用 ffmpeg-ss 参数跳过开头一小段,然后再进行编码:

ffmpeg -ss 1 -i input.mp4 -c:v libx264 -crf 23 -preset slow output.mp4  // 跳过前一秒

(调整 -ss 的值来实验)

5. 使用 -g 参数控制 GOP 大小:

-g 参数设定 GOP (Group of Pictures) 的大小,也就是两个 I 关键帧之间的帧数。 你可以尝试设定一个较大的 GOP 大小,例如 -g 240,这与 keyint 参数的效果类似。

总结:

我建议你从 方案 1 开始尝试,先用 x264 或 x265,并使用 keyintmin-keyint 参数来控制关键帧的插入。 如果仍然无法解决问题,再尝试其他方案。 记得在尝试不同的参数时,每次只改变一个参数,以便更好地找出问题所在。 仔细观察编码过程中的日志讯息,这可能提供额外的线索。 最后,提供你的影片档案的一些资讯 (例如长度、帧率、大小) 也会帮助我更好地理解你的问题。

尝试不同的编码器

ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4

使用两遍编码

ffmpeg -y -i input.mp4 -c:v libx264 -b:v 1000k -pass 1 -an -f mp4 /dev/null && \
ffmpeg -i input.mp4 -c:v libx264 -b:v 1000k -pass 2 output.mp4
ffmpeg -ss 00:00:02 -i input.mp4 -c:v h264_nvenc -cq 42 -preset medium -vsync passthrough output.mp4

ffmpeg -i input.ppt -c:v h264_nvenc -cq 42 -vsync vfr -r 30 -c:a aac -b:a 128k -f mp4 output.mp4
2 个赞

用ffmpeg剪掉开头0.001秒然后拷贝输出就解决了
-c copy -ss 00:00:00.001

猜测是因为视频在制作时不符合视频格式标准,或者与ffmpeg不兼容,

在ffmpeg剪切后重新写了一遍就ok了

一定要剪掉任意一小段,经测试单纯的-c copy并不能解决