[FFmpeg-user] How to enforce VBR minimum bitrate

Zak ffmpeg-user-email at m.allo.ws
Tue Jun 5 00:00:20 EEST 2018

On 2018-06-04 at 1:40 PM EDT, Carl Eugen Hoyos wrote:
> 2018-06-04 16:59 GMT+02:00, DopeLabs <dopelabs at dubstep.fm>:
>> you can combine steps 1 and 2 into a single command:
>> $ ffmpeg- i input -options -f wav - | lame -V 5 -F -b 128 - output.mp3
> wav is a format that cannot easily be piped.
> It may work in many cases, but generally you cannot pipe a valid file.
> Please avoid top-posting here, it is rude.
> Carl Eugen

Okay, I have new findings and opinions:

1. The original poster should use CBR (constant bitrate), almost 
definitely. My reasoning:

1.1. At -V 5 with normal music and no minimum frame size, the output is 
125 to 145 kbps on the small corpus of music that I tested.

1.2. With a minimum frame size of 128 kbps, the same corpus of music is 
132 to 150 kbps, and it sounds the same to me. (It doesn't sound perfect 
at all, -V 0 sounds significantly better.)

1.3. With CBR at 128 kbps, it sounds the same, it is slightly smaller, 
and it will play on very rudimentary hardware decoders. Fast scrubbing 
will also be possible because it is CBR, so quickly seeking to a 
specific time index will not require complex math using the VbrTag (also 
known as the toc, table of contents, the VBRI header).

1.4. MP3 frames do not come in arbitrary sizes, and setting a target 
bitrate of 135 kbps but only allowing the smallest frames to be 128 kbps 
means that almost all of the frames will be 128 kbps. Rather few frames 
are higher than 128 kbps (as shown by the final deduced bitrates ranging 
from 132 to 150 kbps). These files are almost entirely 128 kbps frames. 
The next frame size is 160 kbps, so there is a big jump from 128 to 160, 
and 160 is not being used often with -V 5. After 160, the next frame 
size is 192 kbps, and it shows up less than 1% of the time in all of the 
songs that I spot-checked (at -V 5). For the curious: The MP3 standard 
can only accommodate 14 sizes of frame, because the frame size is stored 
in 4 bits with 0b0000 and 0b1111 both being invalid.

1.5. The benefit of -V 5 is that the files are smaller because of the 
small frames. If you don't let small frames happen, then you are making 
far less compatible files for no reason.

1.6. Using -V 0 with a minimum frame size of 128 kbps is possibly 
sensible. -V 0 gives output around 270 kbps, and adding a minimum frame 
size of 128 kbps barely changes the file size (they get a little bit 
bigger). The -V 0 music sounds perfect to me, I cannot tell the 
difference between -V 0 and lossless, not by any stretch of the 
imagination. It sounds better than the V5 with or without the frame size 

1.7. The 128 kbps CBR code in LAME has actually been heavily optimized 
for sound quality. The VBR code has also been optimized, but not if you 
do something silly like forbid small frames. If you do something closer 
to what the LAME developers were expecting, you will get better-sounding 
results in a smaller file. Though to be fair, I could hear the same 
compression artifacts in both configurations.


The following is not good advice, I just wanted to do some experiments 
and confirm that it is bad advice.

2. Surprisingly, the following does work with 44.1 kHz 16-bit stereo:

ffmpeg -i input.flac -f wav - | lame -V 5 -F -b 128 - output.mp3

However, using more exotic inputs resulted in MP3s that sounded really 
bad, MP3s that consisted of white noise, and one MP3 file that crashed 
my entire computer when I tried to open it with VLC, which was impressive.

The WAV file contains information about the file structure at the 
beginning. LAME will make educated guesses, but if the input is exotic 
then it will guess wrong.

If LAME prints "Assuming raw pcm input file" then you are probably going 
to get garbage out. This warning is the very first thing LAME prints 
(after FFmpeg finishes printing).

Your best bet is to make a WAV file, use that, then delete it. In 
theory, you could have FFmpeg produce an actual raw PCM stream with 
known characteristics, but you would need to tell LAME what to expect.


3. I figured out how to get ABR working via FFmpeg:

ffmpeg -i input -codec:a libmp3lame -abr true -b:a 135k output.mp3

The key is "-abr true". I figured this out from this command:

ffmpeg -h encoder=libmp3lame

This was strikingly hard to figure out.


4. Passing in the -F option via FFmpeg will be impossible. I am 
convinced of this after reading this file:


Here it is in the Git repo:


Only a few of the libmp3lame options can be customized in FFmpeg, and 
you cannot pass in arbitrary options.

Side note: I'm going to try changing this line and recompiling FFmpeg, 
because I like the LAME Info Tag (Xing header):

At line 132 in libmp3lame.c:

    /* do not get a Xing VBR header frame from LAME */
-- lame_set_bWriteVbrTag(s->gfp,0);
++ lame_set_bWriteVbrTag(s->gfp,1);

Will I crash my computer for the second time in one day? Let's see.


More information about the ffmpeg-user mailing list