To get started you need to install the latest svn version of mplayer, x264 and grab neroAacEnc from here. You also need to install gpac for muxing into the .mp4 container. Using FFmpeg or mencoder to handle everything is convenient but they have problems. We can avoid these problems by breaking down the steps and using the best tool for that specific job. Encoding the videoIn 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 send it to x264 as input. x264 won't accept y4m as input through a conventional pipe '-' and y4m is uncompressed, so we'll use a fifo, or named pipe, to pipe the y4m through to x264 as input.
$ mkfifo video.y4m $ x264 --crf 20 --threads auto --output output.264 video.y4m 2>x264.log & mplayer star-wars.mkv -vo yuv4mpeg:file=video.y4m -nosound -benchmark The above command is a very basic example just to show how the process works. It's not intended to be used. In the first half of the command we run x264 with '--crf 20' to enable constant quality mode, '--threads auto' enables parallel encoding, '--output output.264' outputs the raw h264/avc bytestream to 'output.264' (this is the encoded video), 'video.y4m' is our fifo that mplayer is feeding y4m to and x264 is reading as input, '2>x264.log' sends the terminal output from x264 to x264.log (you can open another terminal and monitor x264's progress with 'tail -f x264.log') and '&' sends x264 to the background. In the second half of the command we specify mplayer's input file 'star-wars.mkv', convert our source video stream to y4m and direct the stream to our fifo '-vo yuv4mpeg:file=video.y4m', ignore the audio '-nosound' (we'll deal with audio encoding in Step 2) and perform faster than realtime '-benchmark'. For more info see 'x264 --fullhelp | less' and 'man mplayer'.
$ mkfifo video.y4m $ x264 --crf 20 --profile baseline --level 3 --no-cabac --partitions p8x8,b8x8,i4x4 --me umh --subme 7 --vbv-bufsize 10000 --vbv-maxrate 10000 --threads auto --no-fast-pskip --output output.264 video.y4m 2>x264.log & mplayer star-wars.mkv -nosound -benchmark -vo yuv4mpeg:file=video.y4m -sws 9 -vf dsize=480:320:0,scale=0:0,expand=480:320,dsize=1.5 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).
$ mkfifo video.y4m $ x264 --crf 20 --profile baseline --level 3 --no-cabac --partitions p8x8,b8x8,i4x4 --me umh --subme 7 --vbv-bufsize 10000 --vbv-maxrate 10000 --threads auto --no-fast-pskip --output output.264 video.y4m 2>x264.log & mplayer anime.mkv -nosound -benchmark -vo yuv4mpeg:file=video.y4m -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 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.
For example, the iPhone supports level 3 with the Baseline profile. If you look a the levels chart on the H264 wikipedia page it says you can have a max video bit rate of 10 Mbit/s. '--level 3 --vbv-bufsize 10000 --vbv-maxrate 10000' sets the level to 3 and max video bitrate and bufsize to 10 Mbit/s (--vbv-maxrate and --vbv-bufsize takes kbit/s). Now look at the profile chart, Baseline doesn't support CABAC or b frames so I set '--no-cabac'. x264 doesn't enable b frames by default so no further settings are needed. Update: x264 now has presets and profile settings. 'x264 --fullhelp | less' for more info.
Encoding the audioThe audio will be handled much like the video. mplayer will be used to convert the audio to wav and send it to neroAacEnc via a fifo.
$ mkfifo audio.wav $ neroAacEnc -ignorelength -lc -q 0.5 -if audio.wav -of audio.mp4 2>nero.log & mplayer -nocorrect-pts -vo null -vc null -ao pcm:file=audio.wav:fast start-wars.mkv In the first half of the command we set '-ignorelength' because neroAacEnc is reading from a fifo, '-lc' forces the use of the LC AAC profile (supported by most devices), '-q 0.5' enables target quality mode (vbr), '-if audio.wav' specifies the input, '-of audio.mp4' outputs the encoded aac audio to 'audio.mp4', '2>nero.log' sends the console output to nero.log (open another terminal and run 'tail -f nero.log' to monitor its progress) and '&' sends it to the background. In the second half of the command '-nocorrect-pts' gets around the "Too many buffered pts" bug in mplayer, 'vo null -vc null' ignores the video, '-ao pcm:file=audio.wav:fast' dumps the wav to the fifo and 'start-wars.mkv' is our input. See 'neroAacEnc -help 2>&1 | less' and 'man mplayer' for more info. Muxing into the container
Remember to use the fps from your source video. $ MP4Box -fps 25 -add output.264 -add audio.mp4 star-wars.mp4 |