简体   繁体   English

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

[英]ffmpeg - extract exact number of frames from video

I want to create a maximum of 30 images from a video (and tile them for a sprite sheet). 我想从视频中最多创建30张图像(并将它们平铺为Sprite工作表)。

I've tried using the 'select' with 'mod' but if the total number of frames does not fit neatly into the desired number of images (30) then I sometimes end up with more images, sometimes less. 我尝试将'select'与'mod'一起使用,但是如果总帧数不能完全符合所需的图像数(30),那么有时我会得到更多的图像,有时更少。

For example if my video is 72 frames long, my 'mod' would be 72 / 30, which is 2.4. 例如,如果我的视频长72帧,那么我的“修改”将是72/30,即2.4。

I'm running this from a python script so i'm doing something like the following for the filter: 我正在从python脚本运行它,所以我正在为过滤器执行以下操作:

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

I think the mod has to be an integer (?) so I could either round down and use 2 which gives me 36 images or round up which gives me 24 images 我认为mod必须是整数(?),所以我可以向下舍入并使用2来给我36张图像,或者向上舍入可以给我24张图像。

Whats the best way to get exactly 30? 达到30岁的最佳方法是什么? - obviously the interval wouldn't be identical but thats fine. -显然间隔不是相同的,但是那很好。

Maybe I could use a for loop to generate a list of the frames closest to the desired interval and then pass that in as the select filter? 也许我可以使用for循环生成最接近所需间隔的帧列表,然后将其作为选择过滤器传递?

eg to get the frames I would do something like this: 例如,要获取框架,我将执行以下操作:

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

Then am I able to pass that (the frames list) into the ffmpeg command? 然后我可以将其(帧列表)传递给ffmpeg命令吗? Or can I tell ffmpeg to do something similar? 或者我可以告诉ffmpeg做类似的事情吗?

If you have a list of frames, you can just run 如果您有框架列表,则可以运行

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

There is a way to do this directly with select filter if you can decompose the frequency into a rational number (and do a bit of maths). 如果可以将频率分解为有理数(并做一些数学运算),则可以使用选择滤波器直接执行此操作。

Let's take f = 2.4 which is the same as 12/5 . 让我们假设f = 2.412/5相同。 So that means you need 5 frames from every 12. You can decompose that as 1 out of 3 + 1 out of 12. Since, in this case, the latter will coincide with the former selection, we can pick one frame earlier ie the 11th of every 12th frame. 因此,这意味着您需要从每12个中提取5个帧。您可以将其分解为3个中的1个+ 12个中的1个。由于在这种情况下,后者将与前一个选择一致,因此我们可以提前选择一个帧,即第11每十二帧。

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

The idea is to represent your frequency as a sum of reciprocals, 1/f = 1/m + 1/n + 1/p . 这个想法是将您的频率表示为倒数的总和, 1/f = 1/m + 1/n + 1/p You can use the offset device n+c or nc if one of the denominators is a multiple of the others. 如果分母之一是其他倍数,则可以使用偏移设备n+cnc


A cruder way to do this is 一种更简单的方法是

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

where total number of select clauses is equal to the number of frames needed from each set of X frames. 其中select子句的总数等于每组X框架所需的框架数。


In any case, you can crudely limit the total number of frames by adding -vframes 30 无论如何,您可以通过添加-vframes 30粗略地限制帧总数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM