Search code examples
audioffmpegmp3encodefilesize

FFMPEG - Get the exact calculated audio filesize after encode


Im trying to guess an audio (mp3) filesize before encode with ffmpeg, afterward, need to have the exact calculated filesize.

Here is the formula im using to predict and calculate the filesize (hope im not wrong) :

( Bitrates x Duration ) / 8) x 1000 = Filesize in Bytes.

Im going to give a real example so that everyone can understand the use case.

Example :

Having an m4a file with the following data :

  • Name : Assuming xxx.m4a
  • Filesize : 8 304 014 bytes (8,3 Mo)
  • Bitrates : 256k
  • Duration : 260 seconds

Expected filesize : ( (256 x 260) / 8 ) x 1000 = 8 320 000 bytes

Then im running the following ffmpeg command :

ffmpeg -i xxx.m4a -f mp3 -y -minrate 256k -maxrate 256k -bufsize 256k -b:a 256k -fs 8320000 output.mp3

Console output :

ffmpeg version 2.7.2 Copyright (c) 2000-2015 the FFmpeg developers
  built with Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.7.2_1 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang     --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libvo-aacenc --enable-libxvid --enable-vda
  libavutil      54. 27.100 / 54. 27.100
  libavcodec     56. 41.100 / 56. 41.100
  libavformat    56. 36.100 / 56. 36.100
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 16.101 /  5. 16.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.100 /  1.  2.100
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'xxx.m4a':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf56.36.100
  Duration: 00:04:20.53, start: 0.000000, bitrate: 254 kb/s
    Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 253 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
Output #0, mp3, to 'output.mp3':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    TSSE            : Lavf56.36.100
    Stream #0:0(und): Audio: mp3 (libmp3lame), 44100 Hz, stereo, fltp, 256 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      encoder         : Lavc56.41.100 libmp3lame
Stream mapping:
  Stream #0:0 -> #0:0 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
size=    8127kB time=00:04:20.02 bitrate= 256.1kbits/s    
video:0kB audio:8127kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.011765%    

Problem and Questions :

  • Can you tell me why im I getting an output with 8 322 546 bytes and not 8 320 000 as expected ?
  • Is there something wrong in my formula or the ffmpeg command ?
  • What solution can you suggest to get the exact predicted filesize ?

Thank you in advance.


Solution

  • Besides the muxing overhead inherent in the container, MP3 audio is stored in frames. And each frame has fixed number of 1152 samples. The encoder will output full frames so for an output sampling rate of 44100, the closest to 260 seconds is

    ceiling of (260 x 44100/1152) = 9954 frames = ~260.02285 seconds.

    This throws your calculation, by itself, off balance, even if the encoding assumptions were right.

    Even then, the bit reservoir may come into play.

    Edit:

    You can drop the bitrate and add silent padding, but this too isn't precise as muxing overhead comes into play

    ffmpeg -i xxx.m4a -f lavfi -t 5 -i anullsrc -lavfi "[0:a][1:a]concat=n=2:v=0:a=1" -f mp3 -y -minrate 224k -maxrate 224k -bufsize 224k -b:a 224k -fs N output.mp3
    

    Here, the fs should be calculated as per MP3 + 5 seconds duration.