Use DivX settings to encode to mp4 with ffmpeg

4

1

I'm used to use VirtualDub to encode a video to AVI container with DivX-codec (and MP3 for audio). Now I'm planning to use ffmpeg to encode videos to MP4 container with h264-codec. What I've figured out is that I need to use libx264 and one of those presets to make anything work. However, I'm amazed about the video bitrate ffmpeg uses for encoding.

What I currently have is this little batch file:

@ECHO OFF

SETLOCAL

SET IN=source.avs
SET FFMPEG_PATH=C:\Program Files (x86)\ffmpeg
SET PRESET=-fpre "%FFMPEG_PATH%\presets\libx264-lossless_slow.ffpreset" 
SET AUDIO=-acodec libmp3lame -ab 128000
SET VIDEO=-vcodec libx264 -vb 1978000

"%FFMPEG_PATH%\ffmpeg.exe" -i %IN% %AUDIO% %VIDEO% %PRESET% test.mp4

ENDLOCAL

With this I tell ffmpeg to use 1978k as the bitrate, but ffmpeg uses 15000k+! I tried other presets, but they don't use my specified bitrate. Here are the presets I have:

  • libx264-baseline.ffpreset
  • libx264-ipod320.ffpreset
  • libx264-ipod640.ffpreset
  • libx264-lossless_fast.ffpreset
  • libx264-lossless_max.ffpreset
  • libx264-lossless_medium.ffpreset
  • libx264-lossless_slow.ffpreset
  • libx264-lossless_slower.ffpreset
  • libx264-lossless_ultrafast.ffpreset

ffmpeg version:

FFmpeg git-N-29181-ga304071
libavutil    50. 40. 1 / 50. 40. 1
libavcodec   52.120. 0 / 52.120. 0
libavformat  52.108. 0 / 52.108. 0
libavdevice  52.  4. 0 / 52.  4. 0
libavfilter   1. 79. 0 /  1. 79. 0
libswscale    0. 13. 0 /  0. 13. 0

Note that I don't use the latest version as it has problems with spaces in filenames.

Here's what seems to be the full parameter list DivX 6.9.2 uses:

-bvnn 1978000 -vbv 218691200,100663296,100663296 -dir "C:\Users\sjngm\AppData\Roaming\DivX\DivX Codec" -w -b 1 -use_presets=1 -preset=10 -windowed_fullsearch=2 -thread_delay=1

What command line parameters would that be for ffmpeg?


EDIT:

Going with slhck's suggestion I tried a new 32-bit version. I have no idea if that is 0.9 or newer, I can't find that info.

ffmpeg version N-36890-g67f5650
libavutil      51. 34.100 / 51. 34.100
libavcodec     53. 56.105 / 53. 56.105
libavformat    53. 30.100 / 53. 30.100
libavdevice    53.  4.100 / 53.  4.100
libavfilter     2. 59.100 /  2. 59.100
libswscale      2.  1.100 /  2.  1.100
libswresample   0.  6.100 /  0.  6.100
libpostproc    51.  2.100 / 51.  2.100

I reworked my batch file to look like this (interestingly enough I can't find parameter -vprofile in the documentation):

@ECHO OFF

SETLOCAL

SET IN=VTS_01_1.avs
SET FFMPEG_PATH=C:\Program Files (x86)\ffmpeg
SET PRESET=-vprofile high -preset veryslow
SET AUDIO=-acodec libmp3lame -ab 128000
SET VIDEO=-vcodec libx264 -vb 1978000

"%FFMPEG_PATH%\ffmpeg.exe" -i %IN% %AUDIO% %PRESET% %VIDEO% test.mp4

ENDLOCAL

I see that it now uses the bitrate properly (thanks to LongNeckbeard for pointing out that the lossless-stuff ignores the bitrate!).

Just in case you wonder how I came up with the 1978000, I'm using this formula which I found valid for DivX-files (I'm guessing the bitrate won't change that much for h264):

width * height * 25 * 0.22 / 1000

I'm not sure if the 0.22 correlates with the CRF somehow.

Overall I forgot to say the I will use a two-pass scenario, which is why I don't use the CRF here. I will try to read more about this. Currently I'm just trying to get something running that shows me that I'm doing something right (ffmpeg isn't the easiest tool to understand ;)).

C:\Program Files (x86)\ffmpeg\ffmpeg.exe" -i VTS_01_1.avs -acodec libmp3lame -ab 128000 -vcodec libx264 -vb 1978000 -vprofile high -preset veryslow test.mp4

The output is now:

ffmpeg version N-36890-g67f5650 Copyright (c) 2000-2012 the FFmpeg developers
  built on Jan 16 2012 21:57:13 with gcc 4.6.2
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-runtime-cpudetect --enable-avisynth --enable-bzlib --enable-frei0r --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib
  libavutil      51. 34.100 / 51. 34.100
  libavcodec     53. 56.105 / 53. 56.105
  libavformat    53. 30.100 / 53. 30.100
  libavdevice    53.  4.100 / 53.  4.100
  libavfilter     2. 59.100 /  2. 59.100
  libswscale      2.  1.100 /  2.  1.100
  libswresample   0.  6.100 /  0.  6.100
  libpostproc    51.  2.100 / 51.  2.100
