Mar 03 2009
High Quality h264 MP4 Videos with ffmpeg
I’ve recently been doing some research in the area of producing High Quality MP4 files with the h264 codec. Of course, my program of choice for encoding to this format was ffmpeg with the libx264 codec. I just wanted to share some of my findings, in particular a few example commands for creating these videos.
On my journeys i found a few useful websites, in particular this one for explaining all the options in libx264 and their corresponding ffmpeg names. Of course, these are largely redundant now that ffmpeg have started distributing libx264 presets, more on those in a minute. The Wikipedia page on x264 is also quite useful.
Presets
So, ffmpeg have started bundling presets for libx264. On Gentoo Linux these are found in /usr/share/ffmpeg/, i suspect they’ll be in similar places on most Linux Operating Systems. These are really handy as they provide a large number of sensible options for libx264 in ffmpeg. On the command line you use them like this:
1: ffmpeg -i inputfile.avi -vcodec libx264 -vpre hq -vpre normal outputfile.mp4
The important bits there, are the –vpre switches. These indicate which preset to use. By default ffmpeg will look to /usr/share/ffmpeg/ for these presents, although i think you can make your own and put them in ~/.ffmpeg/ – not sure though.
You can define as presets in your ffmpeg command as you like, but bare in mind that these presets are cascading, so if you have the same option defined in each preset, then the last one will be the one used.
So, if there was g=200 in the hq preset, and g=250 in the normal preset, then g=250 is what would be used.
Sample commands
So then, on to some sample commands. These are what I’ve come up with through my research for YSTV after we acquired some 1080i HD cameras.
1: ffmpeg -i inputfile.avi -vcodec libx264 -vpre hq -vpre normal -pass 1\
2: -s 640x360 -b 2000000 -threads 0 -deinterlace -f mp4 outputfile.mp4
3:
4: ffmpeg -i inputfile.avi -vcodec libx264 -vpre hq -vpre normal -pass 2\
5: -s 640x360 -b 2000000 -threads 0 -deinterlace -f mp4 outputfile.mp4
6:
7: MP4Box -inter 500 outputfile.mp4
For these, the source file was a 720p video. The encoding wasn’t the fasted in the world – i averaged about 10fps on a Core 2 Duo 2.4Ghz machine!
Couple things to point out though, the –threads 0 option is useful, as it tells libx264 to guess how many threads to use based on the number of cores present. Also note the –deinterlace isn’t always needed, but since mp4 isn’t interlaced, it doesn’t hurt to have it there just in case your source video is interlaced.
You’ll also notice the size and bit rate – 630×360 at 2mbit. These aren’t in a HD resolution, but this size does make it ideal for us to embed into a webpage (JW Player will play these files just nicely). At 2mbit, most users will be able to watch these videos without too much waiting around. Of course, if you want a 720p video, then just change –s 640×360 to –s 1280×720 (or you can go to –s 1920×1080 is you want full HD). In each case you may need to up the bit rate slightly, –b 4000000 (4mbit) seemed ok in my testing for a 720p video.
Obviously these are for Widescreen videos in a 16:9 format. You can still use the same technique for Standard Def files in 4:3 or 5:4 if you like – I’ve used a resolution of 640×512 quite successfully with the above commands for a 5:4 video starting at 720×576 resolution. If you’ve got a 4:3 video, then 640×480 would be better. This, again, is something that would be useful for embedding in a webpage if you want to offer a large video to users, and a 2mbit bit rate, there aren’t many reasons not to!
MP4Box
As you’ll note from the above command I’ve used MP4Box on the file after it’s encoded. This is to move the, so called, ‘MOOV’ atom of the mp4 file to the beginning of the file and make it suitable for progressive download in a web player. Ultimately, this means that you can load the page and start watching the file and it’ll download whilst you’re watching it and you don’t have to wait for the whole thing to download first!
Conclusion
I like x264. Coming from using FLV to embed videos on a webpage using a flash player, this is a massive step up. The quality you get out of x264 is far greater than FLV for a similar bit rate AND x264 handles fast motion and darker scenes much better than FLV. On top of that, with a few small tweaks you can make the video play on an iPod…There are so many more possibilities with x264 than FLV – I fear I’ve only just scratched the surface.
One response so far
As I have learned it seems that deinterlace ALWAYS has to be the FIRST option, otherwise it will NOT WORK!
So you have to put -deinterlace as the very first option!!!