Updated: May 29, 2011.
If you've found this guide helpful, please consider making a donation.
To get started you need to install the latest version of mplayer, x264, ffmpeg and neroAacEnc.
Using FFmpeg or mencoder to handle everything is convenient but you gain more control and get better results by breaking down the steps and using the best tool for that specific job.
Encoding the video
In order for x264 to encode the video stream we must first decode our source video stream with mplayer, convert it to a (lossless) yuv4mpeg stream, or y4m for short, and pipe it to x264 as input.
Here's another example that's more advanced. This is how I encode video for my iPhone.
$ mplayer -nosound -benchmark -sws 9 -vf dsize=480:320:0,scale=0:0,expand=480:320,dsize=1.5 -vo yuv4mpeg:file=>(x264 --demuxer y4m --crf 20 --preset slow --profile baseline --level 30 --vbv-bufsize 10000 --vbv-maxrate 10000 --threads auto --output output.264 - 2>x264.log) star-wars.mkv
In the above command I set the lanczos scaler algorithm with
-sws 9 to be used when scaling the video down. It's slower than mplayer's default scaler but if quality is your main concern then I recommend using it.
-vf dsize=480:320:0,scale=0:0,expand=480:320,dsize=1.5 is the video filter chain that scales the video to 480x320 while maintaining the original aspect ratio and adds padding to the top and bottom or left and right and sets the aspect ratio to 1.5 (480/320).
Let's say you want to encode some anime for your phone, ps3 or whatever but you need to hardsub the subtitles because your device doesn't support loading softsubs and you haven't learned Japanese yet, slacker. In case you don't know, hardsubbing is encoding the subtitles into the video stream.
$ mplayer -nosound -benchmark -fontconfig -font 'Sans:style=Bold' -subfont-outline 2 -subfont-text-scale 2.1 -sub-bg-alpha 0 -subfont-blur 0 -sub-bg-color 0 -sws 9 -vf dsize=480:320:0,scale=0:0,expand=480:320,dsize=1.5 -vo yuv4mpeg:file=>(x264 --crf 20 --preset slow --profile baseline --level 30 --vbv-bufsize 10000 --vbv-maxrate 10000 --threads auto --output output.264 video.y4m 2>x264.log) anime.mkv
You can adjust the size of the font by increasing/decreasing the value in
-subfont-text-scale 2.1. If you want to use a different font, you can get a list by running
fc-list | sort | less.
Note: If you want to hardsub advanced sub station styled subtitles, or ass for short, remove all the
-sub* options along with
-font 'Sans:style=Bold' and add
-ass. Most of the time I think they look like ass, har har.
Deinterlace PAL dv, double the frame, scale to 4/3 aspect ratio and pipe to x264. MPlayer can't change the frame rate so we use mencoder. The results will look pretty good!
mencoder input.PAL.dv -of rawvideo -ofps 50 -ovc raw -vf yadif=3,mcdeint=2:1:10,scale=768:576,format=i420 -nosound -really-quiet -o - 2>/dev/null | x264 --demuxer raw --crf 20 --threads auto --fps 50 --input-res 768x576 --output output.264 -
x264 levels and profiles
Most devices only support up to specific level and one or more profiles. Levels define the max macroblocks per second, max frame size (macroblocks) and max video bit rate. Profiles define the h264 capabilities that can be used, such as b frames and CABAC. The H264 wikipedia page lists all the levels and profiles. Update: x264 now has presets and profile settings.
x264 --fullhelp | less for more info.
Encoding the audio
The audio will be handled much like the video. mplayer will be used to convert the audio to wav and pipe it to neroAacEnc inside the subshell.
$ mplayer -nocorrect-pts -vo null -vc null -ao pcm:fast:file=>(neroAacEnc -ignorelength -lc -q 0.6 -if - -of audio.mp4 2>nero.log) start-wars.mkv
-nocorrect-pts gets around the "Too many buffered pts" bug in mplayer,
-vo null -vc null ignores the video,
-ao pcm:fast:file=>(neroAacEnc ...) pipes the wav to the subshell running neroAacEnc and
start-wars.mkv is our input. Inside the subshell we set
-ignorelength because neroAacEnc is reading from a pipe,
-lc forces the use of the LC AAC profile (supported by most devices),
-q 0.6 enables target quality mode (vbr),
-if - specifies the pipe from mplayer as the input,
-of audio.mp4 outputs the encoded aac audio to
2>nero.log sends the console output to nero.log (open another terminal and run
tail -f nero.log to monitor its progress).
neroAacEnc -help 2>&1 | less and
man mplayer for more info.
Muxing into the container