1. Introduction
FFmpeg is a powerful command-line tool for processing audio and video files. It’s fast and versatile, covering a wide range of use cases, but as with many command-line programs, it can be a little bit harder to use than its GUI counterparts.
In this article, we’ll explore various parameters of the FFmpeg render process.
2. Input and Output
First, we need to define our input (or inputs) and output. Inputs are preceded by the “-i” parameter, and the output is simply the last parameter provided to the command. Even these two simple parameters can define a useful process. Let’s say we want to convert a WAV file to mp3. We run:
$ ffmpeg -i file.wav file.mp3
Because we didn’t define any other parameters, FFmpeg will use defaults for the provided extension. We can use the ffprobe command to check the parameters of the newly created file:
$ ffprobe test.mp3
...
Input #0, mp3, from 'test.mp3':
...
encoder : Lavf58.29.100
Duration: 00:03:04.27, start: 0.025057, bitrate: 128 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc58.54
3. Codecs, Bitrate, Size, and Frame Rate
If we don’t want to rely on the defaults, we can specify some encoding options. Some can be specific to the codec that we’re using, but the most basic ones should work similarly in most situations.
3.1. Codecs
First, we must decide what codecs we want to use for audio and video. For now, we’ll assume that we want to apply the same codec to all video streams and the same codec to all audio streams if we have more than one stream in the input file.
Let’s encode our video with the “h264” codec and our audio with the “aac” codec. We’ll use the “-c:v” parameter to set the codec for all video streams and the “-c:a” parameter to set the codec for all audio streams:
$ ffmpeg -i input.mp4 -c:v h264 -c:a aac output.mp4
3.2. Bitrate
We can specify bitrate both for video and audio. For video, we’ll use the “-b:v” parameter, and for audio, the “-b:a” parameter:
$ ffmpeg -i input.mp4 -b:v 2M -b:a 128k output.mp4
Mind that different codecs require different bitrate values to maintain transparency. For example, the mp3 codec needs a higher bitrate to achieve the same quality as the aac codec. Also, the bit rate value will mean slightly different things for constant bit rate encoding and variable bit rate encoding.
3.3. Frame Rate
By default, FFmpeg will encode output with the same frame rate as its input, but if needed, we can customize it. We have a couple of ways of doing this. The first is to use the “-r” parameter. It can be used both with a constant frame rate and a variable frame rate. For variable frame-rate streams, the parameter will work as a ceiling:
$ ffmpeg -i input.mp4 -r 30 output.mp4
It can also be used for rendering images from video. If we’d like to generate a still image for every frame, we could do it easily:
$ ffmpeg -i input.mp4 -r 1 -f image2 snap-%03d.jpeg
We need to force the output to “image2” format using the “-f” parameter. The second way to set the frame rate is to use the “fps” filter:
$ ffmpeg -i input.mp4 -filter:v fps=30 output.mp4
In some situations, we don’t know the frame rate of the input, or the notion of frame rate doesn’t make sense, for example, when we try to build a video from still images. In that case, before providing the input, we need to specify the frame rate as the input argument using the “-framerate” parameter:
$ ffmpeg -f image2 -framerate 30 -i snap-%03d.jpeg output.mp4
3.4. Size and Scaling
If we want to scale the video to a specific size, we can use the scale filter:
$ ffmpeg -i input.mp4 -vf scale=320:240 output.mp4
We may also want to specify only one dimension and keep the aspect ratio:
$ ffmpeg -i input.mp4 -vf scale=320:-1 output.mp4
In some situations, we don’t want to scale to a specific size but, for example, to twice the size of the original. To achieve this, we can use variables instead of numbers — “ih” for input height and “iw” for input width:
$ ffmpeg -i input.mp4 -vf scale=iw*2:ih*2 output.mp4
4. Audio Processing
4.1. Volume
During rendering, we can also use filters to manipulate audio streams. Let’s start with volume and set it to half of the input value:
$ ffmpeg -i input.mp4 -filter:a "volume=0.5" output.mp4
The parameter value in the command above is relative to the input volume. We can also use absolute values given in decibels. Let’s increase volume by 10 dB:
$ ffmpeg -i input.mp4 -filter:a "volume=10dB" output.mp4
4.2. Normalization
If we want to normalize audio to the requested maximum volume peak, we can check the current peak (measured in dBFS):
$ ffmpeg -i input.wav -filter:a volumedetect -f null /dev/null
...
[Parsed_volumedetect_0 @ 0x7fa48bf09cc0] mean_volume: -7.6 dB
[Parsed_volumedetect_0 @ 0x7fa48bf09cc0] max_volume: -2.0 dB
...
And then, we’d adjust the volume accordingly. Let’s say we want to set the peak to -1dBFS instead of -2dBFS from the example above. We need to add 1dB to the output:
$ ffmpeg -i input.wav -filter:a "volume=1dB" output.wav
If we want to normalize not only peak volume but also perceived loudness measured in LKFS, we can use the loudnorm filter:
$ ffmpeg -i input.mp4 -filter:a loudnorm output.mp4
By default, it will normalize audio to match the EBU R 128 standard.
4.3. Sample Rate
We can also change the sample rate of the audio using the “-ar” parameter:
$ ffmpeg -i input.wav -ar 48000 output.wav
Mind that changing the sample rate can result in losing some audio quality, even if the new sample is higher than the original one.
5. Stream Mappings
Up to this point, we operated on at most one video and audio stream. However, sometimes we want to merge a few files into one. To achieve that, we can use the “-map” parameter followed by a stream specifier. Specifiers consist of a number of a file and a number of a stream inside the file delimited by a colon.
Let’s say we want to take a video from the first file and the audio from the second one and merge them into the output file:
$ ffmpeg -i first.mkv -i second.mkv -c copy -map 0:0 -map 1:1 output.mkv
Instead of specifying the number of the stream inside the file, we can use an audio or video alias:
$ ffmpeg -i first.mkv -i second.mkv -c copy -map 0:v -map 1:a output.mkv
6. Conclusion
In this article, we looked into various ways of parametrizing the FFmpeg render process. We learned how to set input and output, then applied different filters to manipulate the output. Finally, we used the mapping feature to choose and pick streams and created a file with combined streams.