Video Encoding

So, I've decided to write this guide, because I've found out some things during my many hours of encoding videos. To start off, I much prefer ffmpeg over mencoder, so I will be covering only ffmpeg. I recommend ffmpeg over mencoder, except for when ffmpeg cannot decode the input video.


First of all, here are the two most important references that I used to figure out how to use ffmpeg: ffmpeg docs and ffmpeg FAQ, check there for more info. Also, I have written some text documents to remind myself of some of the important aspects when encoding a video, here they are: ffmpeg CLI options and ffmpeg howto (some notes), look through these before continuing.

As a general note: Before you start encoding any video run 'ffmpeg -i' on it, and use 'mplayer' on the command line to play it. Keep this information up so that you know what options you should use for the output file. Also, the following sections can be used on ANY input file be it .mkv .VOB .avi .wmv, anything that ffmpeg supports.

encode .avi to Divx/Xvid compliant player (mpeg4 and mp3)

Here I will describe how to encode a video that is meant to play on a Divx/Xvid compliant DVD player. Most DVD players sold in Europe support this, and some in the US also do. The best way to encode it is using 2 pass VBR encoding, which will generate the smallest file with the highest quality possible. Also, make sure that the input file is of good quality, for example a HD source will generate a much smaller and higher quality output file than a DVD source, because the amount of noise is much less.

ffmpeg -i input.mkv -vcodec libxvid -qscale 5 -s 640x272 -aspect 40:17 -r 23.976 -g 240 -bf 2 -acodec libmp3lame -ab 160k -ar 48000 -async 48000 -ac 2 -pass 1 -an -f rawvideo -y /dev/null
ffmpeg -i input.mkv -vcodec libxvid -qscale 5 -s 640x272 -aspect 40:17 -r 23.976 -g 240 -bf 2 -acodec libmp3lame -ab 160k -ar 48000 -async 48000 -ac 2 -pass 2 -f avi outlander-q5.avi

Here the 'libxvid' video codec should be used for best quality and compatibility, but '-vcodec mpeg4 -vtag xvid' can be used instead if you don't have libxvid. Remember that the lower the 'qscale' option, the better the quality, the larger the output file, the higher the bitrate. I usually first run a test encode using something like:

ffmpeg -i input.mkv -vcodec libxvid -qscale 5 -s 640x272 -aspect 40:17 -r 23.976 -g 240 -bf 2 -acodec libmp3lame -ab 160k -ar 48000 -async 48000 -ac 2 test.avi

and watch the bitrate during the encode, look at 'bitrate= 800.2kbits/s' or similar. Let it run for a minute, and if the bitrate goes well over 1000.0kbits/s, you should probably consider using a higher 'qscale' or the player may not play it. Check your DVD player manual for the particular limits of your player in terms of bitrate and resolution maximums. For resolution it's best to stick to '640x' and calculate the height yourself. A 'qscale' of 5 is the standard that I use, I've found it to work best in the greatest number of cases, and paired with the '640x' resolution and '23.976' fps, it usually give a file of about 700 MB or less, or double that for extended length videos, like LOTR. One thing to mention is that many videos report a false size / resolution if you run 'ffmpeg -i' on them, instead use 'mplayer', because it will scale videos to the right dimensions, use the size given my 'mplayer' run on the command line.

For the frame per second, try to use whatever the input file has, unless you have a reason to use something else and want to deal with dropped frames. The aspect is usally listed as 'DAR' in 'ffmpeg -i', but if not, or if you don't trust it, which you shouldn't just use whatever you used for the resolution / size option separated by a colon ':', so '640:' and the height you calculate, it will automatically embed the right aspect options. The '-g' is GOP and it should be 10 times the FPS, so in this case 23.976 x 10 = 239.76 which rounds to 240. If you want to mess with the GOP, see the howto I posted above. The '-bf' option is bframes, and it can only be 2 here.

For the audio you can use AC3 instead, but I prefer mp3. You can also use 128k if you want regular audio quality, instead of the somewhat better audio you will get with 160k. For the audio frequency, use whatever the input is, as long as the player supports it. Make sure to use the same frequency for the '-async' option to keep A/V sync (mencoder cannot do this and your audio may be way off sync with the video). The '-ac' option is audio channels, usually you use 2, and mp3 supports no more than 2, so you can also use 1 if you have a reason to, like if the input audio is mono.

I have written a script to do the above steps automatically, it is experimental: Click here to download xenc.gz ( md5sum xenc.gz 872438520a322a226d78afd24174b99f xenc.gz as of Sun Jun 12 14:47:59 EEST 2011)

files larger than 1GB

One important thing to note is that many Divx players cannot play videos that are larger than 1GB or so. Really, most videos should be 700 - 900 MB. One way to do this is use the ffmpeg '-fs' option to limit the file size, but this may cut the video at a bad time, like right in the middle of something important, so instead I prefer to use mplayer and mencoder to do the cutting.

