Encoding videos for the Xbox 360 using ffmpeg

One of the cooler features of Microsoft's Xbox 360 console is the ability to play back video from a USB memory stick or external hard disk. Only problem is, encoding video can be a bit of a hit-and-miss affair at the best of times, and when you're limited to the codecs supported by the Xbox 360 and can't install any more, a bit of trial and error is required to get good results.

For this little exercise, I'm using a 500Gb Western Digital MyBook Essential Edition which is on special offer from amazon.co.uk, right now for £69.99, and I've got the original footage as raw MPEG-2 files.

I've played with lots of video encoders over the years, both commercial and free, and the best one I've ever used in terms of output quality and encoding speed is an open-source command line tool called ffmpeg.

So... let's say we've downloaded a Win32 binary of ffmpeg from here, we've got our source video file as a raw MPEG-2 file (or just about anything that ffmpeg will read); now it's just a matter of finding the right settings for ffmpeg.

According to the Xbox December 2007 Video Playback FAQ:

Xbox 360 supports the following for MPEG-4:

  • File Extensions: .mp4, .m4v, .mp4v, .mov
  • Containers: MPEG-4, QuickTime
  • Video Profiles: Simple & **Advanced Simple Profile
  • Video Bitrate: 5 Mbps with resolutions of 1280 x 720 at 30fps.
  • Audio Profiles: 2 channel AAC low complexity (LC)
  • Audio Max Bitrate: No restrictions.

Your basic ffmpeg command line looks something like:

C:\>ffmpeg [options] [output file]

The particular invocation we need here is:

ffmpeg -i myfile.mpg -f mp4 -vcodec mpeg4 -b 2000000 -acodec libfaac -ac 2 -ab 128000 -s 640x480 m:\output.mp4

Now let's break those options down and explain what they actually mean...

-i myfile.mpg

specifies "myfile.mpg" as the input file
-f mp4 Specifies that the output file should use the MPEG-4 container format
-vcodec mpeg4 Specifies that within the container, the video stream should be encoded using the MPEG-4 codec
-b 2000000 Specifies the video bitrate - in this case 2,000,000 bits per second, or approximately 2Mbit. Much lower and you'll notice lots of compression artefacts; much higher and you'll have problems with the filesize - see below!
-acodec libfaac Specifies that the audio stream should be encoded using the libfaac codec - an open-source implementation of the AAC audio encoding standard.
-ac 2 Specifies that the output should use two-channel (stereo) output. (The X-Box 360 will not play 5.1 audio from a USB device, apparently)
-ab 128000 Specifies the audio bitrate - roughly 128kbps in this example
-s 640x480 Specifies the size of the output file - 640x480. Output video will be resized to fit the specified size but aspect ratio will be preserved.
m:\output.mp4 The last option is the name of the output file (and the USB hard drive is installed on my system as drive M:)

The X-Box 360 only supports USB storage devices formatted using the FAT32 filesystem, and FAT32 is limited to 4Gb per file. You'll therefore need to calculate your bitrates based on the length of the video files you're encoding. 2Mbps means you're using approximately two million bits = i.e. (2000000 / 8) = 250,000 bytes per second, or 250Kb for each second of video - which equates to (250*60*60) = 900,000 Kb = 900Mb per hour, so you can happily encode movies up to 4.5 hours long at 2Mbps before you hit the FAT32 4Gb-per-file ceiling.

You also need to consider the resolution (width x height) of the output. Higher resolutions means a larger - and more detailed - picture, but costs more bandwidth to maintain the same image quality; in other words, for a specific bitrate, you'll have to choose between big and blurry, or small and sharp.

lilies_large

lilies_smallThese image files are both 12.5Kb in size; you can clearly see the compression artefacts in the larger image above, where we've had to discard more detail in the compression process to reach our target file-size. The smaller image doesn't have such pronounced artefacts - but contains less detail to begin with because it's been reduced to fit a smaller frame size.

If you're encoding video to play back on a specific device, you probably want to use the native resolution of your player. Standard HDTV resolutions are 1280x720 and 1920x1080. The iPod Touch has a native resolution of 480x320, the most recent iPod Nano has a resolution of 320x240. Normal DVD video uses a resolution of 720x576 pixels (on PAL systems) or 720x480 (on NTSC systems).

Obviously this is all highly subjective - your own definition of 'acceptable quality' depends on your equipment, your eyes, and the sort of video footage you're working with - but I find 640x480 at 2Mbps seems to work pretty well. Likewise audio bitrate - if you've got very good ears & speakers and you're encoding something like concert footage, you might want to specify an audio bitrate of 256Kbps (-ab 256000) or higher.

Finally, a note about multi-core systems. ffmpeg does not support multi-threading - this means if you've got multiple CPUs or multiple cores, it'll only run on a single core. However, if you're encoding more than one video file, you can quite happily run two instances of ffmpeg in parallel - Windows is smart enough to run each instance on it's own core, so on my quad-core box I can encode four files simultaneously with each encoder running at full speed. My box will encode about 100 frames per second on each core, so running all four cores flat-out I can encode four seperate one-hour video clips in about fifteen minutes.

Finally, plug the drive with your MP4 files into your Xbox 360, go into the Xbox Dashboard, pick "video" and choose the option to play from external device, and away you go. You may find you need to sign in to Xbox Live! to download the required media updates, but this worked perfectly well when I tried it out so it shouldn't cause any problems.