ffmpeg - extract exact number of frames from video

て烟熏妆下的殇ゞ 提交于 2020-01-07 03:16:20

问题


I want to create a maximum of 30 images from a video (and tile them for a sprite sheet).

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.

For example if my video is 72 frames long, my 'mod' would be 72 / 30, which is 2.4.

I'm running this from a python script so i'm doing something like the following for the filter:

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

Whats the best way to get exactly 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?

e.g. 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? Or can I tell ffmpeg to do something similar?


回答1:


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. 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 i.e. the 11th of every 12th frame.

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. You can use the offset device n+c or n-c if one of the denominators is a multiple of the others.


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.


In any case, you can crudely limit the total number of frames by adding -vframes 30



来源:https://stackoverflow.com/questions/43079422/ffmpeg-extract-exact-number-of-frames-from-video

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!