How to enforce VBR minimum bitrate

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to enforce VBR minimum bitrate

Sook Sin
Hi experts!

 

I am currently using ffmpeg as a solution to audio file conversion and
normalization.

 

I understand that my setting (-q:a 5) below should produce output with
bitrate range in between 120-150kbps, or sometimes even lower than that if
the input already in being a lower bitrate than requested.

 

By using VBR Encoding, is there an option that is able to constrain the
bitrate minimum at 128kbps?

 

ffmpeg -i "input" -af "silenceremove=0:0:0:-1:1:-80dB,
dynaudnorm=p=1:m=3:r=1" -vn -acodec libmp3lame -q:a 5 -ar 44100 "output.mp3"

 

Please kindly advise. Thanks!

 

Regards,

Sook Sin

 



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Zak
Reply | Threaded
Open this post in threaded view
|

Re: How to enforce VBR minimum bitrate

Zak
On 2018-06-04 at 3:03 AM EDT, [hidden email] wrote:

> Hi experts!
>
> I am currently using ffmpeg as a solution to audio file conversion and
> normalization.
>
> I understand that my setting (-q:a 5) below should produce output with
> bitrate range in between 120-150kbps, or sometimes even lower than that if
> the input already in being a lower bitrate than requested.
>
> By using VBR Encoding, is there an option that is able to constrain the
> bitrate minimum at 128kbps?
>
> ffmpeg -i "input" -af "silenceremove=0:0:0:-1:1:-80dB,
> dynaudnorm=p=1:m=3:r=1" -vn -acodec libmp3lame -q:a 5 -ar 44100 "output.mp3"
>
> Please kindly advise. Thanks!
>
> Regards,
>
> Sook Sin

Hello Sook Sin,

