[FFmpeg-user] What is the (technical) difference between -r and the fps filter?

thljcl jiachielee at live.com
Tue Jul 23 14:00:43 CEST 2013

Thanks for telling me the existence of fps video filter. As well as I know,
based on my own experiments, fps video filter can handle frame rate
conversion accurately; -r, on the other hand, is not exactly meant for frame
rate conversion. In other words, depending on usage scenarios, video filter
may not be replacement for -r.
ffmpeg allows us to encode a series of image sequence into a single video
file. For example,
ffmpeg -i "frames\f_%%1d.png" -vcodec "libx264" -crf "0" "output.mkv"
By definition, a video is a series of still images which, when shown on
screen, creates the illusion of moving images. Frame rate is frequency
(rate) at which an imaging device produces unique consecutive images called
frames. Such frame rate may be constant or variable. If a series of image
sequence is to be encoded into a single video with lossless encoding, we can
encode it back to image sequence for editing purposes. We can edit the video
frame by frame; or we can add or remove some frames. Lossy encoding, in
contrast, is irreversible process such that further encoding will further
compromise image quality. Videos meant for commercial release or
distribution are not meant for editing, which are different from “master
copy”. As you may notice, I did not specify frame rate, so by default ffmpeg
chooses -r "25" for me. Film industry generally chooses 24 FPS in film
capturing and production. In that case,
ffmpeg -r "24" -i "frames\f_%%1d.png" -vcodec "libx264" -crf "0"
25 FPS is chosen by default because of the preset of ffmpeg as well as there
is no inherent frame rate for still images. Note that -r is placed before -i
instead of after -i, it is to tell that the still images or source is of the
frame rate of 24 FPS. -crf "0" is to tell x264 to encode the video in
“lossless mode”. Similarly, I can get the still images back:
mkdir "frames"
ffmpeg -i "output.mkv" "frames\f_%%1d.png"
In this case, I omitted -r both before and after -i. ffmpeg can detect the
frame rate from the source “output.mkv”; omission of -i in the output option
means that the frame rate of the source is to be used. The conversion
between still images and a video (lossless encoding) is reversible. What if
-r is placed after -i?
ffmpeg -i "frames\f_%%1d.png" -r "24" -vcodec "libx264" -crf "0"
Of course, omission of -r before -i would mean that ffmpeg would assume that
the source (still images) is of 25 FPS, but the output video is of 24 FPS.
The achievement of 24 FPS, which is lower than the source, is only possible
if some frames are dropped. This is indeed frame rate conversion, from 25
FPS to 24 FPS. However, the algorithm of -r is different from video filter
"fps", which means ffmpeg will drop/duplicate different frames depending
whether -r or video filter "fps" or both are in use. In constant frame rate,
only certain length is allowed for a given frame rate; which means whenever
the frame rate conversion occurs, inevitably there will be changes in video
length as well; the change of video length is due to frame quantization or
rounding in calculation. Video filter "fps", unlike -r, cannot be used to
specify the frame rate for a series of still images sequence; it is meant
for frame rate conversion from a video with a given frame rate to another.
-r has different purposes from video filter "fps". When it comes to frame
rate conversion, how does -r handle compared with video filter "fps"? 
ffmpeg -i "input.mkv" -r "29.97" -vcodec "libx264" -crf "0" "output.mkv"
When I check the media info of output video, it reports the frame rate of
29.97 FPS and it is variable frame rate while the source I use is of the
frame rate of 24 FPS. What does it actually mean?
mkdir "frames"
ffmpeg -r "1" -i "output.mkv" "frames\f_%%1d.png"
Guess what I saw? The number of frames do not change after the encoding.
Variable frame rate means that the frame rate could by any and can be
changed while the video is being played. In this case, for the playback
speed to remain unchanged, no change in the number of frames would mean that
the actual frame rate does not change at all, assuming that the media player
can actually handle such media file correctly. If not, the video file may be
played at a different “normal” speed than original intended. What really
changes is merely the media info being reported.
Why do I put -r "1" before -i? I want to see how many frames that the video
file actually has. If -r "1" is omitted, -r "29.97" would be assumed since
that is what being reported by media player. However, instead of extracting
every frame from the video, ffmpeg will add/drop frames to achieve 29.97 FPS
since the actual frame rate is reported as “variable”; I will not be able to
see how many frames the output video has. By telling ffmpeg that the output
video has a constant frame rate, no matter what it is, thus ignoring the
original frame rate as contained in the source, ffmpeg would extracting all
frames from the output video.
Due to clever design of H.264 codec, its video can have changing frame rate,
which allows higher compression level. ffmpeg actually adds frames if I
choose to create a series of still images first.
mkdir "output"
ffmpeg -i "input.mkv" -r "29.97" "output\f_%%1d.png"
ffmpeg -r "29.97" -i "output\f_%%1d.png" -vcodec "libx264" -crf "0"
rmdir /s /q "output"
The argument is simple. “Variable frame rate” simply does not exist for a
series of still images sequence. Thus, the only way to achieve 29.97 FPS
from the source of 24 FPS is to add frames. Video filter "fps" will force
the output video to have constant frame rate.
ffmpeg -i "input.mkv" -vf "fps=29.97" -vcodec "libx264" -crf "0"
When it comes to conversion to higher frame rate, video filter "fps" and -r
"29.97" actually creates video of the same length; but a closer inspection
makes me realize that ffmpeg duplicates different frames between video
filter "fps" and -r "29.97". When it comes to conversion to lower frame
rate, -r will increase the video length of 1/24 – 1/12 second, depending on
which codec is being used; while video filter "fps" largely preserves the
video length, up to expected quantization, of course.
The bottom line is that -r and video filter "fps" are technically different
from each other. Video filter "fps" is meant for frame rate conversion. -r
has different uses as well.

View this message in context: http://ffmpeg-users.933282.n4.nabble.com/What-is-the-technical-difference-between-r-and-the-fps-filter-tp4658581p4660138.html
Sent from the FFmpeg-users mailing list archive at Nabble.com.

More information about the ffmpeg-user mailing list