First I watch the movie with mplayer from the command line so that it displays the time in seconds in the terminal. I pause the video somewhere near halfway through, at a time of little action, talking, or importance, where the user will not notice the cut. Then I generate the two pieces using mencoder and time in seconds obtained from mplayer when I pause it at the right time:

mencoder -oac copy -ovc copy -idx -endpos 6391.6 lotr2.avi -o lotr2-part1.avi
mencoder -oac copy -ovc copy -idx -ss 6391.6 lotr2.avi -o lotr2-part2.avi

You should also watch the resulting videos and make sure that they were cut properly, because mencoder doesn't always cut exactly where you tell it to, so adjust the times as needed. It is also possible to cut the video using ffmpeg or other tools, but ffmpeg may cause a/v desync sometimes for unknown reasons when cutting videos so I still prefer mencoder for this.

You can also cut videos so they fit on a certain media, for example, for 700 MB run:

mencoder input.avi -oac copy -ovc copy -idx -af volnorm=1 -endpos 696mb -o HP7-part1.avi

the output will have a line:

Pos:3642.2s  91054f (49%) 5789.29fps Trem:   0min 1400mb  A-V:0.040 [1534:63]

so now you run:

mencoder input.avi -oac copy -ovc copy -idx -af volnorm=1 -ss 3642 -o HP7-part2.avi

for the second half. The '-af volnorm=1' is optional, and is there to try to normalize the volume.

If mencoder produces video with massive A/V desync, try using ffmpeg instead:

ffmpeg -i Cowboys.and.Aliens.avi -vcodec copy -acodec copy -t 3381.7 cowboys-aliens-part1.avi
ffmpeg -i Cowboys.and.Aliens.avi -vcodec copy -acodec copy -ss 3381.7 cowboys-aliens-part2.avi

encode .mkv with x264 and AAC

First, I recommend using my x264 presets, which work very will with low 'crf' values, way better than the 'hq' preset, so get the presets here and extract and put that file in your '~/.ffmpeg' directory, create it if it does not exist. So they should be available at '/home/$USER/.ffmpeg/libx264-special.ffpreset'. So, the following is an example of how to encode using the 1-pass CRF method, which is a special method that can only be used with this codec, and it is very fast and produces very good quality. You can also do 2-pass but then you have to put in a bitrate, and it's slower.

ffmpeg -i input.mkv -vcodec libx264 -vpre special -crf 15 -s 704x396 -aspect 16:9 -r 23.976 -threads 4 -acodec libfaac -ab 128k -ar 48000 -async 48000 -ac 2 -scodec copy output.mkv

If you don't want to use my special presets, you can use any that you want, they're usually found in '/usr/share/ffmpeg'. The crf or constant rate factor is similar to qscale, where lower is better quality, and larger size, 23 is the default used by x264, but 15 is a good quality especially using the special presets which work much better with a lower crf. Set the rest of the parameters as needed using the input file as reference, there is no standard here. For the number of threads use the number of cores your CPU has. Again, make sure to use the same audio frequency for the '-async' option to keep A/V sync.

MKV: Resampling with input channels greater than 2 unsupported. Can not resample 6 channels @ 48000 Hz to 2 channels @ 48000 Hz

If you get the above error message when trying to encode, then you have to take a different route. The usual case is when the audio is 'Audio: aac, 48000 Hz, 5.1, s16', so it has 6 channels, and ffmpeg cannot down matrix 6 channels to 2. However faad can do this, so you have to use this instead. First, you will need MKVToolnix. Here's the best way to do it, at least the best way I know how to do it. First run:

mkvinfo Game.mkv

You will get something like:

| + A track
|  + Track number: 2
|  + Track type: audio
|  + Codec ID: A_AAC

This tells you that track 2 is audio of type aac, so now you can extract it, convert it to wav, then to mp3, mux it back to another mkv, then finally convert the video with:

mkvextract tracks Game.mkv 2:file.aac
faad -d -o output.wav file.aac
lame -V2 output.wav final.mp3
mkvmerge -o out.mkv -A Game.mkv final.mp3
ffmpeg -i out.mkv -vcodec libxvid -qscale 5 -s 640x272 -aspect 640:272 -r 23.976 -g 240 -bf 2 -acodec copy -pass 1 -an -f rawvideo -y /dev/null
ffmpeg -i out.mkv -vcodec libxvid -qscale 5 -s 640x272 -aspect 640:272 -r 23.976 -g 240 -bf 2 -acodec copy -pass 2 game.avi

Remember to always check the output to make sure the sound is ok and there is no a/v desync, as strange things do sometimes happen.


Valid XHTML 1.0 Strict Valid CSS!