I'm trying to encode sample video clip or audio track with ffmpeg and libfdk_aac with variable bitrate mode-vbr 3:

ffmpeg -i sample.mp4 -crf 21 -vcodec h264 -acodec libfdk_aac -vbr 3 -ac 2 out.mp4
ffmpeg -i sample.mp3 -acodec libfdk_aac -vbr 3 -ac 2 out.m4a

mediainfo always shows

Bit rate mode                            : Constant

It sounds like a bug, isn't it?

Also, Mp4info looks like

  major brand:      M4A 
  minor version:    200
  compatible brand: M4A 
  compatible brand: isom
  compatible brand: iso2
  fast start:       no

  duration:   229042 ms
  time scale: 1000
  fragments:  no

Found 1 Tracks
Track 1:
  flags:        3 ENABLED IN-MOVIE
  id:           1
  type:         Audio
  duration: 229042 ms
  language: und
    sample count: 9864
    timescale:    44100
    duration:     10100736 (media timescale units)
    duration:     229042 (ms)
    bitrate (computed): 88.674 Kbps
  Sample Description 0
    Coding:      mp4a (MPEG-4 Audio)
    Stream Type: Audio
    Object Type: MPEG-4 Audio
    Max Bitrate: 88674
    Avg Bitrate: 88674
    Buffer Size: 0
    Codecs String: mp4a.40.2
    MPEG-4 Audio Object Type: 2 (AAC Low Complexity)
    MPEG-4 Audio Decoder Config:
      Sampling Frequency: 44100
      Channels: 2
    Sample Rate: 44100
    Sample Size: 16
    Channels:    2

How mediainfo recognizes Bit rate mode for mp4 \ m4a ? And is there any way to correct it to Variable ? enter image description here

P.S.: Bitrate's plot show that libfdk_aac works fine, but output metadata is incorrect - it can't be CBR. Here's example for CBR below (with option -vbr 0):

enter image description here

UPDATE: After an hour of digging this issue I noticed that issue could be solved by editing ESDescriptor. Here's sample's ESDescriptor that ffmpeg produces:

[ESDescriptor] size=5+34
  es_id = 2
  stream_priority = 0
  [DecoderConfig] size=5+20
    stream_type = 5
    object_type = 64
    up_stream = 0
    buffer_size = 0
    max_bitrate = 151870
    avg_bitrate = 151870
    DecoderSpecificInfo = 11 90 
  [Descriptor:06] size=5+1

Well, if you set max_bitrate and avg_bitrate to 0 - Bit rate mode magically switches to correct value VBR as it is. So the problem could be solved by using mp4edit or by patching ffmpeg (libavformat/movenc.c::mov_write_esds_tag)

Out of curiosity, I checked youtube's videos' ESDescriptor, they also has max_bitrate and avg_bitrate set to 0.

  • 0 isn't valid value for those fields. Ideal would to calculate actual max bitrate. – Gyan Dec 26 '20 at 16:36
  • Yeah, I noticed that ffmpeg has a bug while writing esds: it writes avg_bitrate instead of max_bitrate which cause decoders think it's CBR audio stream. Somehow if set to 0 works fine everywhere and decoders detect it as VBR. I'm not sure about old ones, but yeah, to be sure every decoder read an audio correctly - better calc actual size. – Andrew Trofimov Dec 26 '20 at 17:24
  • As long as the buffer size, when specified, is accurate, what difference does it make? – Gyan Dec 26 '20 at 19:26

The issue was caused by ffmpeg/libavformat/movenc.c::mov_write_esds_tag, it can't find max_bitrate. To solve it you should specify audio bitrate -b:a 128k along with -vbr 4. Then mp4's ESDescriptor would have info about max_bitrate and mediainfo and decoders would know that audio stream has variable bitrate mode.


Currently only the 'aac_low' profile supports VBR encoding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.