14 July 2014

FFmpeg Settings for Compatibility when Archiving Videos

We have hundreds of family videos in a variety of formats. Some have been captured from old VHS tapes. Some were recorded on DV tape using a camcorder and then transferred to my computer. And some were recorded on my Canon S5 IS. I want to convert them to a consistent video format that's playable on most of our current devices and will continue to be playable decades in the future. The questions boil down to two: What format to use? How to do the conversion?

A Quick Tutorial

Computer audio and video formats typically have three features:
  • The audio codec: This is how the audio information is compressed and encoded. Some codecs compress the audio to save space. Lossy compression schemes give up some detail of the audio – usually imperceptible detail. Common audio codecs include lossy compression: MP3, AAC, and Vorbis; lossless compression: FLAC (lossless compression); and uncompressed: PCM.
  • The video codec: This is how the video information is compressed and encoded. Most practical video codecs use lossy compression. Commonly-used codecs include H.264/AVC, H.262/MPEG-2, Theora, Motion JPEG, and DV.
  • The container format: This defines how the audio and video streams are interleaved and how metadata about the content is stored including information about which codecs are in use for the audio and video streams. It's the container formats, not the codec that is most familiar to computer users. Popular container formats include MP4, MPEG, AVI, OGG, ASF(WMV/WMA), and MKV.
In theory, any codec should be usable with any container. In practice, certain codecs are generally associated with certain containers. For example, OGG typically uses Theora video and Vorbis audio; MPEG uses MPEG-2 video and MP3 audio; and MP4 uses H.264 video and either MP3 or AAC for audio.

The Plan: Use FFmpeg to convert to MP4

After some research, I've decided that MP4 using the H.264 video codec and AAC audio codec is the best choice for my needs. It has excellent support on a variety of devices, media players, and web browsers and the codecs are also the most commonly used by Blu-ray discs. It also supports metadata.

Conveniently, FFmpeg is an open source program that can convert from just about any format into MPEG-4. Inconveniently, the pre-built versions of FFmpeg that you can download cannot encode high-quality audio in AAC format. It's limited to MP3 due to some unusual intellectual property licenses in the source code. And while MP3 is certainly good enough for the audio, many devices, particularly those from Apple, will not play MP3 audio when stored in an MP4 container.

For maximum compatibility you need a version of FFmpeg with AAC support. So, you (or a tech-savvy friend) will have to build a version of FFmpeg with AAC support. In my last post I wrote instructions on how to do that build.

Using FFmpeg

OK, you followed the instructions and have a functional copy of FFmpeg that supports H.264 and AAC. Now you need to know how to use it. FFmpeg is a command line tool with hundreds of options. The documentation is long and complicated. And if you google for FFmpeg settings you can get really confused really quickly. Much of the information is out of date as FFmpeg has been changed and updated over the last 14 years.

I'm going to get you started by outlining the settings for this particular goal – encoding high-quality videos in MPEG-4 for long-term archive. For these examples, we'll be converting a video called MountainHike.avi into an MPEG-4 version called MountainHike.mp4. This example is based on converting videos from my Canon digital camera. It records videos in .AVI format using a Motion-JPEG video codec. The resulting .MP4 videos are about 1/10 the size of the originals, look just as good (to my eyes) and play on a greater variety of devices.

The Minimal Command-Line (that works)

FFmpeg is a command line tool so you need to launch an command-line shell. Here's the minimal command-line to do our conversion.

ffmpeg -i MountainHike.avi -pix_fmt yuv420p MountainHike.mp4

There are three parameters in this line:
  • -i MountainHike.avi
Specifies the input file name.
  • -pix_fmt yuv420p
Specifies that the pixel format should be YUV4:2:0. All you really need to know about this is that there are a number of different pixel formats. Some offer better quality than YUV4:2:0 but none are as commonly supported. If you don't specify a format then FFmpeg will preserve whatever format was in the original video and there's a very good chance that your player will not support that format. So, it's best to specify the pixel format.
  • MountainHike.mp4
A parameter without any prefix is considered to be the destination file name. Since the file name has a .mp4 extension, FFmpeg infers that the destination format is MP4 and it defaults the video and audio codecs to H.265 and AAC respectively. Those happen to be what we want and so thinks work. But, to optimize quality and compatibility we need a few more settings.

Explicitly Specify the Codecs and the File Format

ffmpeg -i MountainHike.avi -pix_fmt yuv420p -c:v libx264 -c:a libfdk_aac -f mp4 MountainHike.mp4

It's a good idea to explicitly specify which codecs to use and the destination file format. That way you're sure you're getting what you expect. The command line above does that. Here is what the additional parameters do:
  • -c:v libx264
Specifies that the video codec should be H.264.
  • -c:a libfdk_aac
Specifies that the audio codec should be AAC.
  • -f mp4
Specifies that the container file format should be MP4 (also known as ISOM or ISO base media file format).

Setting the MPEG-4 Profile for Compatibility

ffmpeg -i MountainHike.avi -pix_fmt yuv420p -c:v libx264 -c:a libfdk_aac -profile:v main -level 3.1 -f mp4 MountainHike.mp4

The MPEG-4 standards specify a number of different feature profiles. The best known are "baseline", "main", and "high". Within each profile are levels. the "main" profile with level "3.1" is supported by most mainstream devices including desktops, tablets, and phones. So it's a good choice to ensure compatibility.

Here are what the additional parameters do:
  • -profile:v main
Specifies that the MPEG-4 "main" profile should be used.
  • -level 3.1
Specifies level 3.1 within the main profile.

Setting the Video Quality

ffmpeg -i MountainHike.avi -pix_fmt yuv420p -c:v libx264 -c:a libfdk_aac -profile:v main -level 3.1 -crf 18 -f mp4 MountainHike.mp4

MPEG-4 can achieve higher video quality at the expense of size, or vise versa. In FFmpeg the CRF or Constant Rate Factor is the best parameter for managing quality. Values range from 0 (extremely high quality and high bitrate) to 51 (very low quality and low bitrate). The default is 23 and represents a good balance between quality and size. "Sane" values range from 18 to 28. Reducing CRF by six points will roughly double the file size.

Here's the additional parameter:
  • -crf 18
Since I'm archiving family videos and storage will only get cheaper with time, I'm choosing 18 for the maximum practical quality.

Tweaking the Audio Quality

You can use parameters to tweak the audio quality but I recommend leaving them alone. With no audio parameters, it will automatically select stereo or mono according to the input video and uses 128 kbps which is very good quality. If you do want to tweak the audio quality, start with this article.

Please Share

That's about all there is to it. If you have settings that work particularly well for you, please share in the the comments section. Happy transcoding!