Disclamer: It might depend on your version of FFmpeg and libmp3lame, but I doubt it (assuming versions from 2012 or more recent). The libmp3lame behavior in this respect has been the same since at least 2012, and the FFmpeg behavior has probably been the same in this respect. (If it changed, it would indicate that FFmpeg removed a feature, and I don't think they did this. There is no reason to remove features.)

Short version: You can set a minimum bitrate in VBR mode with the LAME command line interface, but I think you CANNOT do this with the version of libmp3lame that is linked by FFmpeg during compilation of FFmpeg. I just tried, the minimum bitrate was not respected, every frame of silence was encoded at 32 kbps. A work-around is to use your FFmpeg command to make an uncompressed PCM file, such as a WAV file, and then convert the WAV to MP3 using the LAME command line interface (going forward, I will call it the LAME CLI). I give an example of how to do this below.

Question for the whole list:
Is it possible to pass arbitrary options from FFmpeg to libmp3lame as if they came from argc and argv? I am guessing no. libx264 seems to take arbitrary options via FFmpeg, but I am guessing libmp3lame does not. Sook Sin wants to pass in the option "-F" as if it came from the command line. (Or rather, if this were possible it would solve the problem at hand.)

Why:

In order to tell the LAME CLI to do VBR but also enforce a minimum bitrate for all frames of MP3 audio data, you need to give the LAME CLI a command like this (this is valid Bash syntax for GNU/Linux, MacOS, or Cygwin on Windows):

bash$ lame -V 5 -F -b 128 input.wav output.mp3

The option "-V 5" for the LAME CLI is the same as "-q:a 5" in FFmpeg, and in fact FFmpeg passes the number 5 directly to libmp3lame to be used by libmp3lame as it sees fit. The FFmpeg option "-q:a 5" should not be confused with the LAME CLI option "-q 5", which is a different encoder parameter.

The option -V (LAME) and its sister -q:a (FFmpeg) control the file size and target bitrate.

The option -q (LAME) and its sister -compression_level:a (FFmpeg) control how fast or slow the encoder is. "-q 0" (LAME CLI) is equal to "-compression_level:a 0" (FFmpeg), and it will be the slowest during compression, equally fast during playback, and give the best-sounding results. "-q 3" is the default in VBR mode for LAME (both CLI and FFmpeg-linked). In CBR mode, -q 3 is often the same as -q 0, but it depends on the sample rate of the input and the output bitrate of the MP3. For CD audio (44.1 kHz stereo) at CBR at 320 kbps, -q 3 is actually a tiny bit faster than -q 0. At lower bitrates they are often identical algorithms, speed, and output. -q 0 is the highest quality and slowest compression, -q 9 is the lowest quality and fastest, the output file sizes are generally about the same with no systematic trend larger or smaller.

The option -F (LAME) is the key option that you want. It means FORCE the encoder to use frames of a certain minimum size, even if it can achieve the target quality (implied by -V 5) using a small frame. You say -F and then you say -b N with the frame size in kbps. So for a minimum frame size of 128 kbps, it is the command above with "-F -b 128". This does indeed work in LAME v3.100, I just tested it. Even silence will be 128 kbps. In fact, if I set -V 9 (which should be about 65 kbps and should sound terrible), the whole file is created using 128 kbps frames and the quality is much better, because 128 kbps sounds markedly better than ~65 kbps VBR. (These examples and numbers are all for CD audio, in which silence would normally be 32 kbps in -V N for any value of N. Frames smaller than 32 kbps are not valid at CD sample rates in the MP3 standard - VLC will play such files, iTunes will not. LAME CLI will make such a file if you compile in debug mode. FFmpeg will not make such files, as far as I know. This seems like good behavior on all accounts.)

Sadly, you need the -F option, and FFmpeg doesn't seem to know how to accept that option and pass it to libmp3lame. Using a realistic music file with some silence, I was not able to get FFmpeg to respect the minimum frame size. In VBR mode, FFmpeg wants to make 32 kbps frames if it feels like they are high-enough quality.

Working solution, use two steps:

Step 1:

bash$ ffmpeg -i foo -args -args -more_args intermediate.wav

Step 2:

bash$ lame -V 5 -F -b 128 intermediate.wav output.mp3

bash$ rm intermediate.wav

The commands above will work assuming the FFmpeg command in step 1 works and assuming you have a semi-recent version of LAME. I recommend the latest version of LAME, they don't come out very often and they get progressively better.

Alternative solution, not as good:

Use an ABR mode. This will give worse audio quality, and you may still get frames smaller than 128 kbps, especially if you set the ABR target as 135 kbps, which is the midpoint of 120-150 kbps. Let's try it:

Oh, I actually can't get this to work. The solution likely looks like this, kind of:

bash$ ffmpeg -i song.wav -codec:a libmp3lame -abr:a -b:a 135k output.mp3

The above does not work for me, I tried a few variations and it is not valid syntax, but I don't recommend ABR for MP3 in general, and it also probably won't solve this problem because if the target is 135 kbps, then 32 kbps frames are very likely to show up in the output. There just won't be as many as -V 5. ABR at 135 kbps will likely have a huge number of 112 kbps frames, which is already below your desired minimum.

Note that the LAME docs imply that -F only applies to frames of silence. This is only implied, the term "silence" is not defined rigorously, and in reality you need the -F option if you are trying to make the MP3 play on a device or in software that can't handle small frames. Devices or software that need a minimum frame size really NEED a minimum frame size, even for silence.

ABR might be a viable option if your goal is to make sure the total audio size is predictable, or above some minimum. ABR will not give good results in terms of audio quality, and it will use 32 kbps frames sometimes (possibly breaking your player), but it will ensure a minimum size for the finished audio file. If you use ABR with a target of 150 kbps, then I think it is unlikely the finished product will average less than 128 kbps. ABR doesn't promise to come within any margin of the target, but it comes very close usually.

Good luck,

Zak F.


_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: How to enforce VBR minimum bitrate

DopeLabs
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


> On Jun 4, 2018, at 7:52 42AM, Zak <[hidden email]> wrote:
>
> On 2018-06-04 at 3:03 AM EDT, [hidden email] wrote:
>
>> Hi experts!
>>
>> I am currently using ffmpeg as a solution to audio file conversion and
>> normalization.
>>
>> I understand that my setting (-q:a 5) below should produce output with
>> bitrate range in between 120-150kbps, or sometimes even lower than that if
>> the input already in being a lower bitrate than requested.
>>
>> By using VBR Encoding, is there an option that is able to constrain the
>> bitrate minimum at 128kbps?
>>
>> ffmpeg -i "input" -af "silenceremove=0:0:0:-1:1:-80dB,
>> dynaudnorm=p=1:m=3:r=1" -vn -acodec libmp3lame -q:a 5 -ar 44100 "output.mp3"
>>
>> Please kindly advise. Thanks!
>>
>> Regards,
>>
>> Sook Sin
>
> Hello Sook Sin,
>
> Disclamer: It might depend on your version of FFmpeg and libmp3lame, but I doubt it (assuming versions from 2012 or more recent). The libmp3lame behavior in this respect has been the same since at least 2012, and the FFmpeg behavior has probably been the same in this respect. (If it changed, it would indicate that FFmpeg removed a feature, and I don't think they did this. There is no reason to remove features.)
>
> Short version: You can set a minimum bitrate in VBR mode with the LAME command line interface, but I think you CANNOT do this with the version of libmp3lame that is linked by FFmpeg during compilation of FFmpeg. I just tried, the minimum bitrate was not respected, every frame of silence was encoded at 32 kbps. A work-around is to use your FFmpeg command to make an uncompressed PCM file, such as a WAV file, and then convert the WAV to MP3 using the LAME command line interface (going forward, I will call it the LAME CLI). I give an example of how to do this below.
>
> Question for the whole list:
> Is it possible to pass arbitrary options from FFmpeg to libmp3lame as if they came from argc and argv? I am guessing no. libx264 seems to take arbitrary options via FFmpeg, but I am guessing libmp3lame does not. Sook Sin wants to pass in the option "-F" as if it came from the command line. (Or rather, if this were possible it would solve the problem at hand.)
>
> Why:
>
> In order to tell the LAME CLI to do VBR but also enforce a minimum bitrate for all frames of MP3 audio data, you need to give the LAME CLI a command like this (this is valid Bash syntax for GNU/Linux, MacOS, or Cygwin on Windows):
>
> bash$ lame -V 5 -F -b 128 input.wav output.mp3
>
> The option "-V 5" for the LAME CLI is the same as "-q:a 5" in FFmpeg, and in fact FFmpeg passes the number 5 directly to libmp3lame to be used by libmp3lame as it sees fit. The FFmpeg option "-q:a 5" should not be confused with the LAME CLI option "-q 5", which is a different encoder parameter.
>
> The option -V (LAME) and its sister -q:a (FFmpeg) control the file size and target bitrate.
>
> The option -q (LAME) and its sister -compression_level:a (FFmpeg) control how fast or slow the encoder is. "-q 0" (LAME CLI) is equal to "-compression_level:a 0" (FFmpeg), and it will be the slowest during compression, equally fast during playback, and give the best-sounding results. "-q 3" is the default in VBR mode for LAME (both CLI and FFmpeg-linked). In CBR mode, -q 3 is often the same as -q 0, but it depends on the sample rate of the input and the output bitrate of the MP3. For CD audio (44.1 kHz stereo) at CBR at 320 kbps, -q 3 is actually a tiny bit faster than -q 0. At lower bitrates they are often identical algorithms, speed, and output. -q 0 is the highest quality and slowest compression, -q 9 is the lowest quality and fastest, the output file sizes are generally about the same with no systematic trend larger or smaller.
>
> The option -F (LAME) is the key option that you want. It means FORCE the encoder to use frames of a certain minimum size, even if it can achieve the target quality (implied by -V 5) using a small frame. You say -F and then you say -b N with the frame size in kbps. So for a minimum frame size of 128 kbps, it is the command above with "-F -b 128". This does indeed work in LAME v3.100, I just tested it. Even silence will be 128 kbps. In fact, if I set -V 9 (which should be about 65 kbps and should sound terrible), the whole file is created using 128 kbps frames and the quality is much better, because 128 kbps sounds markedly better than ~65 kbps VBR. (These examples and numbers are all for CD audio, in which silence would normally be 32 kbps in -V N for any value of N. Frames smaller than 32 kbps are not valid at CD sample rates in the MP3 standard - VLC will play such files, iTunes will not. LAME CLI will make such a file if you compile in debug mode. FFmpeg will not make such files, as far as I know. This seems like good behavior on all accounts.)
>
> Sadly, you need the -F option, and FFmpeg doesn't seem to know how to accept that option and pass it to libmp3lame. Using a realistic music file with some silence, I was not able to get FFmpeg to respect the minimum frame size. In VBR mode, FFmpeg wants to make 32 kbps frames if it feels like they are high-enough quality.
>
> Working solution, use two steps:
>
> Step 1:
>
> bash$ ffmpeg -i foo -args -args -more_args intermediate.wav
>
> Step 2:
>
> bash$ lame -V 5 -F -b 128 intermediate.wav output.mp3
>
> bash$ rm intermediate.wav
>
> The commands above will work assuming the FFmpeg command in step 1 works and assuming you have a semi-recent version of LAME. I recommend the latest version of LAME, they don't come out very often and they get progressively better.
>
> Alternative solution, not as good:
>
> Use an ABR mode. This will give worse audio quality, and you may still get frames smaller than 128 kbps, especially if you set the ABR target as 135 kbps, which is the midpoint of 120-150 kbps. Let's try it:
>
> Oh, I actually can't get this to work. The solution likely looks like this, kind of:
>
> bash$ ffmpeg -i song.wav -codec:a libmp3lame -abr:a -b:a 135k output.mp3
>
> The above does not work for me, I tried a few variations and it is not valid syntax, but I don't recommend ABR for MP3 in general, and it also probably won't solve this problem because if the target is 135 kbps, then 32 kbps frames are very likely to show up in the output. There just won't be as many as -V 5. ABR at 135 kbps will likely have a huge number of 112 kbps frames, which is already below your desired minimum.
>
> Note that the LAME docs imply that -F only applies to frames of silence. This is only implied, the term "silence" is not defined rigorously, and in reality you need the -F option if you are trying to make the MP3 play on a device or in software that can't handle small frames. Devices or software that need a minimum frame size really NEED a minimum frame size, even for silence.
>
> ABR might be a viable option if your goal is to make sure the total audio size is predictable, or above some minimum. ABR will not give good results in terms of audio quality, and it will use 32 kbps frames sometimes (possibly breaking your player), but it will ensure a minimum size for the finished audio file. If you use ABR with a target of 150 kbps, then I think it is unlikely the finished product will average less than 128 kbps. ABR doesn't promise to come within any margin of the target, but it comes very close usually.
>
> Good luck,
>
> Zak F.
>
>
> _______________________________________________
> ffmpeg-user mailing list
> [hidden email]
> http://ffmpeg.org/mailman/listinfo/ffmpeg-user
>
> To unsubscribe, visit link above, or email
> [hidden email] with subject "unsubscribe".

_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: How to enforce VBR minimum bitrate

Carl Eugen Hoyos-2
2018-06-04 16:59 GMT+02:00, DopeLabs <[hidden email]>:
> 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
_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Zak
Reply | Threaded
Open this post in threaded view
|

Re: How to enforce VBR minimum bitrate

Zak
On 2018-06-04 at 1:40 PM EDT, Carl Eugen Hoyos wrote:
 >
> 2018-06-04 16:59 GMT+02:00, DopeLabs <[hidden email]>:
 >

>> 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
limit.

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:

ffmpeg/libavcodec/libmp3lame.c

Here it is in the Git repo:

https://git.ffmpeg.org/gitweb/ffmpeg.git/blob/refs/heads/release/4.0:/libavcodec/libmp3lame.c

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.

Zak
_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: How to enforce VBR minimum bitrate

low sin
In reply to this post by Sook Sin
Thanks all! Meanwhile let me try every way that you have suggested.
Zak, I look forward to see your result too!

Sincerely,
Sook Sin

Sent from Mail for Windows 10



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
_______________________________________________
ffmpeg-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/ffmpeg-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".