Input #0, avs, from 'VTS_01_1.avs':
  Duration: 00:58:46.12, start: 0.000000, bitrate: 0 kb/s
    Stream #0:0: Video: rawvideo (YV12 / 0x32315659), yuv420p, 576x448, 77414 kb/s, 25 tbr, 25 tbn, 25 tbc
    Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s
File 'test.mp4' already exists. Overwrite ? [y/N] y
w:576 h:448 pixfmt:yuv420p tb:1/1000000 sar:0/1 sws_param:
[libx264 @ 05A2C400] using cpu capabilities: MMX2 SSE2Fast FastShuffle SSEMisalign LZCNT
[libx264 @ 05A2C400] profile High, level 3.1
[libx264 @ 05A2C400] 264 - core 120 r2120 0c7dab9 - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 - http://www.videolan.org/x264.html - options: cabac=1 ref=16 deblock=1:0:0 analyse=0x3:0x133 me=umh subme=10 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=24 chroma_me=1 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=3 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=8 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=60 rc=abr mbtree=1 bitrate=1978 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'test.mp4':
  Metadata:
    encoder         : Lavf53.30.100
    Stream #0:0: Video: h264 (![0][0][0] / 0x0021), yuv420p, 576x448, q=-1--1, 1978 kb/s, 25 tbn, 25 tbc
    Stream #0:1: Audio: mp3 (i[0][0][0] / 0x0069), 48000 Hz, 2 channels, s16, 128 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo -> libx264)
  Stream #0:1 -> #0:1 (pcm_s16le -> libmp3lame)
Press [q] to stop, [?] for help
frame=    0 fps=  0 q=0.0 size=       0kB time=00:00:00.00 bitrate=   0.0kbits/s
frame=    0 fps=  0 q=0.0 size=       0kB time=00:00:00.00 bitrate=   0.0kbits/s
frame=    0 fps=  0 q=0.0 size=       0kB time=00:00:00.00 bitrate=   0.0kbits/s
frame=    3 fps=  1 q=22.0 size=      39kB time=00:00:00.04 bitrate=8063.8kbits/
frame=    8 fps=  2 q=22.0 size=      82kB time=00:00:00.24 bitrate=2801.3kbits/
frame=   13 fps=  3 q=23.0 size=     120kB time=00:00:00.44 bitrate=2229.5kbits/
frame=   16 fps=  4 q=23.0 size=     147kB time=00:00:00.56 bitrate=2156.7kbits/
frame=   20 fps=  4 q=22.0 size=     175kB time=00:00:00.72 bitrate=1987.4kbits/
:
video:4387kB audio:273kB global headers:0kB muxing overhead 0.260038%
[libx264 @ 05A2C400] frame I:2     Avg QP:19.53  size: 29850
[libx264 @ 05A2C400] frame P:76    Avg QP:22.24  size: 19541
[libx264 @ 05A2C400] frame B:359   Avg QP:25.93  size:  8210
[libx264 @ 05A2C400] consecutive B-frames:  0.5%  0.5%  0.0%  8.2% 17.2% 52.2% 16.0%  5.5%  0.0%
[libx264 @ 05A2C400] mb I  I16..4:  5.4% 75.3% 19.3%
[libx264 @ 05A2C400] mb P  I16..4:  1.3% 16.5%  2.2%  P16..4: 36.3% 28.6% 12.7% 1.8%  0.2%    skip: 0.4%
[libx264 @ 05A2C400] mb B  I16..4:  0.4%  3.8%  0.3%  B16..8: 40.0% 18.4%  4.7% direct:18.5%  skip:13.9%  L0:45.4% L1:38.1% BI:16.5%
[libx264 @ 05A2C400] final ratefactor: 20.35
[libx264 @ 05A2C400] 8x8 transform intra:83.1% inter:68.5%
[libx264 @ 05A2C400] direct mvs  spatial:99.2% temporal:0.8%
[libx264 @ 05A2C400] coded y,uvDC,uvAC intra: 64.9% 83.4% 49.2% inter: 49.0% 50.4% 4.4%
[libx264 @ 05A2C400] i16 v,h,dc,p: 25% 22% 27% 26%
[libx264 @ 05A2C400] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 10%  7% 23%  9% 10% 10% 10%10% 13%
[libx264 @ 05A2C400] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 12% 11% 13%  9% 12% 11% 10% 9% 12%
[libx264 @ 05A2C400] i8c dc,h,v,p: 42% 28% 16% 14%
[libx264 @ 05A2C400] Weighted P-Frames: Y:18.4% UV:7.9%
[libx264 @ 05A2C400] ref P L0: 29.1% 11.3% 15.7%  7.3%  6.9%  4.9%  5.1%  3.4%3.9%  2.7%  2.8%  1.8%  1.7%  1.2%  1.4%  0.9%
[libx264 @ 05A2C400] ref B L0: 68.8% 11.4%  5.5%  2.9%  2.3%  1.9%  1.5%  1.1%1.1%  1.0%  0.9%  0.7%  0.5%  0.3%  0.1%
[libx264 @ 05A2C400] ref B L1: 91.9%  8.1%
[libx264 @ 05A2C400] kb/s:2055.88

