FFmpeg x264 encoding guide
Preset files are available from the FFmpeg source code in the ffpresets subdirectory. Using the 0.5 release or current svn trunk of FFmpeg, running make install will install the preset files to ${prefix}/share/ffmpeg and just specifying -vcodec libx264 -vpre <preset> is sufficient for ffmpeg to find the preset.
Otherwise, you can either copy *.ffpreset from the FFmpeg source into ~/.ffmpeg/ or you can point to a preset file directly in the argument of -vpre in your command line.
Basic FFmpeg Usage
To construct an ffmpeg command line, you need to understand a few fairly simple things. The basic command line format is:
ffmpeg [input options] -i [input file] [output options] [output file]
- input options – these are usually mandatory information that is missing about the source file (for example, in the case of a sequence of image files this could be the frame rate), or the seek position corresponding to the desired start point of the stream
- output options – audio and video filtering (alteration of the sample rate, number of channels, frame dimensions, frame rate), audio and video codecs and their corresponding options, container format and related options
Normally the minimum one should specify in an ffmpeg command line would be something like:
ffmpeg -i INFILE -acodec ACODEC -ab 96k -vcodec VCODEC -b 500k OUTFILE
…replacing the capitalised values as appropriate. When using x264, we need to add some extra bits as the defaults are bad.
x264 – Rate Control Choices
Firstly, you need to decide on a rate control method. This controls how bits are allocated within the stream. At a rudimentary level, you want the quality to remain constant but this implies that more complex frames use more bits and less complex frames use less bits.
Rate control methods available:
- constant quantisation parameter – not recommended anymore unless you know you want it
- constant rate factor – good for one pass when the priority is quality and file size/bit rate is not really a concern
- one pass average bit rate – good for streaming purposes or targeting a bit rate when two-pass is unfeasible
- two pass variable bit rate – good for targeting a bit rate when you have the time to spend on two passes (though the first pass can be quite fast) and are writing to a file
Or in prose, CQP mode is mostly deprecated by CRF as CRF maintains more constant quality which was usually the aim of someone using CQP mode. If you care more about quality than bit rate then I would recommend using one pass CRF to save yourself a bit of time. Evaluate various rate factors between about 25 and 15 (a lower value is higher quality and higher bit rate) until you find a quality level/approximate bit rate with which you’re happy and then you can use that value forever more.
One pass average bit rate is good if you need to aim for an approximate bit rate but don’t have time to run two passes. If you have the time then two passes are recommended as the bits will be better distributed to maintain constant quality.
To use one pass CQP:
-cqp <int>
To use one pass CRF:
-crf <float>
To use one pass ABR or two pass VBR:
-b BIT_RATE -bt BIT_RATE
x264 – FFmpeg Preset Choices
Secondly, you need to choose an appropriate preset from those available.
Presets available (for lossy compression):
- quality related:
- default
- normal
- hq – recommended choice for single pass or the second pass of two passes
- max
- first pass:
- slowfirstpass
- fastfirstpass – recommended choice for first passes
- profile constraints:
- baseline
- main
Note: Profile constraint presets need to be specified with a second -vpre option after the quality/first pass preset, e.g. -vpre hq -vpre main
x264 – Recommended General Options
For all rate control methods you will probably want libx264 to select the number of threads to use to maximise its performance on your CPU(s):
-threads 0
Two-Pass Example
So if you wanted to encode using two-pass VBR, the command line would be something like:
ffmpeg -i INPUT -an -pass 1 -vcodec libx264 -vpre fastfirstpass -b BIT_RATE -bt BIT_RATE -threads 0 OUTPUT.mp4
Note: Use of -vpre fastfirstpass is recommended for first passes as it reduce the encoding time for the first pass while having minimal to no noticable impact on the resulting stream. Also, we don’t encode the audio in the first pass because we will not be using the data that was output.
ffmpeg -i INPUT -acodec libfaac -ab 128k -pass 2 -vcodec libx264 -vpre hq -b BIT_RATE -bt BIT_RATE -threads 0 OUTPUT.mp4
Note: We use -vpre hq in the second pass to obtain a high quality result.
Single-Pass Constant Rate Factor (CRF) Example
Or for a single pass CRF encode:
ffmpeg -i INFILE -acodec libfaac -ab 96k -vcodec libx264 -vpre hq -crf 22 -threads 0 OUTPUT.mp4
Related Reading
Also, see my x264 <-> FFmpeg option mapping and an externally maintained list of mappings with descriptions of what the options mean.
Those of you looking for the iPod/PSP information, I felt it was a little out of place here and have subsequently moved them to their own pages. | iPod guide | PSP guide |
For the Two-Pass example the output file should be either NUL on windows or /dev/null on unix / linux boxes. When using this you also need of -f mp4; to specify the container format, as it cant be determined from the output filename, and -y to overwrite as these “files” ( really devices ) already exists. This will prevent the file being written saving on disk IO bandwidth.
Robert,
I’ve been trying to encode a video using the H.264 codec with an audio bit rate of 384kbps. The source video is encoded at that audio bit rate (but mp2).
For some reason, the resulting audio bit rate is always around 162kbps. If I encode it using mpeg I get 384kbps for the audio bit rate.
I can encode the audio (when using H.264) at a bit rate lower, say 48k or 96k or 128k but just can’t get higher than 162kbps. To be clear, I am setting -ab 384k but the resulting file’s audio bit rate is never above 162k
Hope you can help here. I’ve been scratching my head for a couple of days.
I can take the same video and encoding it using Adobe PPro and I’ll get an audio bit rate of 384kbps.
The difference seems to be that with ffmpeg it is encoded as
video: High@L3.1
audio: AAC LC
while with Adobe PPro
video: High@4.2
audio: AAC LC
So is there some limit with High@3.1 with regards to audio bit rate? Either ways, how whould I get ffmpeg to encode as High@4.2?
Hello Robert,
I’ve found in your site, the most complete documentation of x264 usage and profiling with FFMPEG, making encoding H.264 a joyful experience. Hope FFMPEG developer, write with more detail this feature documentation.
I know you are author of FFpresets and I want to ask you: How do I use Baseline profile correctly using FFpresets? This is what I’m doing.
Having compiled the latest FFMPEG with x264 support from the repositories, I try the following command:
ffmpeg -r 5 -y -s 320×240 -f mjpeg -an -i ‘http://192.168.225.60/axis-cgi/mjpg/video.cgi?resolution=320×240&compression=50&fps=5′ -vcodec libx264 -vpre default -vpre baseline -b 32k -bt 32k -threads 0 hello.mp4
But I get: “[libx264 @ 0x90e8ec0]profile Main, level 1.2″
Is this the correct way to call FFMPEG to use Baseline profile? Perhaps I just misunderstood something about profiles and its doing it correctly.
KR
Could you please also explain the use of the lossless presets?
I assume they are ALL related to speed (and not quality). So what is the difference, bitrate? And where is max positioned, after slow?
* speed:
o ultrafast
o fast
o medium
o slower
o slow
o max
@paulg: Try running a locate on your system for ffpreset, you will see all of the x.264 presets mentioned have a preset/config file which displays all of the info about the bitrate etc being used.
I uploaded a screenshot of them all here: http://www.uploadscreenshot.com/image/45677/7200352
They will indeed only affect the bit rate of the lossless output. I’m not sure of the difference in compression efficiency for the lossless presets. They were suggested by Jason (the current main x264 developer). The order should be:
When I tried using the commands supplied by you for the two pass x264 encoding I end up with empty ffmpeg2pass-0.log file and x264_2pass.log full of data, but the second command (the second pass) exits with an error. Is the empty ffmpeg2pass-0.log normal or should it be filled with data?
It is normal for that file to be empty as libx264 uses its own log file as you have noted. As far as your error goes, can you paste the full command lines you used for the first and second passes and the output from the second pass to http://ffmpeg.pastebin.com/ and paste the link to that back here?
There you go http://ffmpeg.pastebin.com/f745dfc6e
Ah, OK. So there’s the answer. the value of b-pyramid must be the same in the first and second passes. As you’re using ffmpeg 0.5 which was released in March, I’m not sure what the preset files contain. If you add ‘-flags2 -bpyramid’ to your second pass command line, it should work though. Else try compiling x264 and FFmpeg from source from the current development code.
It works with -flags2 -bpyramid! Thanks a lot rob!
I’m aware that the latest ffmpeg should be better, but unfortunately I need vhook support to apply watermarks to some videos, and I think this was removed at some point, and the newer avfilter (?) still did not work when I last checked.
Do you know of a way to use latest ffmpeg and latest x264 and still be able to apply logos watermarked to vidoes?
Thanks.
Not yet in trunk I don’t think. It is at least being worked on and there was some code for an lavfi overlay filter flying around a while ago, but it would take some effort to find it and get it building with the current code I guess.
OK thanks a lot for the info.
can you please tell me why i can’t use subtitles srt with ffmpeg
ffmpeg -i ‘.$in.’ -f mp4 -vcodec mpeg4 -newsubtitle ‘.$in_sub.’ -slang eng -r 25 -b 560000 -s 610×340 -acodec mpeg4aac -ac 2 -ab 64 -ar 44100 ‘.$out_vid
ffmpeg built on hardy ubuntu 8.04 with libx264 everything why cant i use srt ? while mencoder can !!
I’m afraid ffmpeg doesn’t support SRT subtitles yet.
We currently have a problem with libx264 encoded files ending up slightly shorter than the original. The output file is 5-10 frames shorter, creating the effect that the video is cut off prematurely.
I am using the following command:
ffmpeg -i testclip.mov -acodec libfaac -ab 96k -vcodec libx264 -vpre hq -crf 22 -threads 0 testclip.flv
Using another codec I don’t have the same problem. Has anyone run into this before?
Thanks,
KC
Strange. It sounds like the wrapper around libx264 in FFmpeg isn’t flushing the last frames properly or something.
1) Use current libx264 from git clone git://git.videolan.org/x264.git
2) Use current FFmpeg from svn co svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
If you are and/or that doesn’t fix it, maybe try asking Dark_Shikari in #ffmpeg on irc.freenode.net.
I want to encode a video which has h264 codec, but the output generated has no video and audio. below is some detail.
http://ffmpeg.pastebin.com/m69cfba00
Could you also paste the output of ffmpeg -i for the file output from ffmpeg? May I ask why you want to reencode the input file? It should be supported by flash players in its current form.
I am using this code and it works for videos under a minute but nothing more than that…
this works:
exec(“$ffmpegPath -ss $startTime -t 15 -y -i $srcFile -acodec libfaac -ar 44100 -ab 96k -f mp4 -vcodec libx264 -padtop $padTop -padbottom $padBottom -vpre hq -crf 22 -threads 0 $destFile”);
but if i try to encode the whole video that is 2:08 (2 min, 8 sec) it will encode but they wont play.
any idea why? im using cirtex hosting
Can you latch on to the stderr (standard error) output of FFmpeg or run the command from a command line on your host to check it’s completing properly? If not, paste the full output to a pastebin (e.g. http://ffmpeg.pastebin.com/ ) and then paste a link here.
Idont know how to get the output of this at all
thats one of the issues i am having… how do i get it to show me the output? can you show me how to do it with php?
thanks and i have no idea how to use irc.freenode.net either, so i cant go there tio ask questions..
http://php.net/manual/en/function.exec.php
php.net is rather useful methinks.