ffmpeg:当指定 fps 值时,ffmpeg 如何决定选择哪些帧?

ffmpeg:当指定 fps 值时,ffmpeg 如何决定选择哪些帧?

我正在使用 ffmpeg 使用此命令每秒提取 3 帧

ffmpeg -i input.flv -f image2 -vf fps=fps=3 out%d.png

我想知道如果我设置了 fps 值,ffmpeg 如何在一秒钟内选择 3 帧。它是随机的还是会选择该秒内的前 3 帧?有什么帮助吗?

答案1

它通过将时间戳值从输入时间基(即 FPS 作为分数,例如 24fps 将变为 1/24)重新缩放到输出时间基来实现此目的。

首先时间基准已设定根据所请求的 FPS:

link->time_base = av_inv_q(s->framerate);

过滤时,输出帧的数量是根据缓冲区中的输入帧的数量来计算的,并在两个时间基准之间缩放该数字,因此基本上帧数 × 输入/输出。请注意,buf->pts - s->first_pts显然是帧数,而不是 PTS 时间的实际差异。

/* number of output frames */
delta = av_rescale_q_rnd(buf->pts - s->first_pts, inlink->time_base,
                         outlink->time_base, s->rounding) - s->frames_out ;

例如,输入时间基为 0.042(24 fps),输出为 0.33(3 fps),并且缓冲区中有 12 帧输入,您将获得12 × 0.042 / 0.33帧,四舍五入为最接近的整数 2 — 因此将生成两个帧。如果您有 24 个帧,那么您当然会得到三个帧。对于输入缓冲区中的 35 个帧,您将得到四个输出帧。

如果该增量小于 1,则可以丢弃缓冲区中的帧,因为在此时间范围内不需要任何帧。另一方面,如果增量大于 1,则它是需要为输入缓冲区输出的帧数。

对于新帧,PTS 值根据输入和输出时间基准进行缩放:

buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
                                outlink->time_base) + s->frames_out;

实际上,这意味着您必须查看输入视频的 PTS,计算输出每秒可以有多少帧,然后根据需要通过丢弃帧来均匀分布这些帧。如果您想做到非常精确,我建议您使用您拥有的一些测试视频来调试源代码。

恐怕我无法想出比我的答案更实际的解决方案最近在这里发布,其中我解释了如何显示帧速率发生变化的视频中每一帧的 PTS:

ffmpeg -i input.mp4 -t 10 -filter:v "fps=fps=25, showinfo" -f null - 2>&1 grep pts_time | awk '{print $6}' | cut -d: -f2

这些时间戳属于每个输出帧,以及其对应的输入 PTS 时间。

相关内容