I was up extremely late last night figuring this out, so I made some rough notes as I went along. Hopefully they’ll save someone a small nightmare.

Disclaimer: I haven’t written C code since I was in my teens, and apart from some Objective-C from the comfort of XCode, I haven’t really done a whole lot of GCC compiling on any system, so this may not be the best way to do any of this.

Flash Video

First of all, what are we doing? Compiling a portable FFMPEG binary from source so that we can include the exact libraries we want and run FFMPEG from another application. Why? In short, I want to convert almost any video format to… FLV/F4V. Technically the extension is irrelevant, what we are talking about here is the video codec used, which is either the Sorenson H.263 codec (Flash Player 6+), On2’s VP6 (FP 8), or H.264 (FP 9 update 3).

The F4V extension is really for files that use the H.264 codec in an MP4 container. So it’s up to you which you target, but it will impact on what you build into FFMPEG. The audio-codec used is generally MP3, but for the H.264 video it is AAC or MP3 (AAC is used in most MP4 files, such as podcasts from iTunes).

Now when you convert a video using FFMPEG, it will figure out what format to use based on the output file extension (e.g. flv), but you can supply extra parameters to choose a specific audio or video encoder.

For more info on the codecs inside FLV files see this Wikipedia page.

Compiling C-based Projects from Source on Mac OS X

Below are the general steps to compiling C-based projects on your Mac.

  • Install XCode (developer.apple.com) – this installs the required GCC compiler.
  • Download and extract your source code, for example, the lame library.
  • Navigate to the extracted folder in Terminal.
  • Run ‘./configure –enable-static –disable-shared‘. This will set up the make files with the given options for compilation, these options depend on the project, but they can be as general as where to find linked libraries, or what features to enable in the end product. In this case we’re doing a standard static compilation (this means a user won’t require shared libraries on another computer as we will compile them in and link to them statically).
  • Run ‘make && sudo make install‘. Here I’m “making” aka compile and linking (you’ll see the binary appear in the source folder), then calling sudo to allow super user permissions and finally I’m also “make installing” it -copying it to the relevant place on my system so that I can invoke the new functionality from anywhere, and copying the libraries to my /usr/local/lib folder so that I may use them in other projects… such as FFMPEG!

Note: If you used something like Macports (or Fink) to install lame and any other video or audio libraries in the past, you’ll find that it installed them as dynamic libraries, dynlibs (and probably put them in /opt/local or /sw). This won’t do as we cannot statically link to these when compiling FFMPEG, we require the “.a” files. So I’m afraid that means you have to download the source for these separately, and when you ./configure them, make sure you specify –enable-static. You should then find them located in /usr/local/lib (by default) so that the linker can pick them up when we build FFMPEG.

I would take some time to look at the difference between static and dynamic libraries in *nix environments if like me this sort of thing is either forgotten or way over your head:

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

Compiling the Dependencies

Download the source for the desired extra libraries, such as lame (http://lame.sourceforge.net/), x264 (http://www.videolan.org/developers/x264.html), faad and faac (http://www.audiocoding.com/downloads.html). You can then extract each to a folder, and follow the above instructions on Compiling C Source on Mac OS X. With x264 I had trouble building from the provided tar files, so I used git to get the latest source from their repo, but that requires you have compiled and installed git and Yasm (done in exactly the same way as all the rest of these projects).

Tip: If you download FAAD and FAAC, make sure you download the “bootstrapped” source as that includes the configure tool.

Compiling FFMPEG

When you compile FFMPEG you have two choices as to how you compile it, –enable-static, or –disable-static. This option dictates whether the resulting binary (app) includes within it any dependent libraries, such as libmp3lame used in MP3 encoding/decoding and FAAD for AAC audio decoding (for example in MP4 files). In this case I’m not bothering with FAAC as I am not encoding AAC, but I do want to statically link to libmp3lame.

When you go to compile FFMPEG, follow these instructions, and all should go well, giving you an ffmpeg binary that has everything it needs to convert video with the formats and codecs mentioned.

http://stephenjungels.com/jungels.net/articles/ffmpeg-howto.html

Using FFMPEG

Here’s the command line required to turn a sample video into an FLV file using MP3 audio and H.264 video codecs (I know, I know, I should be using MP4/F4V but I had serious problems getting that to play in anything). This file should play in any well-written video player as long as you require Flash Player 9.0.115.0 or higher.


./ffmpeg -y -i inputvideo.avi -acodec libmp3lame -vcodec libx264 -ab 96k -ar 44100 -b 256000 -g 40 video.flv

You can probably guess some of the flags, -y = overwrite file, -acodec = audiocodec, -vcodec = video codec, -ab = audio bitrate, -ar = audio sample rate, -b = bitrate, -g = frame grouping (used for keyframe creation/scrubbing).

Missing MetaData

So it may create a video that you can play, but you can’t see the video’s duration or actively scrub to another part of the video (I recommend installing an offline player like Wimpy FLV to test your videos easily). This is because FFMPEG does not inject the metadata into FLV files. But there is a cross-platform GPL’d tool that works (and they supply pre-compiled binaries!)

http://code.google.com/p/flvmeta/

Simple run ./flvmeta input.flv output.flv to inject correct meta-data.

The coders of these projects are true heroes of the community. Thank you.

Wrapping up

In my case I did not specify the –enable-non-free flag when ./configure’ing FFMPEG so that I can redistribute the binary, this meant until the FFMPEG team make their own AAC library, I cannot enable libfaad and libfaac to perform AAC encoding/decoding for my H.264 videos (so I’m sticking to MP3). Apparently some faac code has conflicting non-GPL licenses carried over from code written at companies.

Also remember you have to adhere to the LGPL or GPL license when including FFMPEG with your app. You also have to consider extra patent licenses for the codecs used, specifically the MPEG-4 codecs require licensing from the MPEG-LA, and MP3 from Thompson. The cost of licensing is apparently very low. The details of what licenses you require are a horribly grey area, it would take a specialist lawyer to really figure it out, if they could at all, and it depends on what country you are in anyway (see the FFMPEG homepage for more on this issue).

This same approach works for Windows however you’d be using the MingW compiler and probably want to have Cygwin installed to give you a *nixy style setup so the above instructions still work. However it’s much easier to find pre-compiled executables for Windows, in my case I found ones that included everything I had included in the Mac build so luckily I avoided this.