As far as I'm concerned it doesn't look that bad to me.

sjngm

Posted 2012-01-20T17:38:31.903

Reputation: 1 873

2Lossless presets will ignore your declared -b. – llogan – 2012-01-21T00:26:55.177

1

I found a nice doc to help with finding good options.

– sjngm – 2012-01-21T18:39:12.147

Answers

9

You should first upgrade to at least FFmpeg 0.9. vpre is not really encouraged to be used for preset control anymore. This is why the ffpreset files have been removed from newer versions. Preset control for libx264 now happens through x264 itself, not through FFmpeg.

That being said, setting an average bitrate for x264 is the worst rate control mode there is. Rather than an average bitrate, you should consider using two-pass encoding if you are targeting a specific output file size, or setting a Constant Rate Factor (CRF) if you just care about achieving a specific quality. If in doubt, use CRF.


You generally want the following syntax for using FFmpeg and x264:

ffmpeg -i in.mp4 -vcodec libx264 <options> out.mp4

… with the following non-mandatory options. It is important to specify them before the output and after the vcodec switch. Those are just some (see also the options mapping for more):

  • -vprofile: Set h.264 profile constraints, e.g. baseline, main, high

  • -preset: Set an encoding preset, which generally enables optimization strategies. You can choose from veryslow, slow, fast, ultrafast, and many more. Slower presets result in better compression at a cost of slower encoding. You generally use the slowest preset you have patience for.

  • -tune: Set a special tune factor, e.g. for movies: film

  • -b: Set the bitrate. As already said, this is not really what you want with a one-pass encoding, but if you need to, this should work. Possible values are in Bits, or rather 500K, 1M, et cetera.

  • -crf: Set quality. Mutually exclusive with -b. A good starting value is 24. A lower value is higher quality. Use the highest value that still looks good to you.


Two-pass example, H.264 video, AAC audio in MP4:

ffmpeg -i input -c:v libx264 -preset slow -b:v 500k -pass 1 -an -f mp4 -y NUL
ffmpeg -i input -c:v libx264 -preset slow -b:v 500k -pass 2 -c:a libfaac -b:a 128k output.mp4

CRF example, H.264 video, MP3 audio in MKV:

ffmpeg -i input -c:v libx264 -preset medium -crf 24 -c:a libmp3lame -q:a 4 output.mkv

slhck

Posted 2012-01-20T17:38:31.903

Reputation: 182 472

Also, if you still experience any problems, please post the full command line and the full FFmpeg / x264 output you get. – slhck – 2012-01-20T23:45:49.283

Thanks a lot, that showed some new info to me! Please read my question as I appended my recent findings into it. It looks okay to me. – sjngm – 2012-01-21T18:02:28.277

Regarding two-pass: if I use -vcodec libx264 as the only video-specific option for the second pass I get an error (maybe incorrect parameters such as bit_rate, rate, width or height). It works if I add -vb 1978k. So I have to add a bitrate-option. -minrate and -maxrate seem a little vague to me. Or is -vb okay for two-pass? – sjngm – 2012-01-21T19:10:41.957

Some comments on your updated question: 1) MP3 isn't officially supported in MP4. 2) Use two-pass encoding if you are targeting a specific output file size and don't care about quality. Use CRF if you want to target a specific quality and don't care about file size. – llogan – 2012-01-21T20:06:08.843

@LordNeckbeard Thanks for the edit. /dev/null won't work in Windows I guess, do you know what to use instead? – slhck – 2012-01-21T21:10:13.637

@sjngm Pinging you about the updated answer and LordNeckbeard's comments. – slhck – 2012-01-21T21:10:27.817

@slhck yeah, it's NUL – sjngm – 2012-01-21T23:09:07.603

@LordNeckbeard You are confusing me. I'm reading your comment as if I did something wrong. However, I said I used -vb for the second pass and in your two-pass edit you put -b:v which is the same IMHO. So am I doing something wrong or am I doing okay? – sjngm – 2012-01-21T23:18:05.640

@slhck You're right. I forgot that sjngm is using Windows and I'm not sure what the Windows equivalent is. Alternatively, a simple file name could be used and the second pass can use the same file name with the -y option. Maybe a Windows user should change the example. – llogan – 2012-01-22T08:30:58.253

@slhck -b:v is the current syntax to declare video bitrate. -vb will work for older FFmpeg versions and may still mapped to -b:v. I'm not sure what is causing your "incorrect parameters" message without knowing your command, but start with a simple command. You probably won't need -minrate and -maxrate. – llogan – 2012-01-22T08:35:10.400

@LordNeckbeard I guess you meant me ;). Thanks to everybody I think I got what I need now. – sjngm – 2012-01-22T14:32:31.303