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?
If you have a list of frames, you can just run
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 as12/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.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 devicen+c
orn-c
if one of the denominators is a multiple of the others.A cruder way to do this is
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