ffmpeg - 从视频中提取确切的帧数

时间:2017-03-28 20:33:50

标签: select video ffmpeg frames

我想从视频中创建最多30张图片(并将其拼贴为精灵表)。

我尝试将'select'与'mod'一起使用但是如果帧的总数不能很好地适合所需数量的图像(30)那么我有时候会得到更多的图像,有时甚至更少。

例如,如果我的视频是72帧长,我的'mod'将是72/30,即2.4。

我是从python脚本运行的,所以我正在为过滤器执行以下操作:

select='not(mod(n\," + str(mod) + "))'

我认为mod必须是一个整数(?)所以我可以向下舍入并使用2给我36个图像或向上舍入给我24个图像

什么是获得30分的最佳方法? - 显然间隔不一样,但没关系。

也许我可以使用for循环生成最接近所需间隔的帧列表,然后将其作为选择过滤器传递?

e.g。得到帧我会做这样的事情:

nframes = 72 # number of frames in video
outImages = 30 # number of images I want
mod = float(nframes) / outImages # 2.4

frames = []

idx = 1

while i < nframes:
    print str(idx) + ": " + str(math.floor(i+0.5)) 
    frames.append(int(math.floor(i+0.5)))
    idx += 1
    i += mod

然后我能将那个(帧列表)传递给ffmpeg命令吗?或者我可以告诉ffmpeg做类似的事情吗?

1 个答案:

答案 0 :(得分:1)

如果你有一个框架列表,你可以运行

ffmpeg -i in.mp4 -vf select='eq(n,5)+eq(n,11)+eq(n,15)..' -vsync 0 frames%d.jpg

如果你可以将频率分解为有理数(并做一些数学运算),有一种方法可以直接使用选择滤波器。

我们取f = 2.4,它与12/5相同。这意味着你需要每12帧中有5帧。你可以将其分解为12中的1 + 1中的1个。因为,在这种情况下,后者将与前一个选择重合,我们可以提前选择一帧,即第11帧每12帧。

ffmpeg -i in.mp4 -vf select='not(mod(n,3))+not(mod(n+1,12))' -vsync 0 frames%d.jpg

这个想法是将你的频率表示为倒数之和1/f = 1/m + 1/n + 1/p。如果其中一个分母是其他分母的倍数,则可以使用偏移设备n+cn-c

这样做的一个更好的方法是

ffmpeg -i in.mp4 -vf select='not(mod(n,12))+not(mod(n+3,12))+not(mod(n+5,12))+not(mod(n+7,12))+not(mod(n+11,12))` -vsync 0 frames%d.jpg

其中select子句的总数等于每组X帧所需的帧数。

在任何情况下,您都可以通过添加-vframes 30

粗略地限制总帧数