4

I was trying to extract one every N frames from a video using ffmpeg. I tried using this command: ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" 1_every_10/img_%03d.jpg

I wanted to verify that it is working as expected. So I extracted all frames using: ffmpeg -i input.mp4 -vf "select=not(mod(n\,1))" all/img_%03d.jpg

And then I tried to see if 2nd image from the first command matches image number 20 from the second command, and it didn't match. Confirmed both visually and using diff command like

diff all/img_020.jpg 1_every_10/img_002.jpg Binary files all/img_020.jpg and 1_every_10/img_002.jpg differ

Anyone knows what could be going on? Thanks!

3

The image2 muxer defaults to constant frame rate. So if the input is, say, 30 fps, and you select every 10th frame i.e. frames with timestamp 0s, 0.33s, 0.66s.. then ffmpeg will duplicate frames to match the input rate so duplicate 9 frames for every input frame.

Way to avoid that is to set video sync method to passthrough or variable frame rate

e.g.

ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" -vsync vfr 1_every_10/img_%03d.jpg

This can potentially affect the full extraction if the input is VFR. So, use

ffmpeg -i input.mp4 -vf select -vsync vfr all/img_%03d.jpg
  • Thanks @mulvya for the education. I tried the above but still see similar problem. I see that 1_every_10/img_001.jpg and all/img_001.jpg match but then nothing else in 1_every_10 matches. – Pradheep Elango Dec 6 '17 at 13:48
  • for f in all/*.jpg; do diff $f 1_every_10/img_002.jpg; done | wc -l gives 136. for f in all/*.jpg; do diff $f 1_every_10/img_001.jpg; done | wc -l gives 135. for f in all/*.jpg; do diff $f 1_every_10/img_003.jpg; done | wc -l <br/> gives 136. – Pradheep Elango Dec 6 '17 at 13:49
  • That's not a reliable method to check. If you inspect it by eye, you will find it works. ffmpeg is primarily a video app so all encoders have some rate control method in use, either implicit or explicit. For a sequence of JPEGs, the encoder is MJPEG and default bitrate is 200 kbps, so when feeding 30 frames per second of media duration to this encoder as opposed to say 3, the quantization will be different. Add -q:v 1 to set a fixed quality and -flags +bitexact to avoid platform/runtime associated metadata idiosyncracies. – Gyan Dec 6 '17 at 14:24
  • Thank you very much @mulvya. That worked! You are right, in the previous run, also visually the images matched. The thing that set me off was that n seems to start from 0 and frame number starts from 1. So 1 matches with 1, 2 matches with 11, 3 with 21, and so on ... When I add the flags you mentioned, they match bit-by-bit with diff. Also, I found that just -q:v 1 gave me exact match. When I added the -flags +bitexact I got a file size slightly smaller than when I had just -q:v 1, 18 bytes smaller. Don't know why though. – Pradheep Elango Dec 6 '17 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.