webm files created with ffmpeg are too long

I have a folder of exactly 300 images in png format (labelled 1.png, 2.png, ..., 300.png), which I'm trying to convert to a video. I would like the video to be in the webm format, but there seems to be an issue:

using the following command:

ffmpeg -start_number 1 -i ./frames/%d.png -frames:v 300 -r 30 out.webm

does generate an out.webm file, and, according to ffprobe -select_streams v -count_frames -show_entries stream=nb_read_frames,r_frame_rate out.webm (which is presumably quite an inefficient way to get that information, but that's besides the point), it does contain 300 frames and has a framerate of exactly 30/1, however, instead of the expected exactly 10 seconds (from 300 frames being played at 30 fps), the video lasts slightly longer (about 12 seconds).
This discrepancy does seem to scale up with video length; 900 frames being converted to a video the same way and with the same frame rate yield a 36 (instead of 30) second video.

For testing, I also tried generating an mp4 file instead of a webm one, with the following command (exact same as above, but out.mp4 instead of out.webm), and that worked exactly as expected, out.mp4 was a 10-second long video.

ffmpeg -start_number 1 -i ./frames/%d.png -frames:v 100 -r 30 out.mp4

How do I fix this? is my ffmpeg command off or is this a bug within the tool?


  • The documentation ( https://www.ffmpeg.org/ffmpeg.html ) has an example:

    For creating a video from many images: ffmpeg -f image2 -framerate 12 -i foo-%03d.jpeg -s WxH foo.avi


    To force the frame rate of the input file (valid for raw formats only) to 1 fps and the frame rate of the output file to 24 fps: ffmpeg -r 1 -i input.m2v -r 24 output.avi

    and also

    As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps. This is not the same as the -framerate option used for some input formats like image2 or v4l2 (it used to be the same in older versions of FFmpeg). If in doubt use -framerate instead of the input option -r.

    For your case result:

    ffmpeg -framerate 30 -i ./frames/%d.png output.webm