Multimedia Mean Machine: ffmpeg

by Paul Arnote (parnote)

Last month, we took a look at the power of the mencoder command line utility, and how it can help you when working with multimedia files. There is another tool in your multimedia arsenal, called ffmpeg. Ffmpeg is similar to mencoder, but many find its command line much easier to master.

Ffmpeg documentation is fragmented, at best. There is the main documentation, which can be found at http://www.ffmpeg.org/ffmpeg-doc.html. Although the main documentation contains some examples of how to use ffmpeg, finding other examples can lead you in multiple directions during a typical internet search. And the examples given in the main documentation really don't do much to reveal the full power of ffmpeg.

The current version of ffmpeg, and the version in the PCLinuxOS repository, is 0.5. Do use some caution when looking for ffmpeg examples. The ffmpeg developers have been know to change some of the command line parameters when a new version of ffmpeg is released, so items that worked just fine with older versions of ffmpeg, may not work now. The current version was released in March, 2009. So try to pay attention to the dates on the web pages you are seeking examples from. They may or may not work, and your mileage may vary.

Commands

The first command, and one you should get in the habit of issuing before working with a multimedia file, is -i, and represents the input file. Issuing this command, followed by a sole multimedia file, and without an output file specified, will list information for that file, revealing vital information about the formats used for the video and audio. The following is the printout of the file information for the New Moon trailer that I downloaded and converted for my wife to see on her Blackberry Storm:

$ ffmpeg -i new-moon-trailer.mp4
FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.
configuration: --prefix=/usr --enable-shared --libdir=/usr/lib --shlibdir=/usr/lib --incdir=/usr/include --enable-postproc --enable-gpl --enable-pthreads --enable-libtheora --enable-libvorbis --enable-x11grab --disable-debug --enable-swscale --enable-libmp3lame --enable-libfaad --enable-libfaac --enable-libx264 --enable-libxvid --enable-nonfree --enable-libamr_nb --enable-libamr_wb
  libavutil 49.15. 0 / 49.15. 0
  libavcodec 52.20. 0 / 52.20. 0
  libavformat 52.31. 0 / 52.31. 0
  libavdevice 52. 1. 0 / 52. 1. 0
  libswscale 0. 7. 1 / 0. 7. 1
  libpostproc 51. 2. 0 / 51. 2. 0
  built on Jun 2 2009 20:09:15, gcc: 4.1.1 20060724 (prerelease) (4.1.1-4pclos2007)
Seems stream 0 codec frame rate differs from container frame rate: 48.00 (48/1) -> 24.00 (24/1)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'new-moon-trailer.mp4':
  Duration: 00:02:19.88, start: 0.000000, bitrate: 543 kb/s
    Stream #0.0(und): Video: h264, yuv420p, 480x200, 24 tbr, 24 tbn, 48 tbc
    Stream #0.1(und): Audio: mp3, 44100 Hz, stereo, s16, 128 kb/s
At least one output file must be specified

The first line lets you know which version of ffmpeg (0.5, in this case) is being used. What immediately follows is how your version of ffmpeg is configured, and when, and how, it was built. When ffmpeg is compiled, options like which codecs to support and which libraries to include, have to be specified. This information is useful to let you know which codecs are at your disposal. The last 4 lines are what you will be most interested in. The first of those lines tell you the duration of the video file (2 minutes, 19.88 seconds), the starting point of that video (usually 0.000000), and the average bitrate of the video file. The next line tells you the codec used (h264), the resolution of the video image (420p), and the size of the video image (480x200). The third line tells you about the codec used for the audio portion of the file (mp3), the sampling rate (44100 Hz), whether it's stereo or mono (stereo), and the sample bitrate (128 kb/s).

Converting from one format to another is relatively easy with ffmpeg. Take a look at these examples:

ffmpeg -i jinglebells.mp3 jinglebells.wav
ffmpeg -i new-moon-trailer.flv new-moon-trailer.avi

The first one converts the MP3 file, jinglebells.mp3, into a WAV file of the same name. The second one converts the FLV file, new-moon-trailer.flv, to an AVI file, named new-moon-trailer.avi. You need to be sure to use the -i parameter. It tells ffmpeg that the file name immediately following is the input file. Without the -i parameter, ffmpeg will attempt to do the conversion, and name the output file the same name as the input file. Ffmpeg will, by default, attempt to make the conversion as "losslessly" as possible.

Of particular interest is the second example above. While it works, the results are less than stellar. With no other parameters specified, ffmpeg will default to a video bitrate of 200 kbps. The video will not be of very good quality. Fortunately, we can give ourselves much better control of the finished product. Mind you, we can't put in garbage and spit out a diamond. The old adage "garbage in, garbage out" really does apply here. And, unless we exercise control over the finished product, we can put in a diamond, and spit out garbage.

Let's redo the video conversion above, manipulating some of the parameters for the output video:

ffmpeg -i new-moon-trailer.flv -b 500000 -s 480x200 -vcodec libxvid -ab 128k -ar 44100 -acodec libmp3lame new-moon-trailer.avi

So, let's take a walk through what we have done here, item by item. We have specified the input file (-i) as new-moon-trailer.flv. We've also instructed ffmpeg to make the output video bitrate 500 kb/s (-b 500000), to resize it to 480 x 200 (-s 480x200), using the Xvid codec (-vcodec libxvid), to make the sound bitrate 128 kb/s (128k), to make the sound sample rate 44,100 Hz (-ar 44100), to use the MP3 audio codec to encode the audio in (-acodec libmp3lame), and to name the output file to new-moon-trailer.avi. Phew! Are you as out of breath reading all of that as I am leading you through it?

It's actually quite simple, once you break it down into its individual components. The thing to remember is that any options or parameters you specify will apply to the filename immediately following them. Thus, you can specify options for the input file, and for the output file -- even repeating them as necessary withing the same command line. The order in which the options appear is unimportant, other than they must precede the file for which they are intended.

If you were paying attention to the above command line, you might have noticed something else. For the video bitrate (-b 500000), I put the whole number in there. I could have just as easily specified the bitrate as 500k. Similarly, for the audio bitrate (-ab 128k), I could have just as easily specified the bitrate as 128000. The way you specify the number is interchangeable.

Certainly, there are a LOT more options than those that we have covered thus far. The more you dig into ffmpeg, the more you realize how powerful and flexible it is, and just how many possibilities there are. So, with that in mind, let's take a look at a few more examples. If you are interested, a simple Internet search will turn up many more examples than I can possibly present here.

Say you have just saved a file from YouTube or MetaCafe. You take a look at the information/specification of the file, and decide that the audio (or video) portion of the file is already in the format that you want. Ffmpeg makes it easy to "let it ride," and to merely carry over the format you want to keep.

ffmpeg -i rock-and-roll-fail.flv -b 500k -vcodec h264 -s 320x240 -acodec copy rock-and-roll-fail.mp4

The above transcodes the input file, rock-and-roll-fail.flv, at a video bitrate of 500 kb/s, using the h264 video codec, resizes the video to 320x240, copies the file's audio track without transcoding, and produces an output file, named rock-and-roll-fail.mp4.

Ffmpeg also knows how to format your video for the different optical media formats that exist.

ffmpeg -i st-tos-ep-14.avi -target ntsc-vcd st-tos-ep-14.mpg

The above command will take the input file (st-tos-ep-14.avi), and transcode it to a format that is compatible with the NTSC VCD standard (-target ntsc-vcd). Other popular targets include ntsc-svcd, ntsc-dvd, pal-vcd, pal-svcd, and pal-dvd.

You can also use ffmpeg to strip the audio from a video file.

ffmpeg -i 102209-lecture.avi -vn -ar 44100 -ab 192k -acodec libmp3lame 102209-lecture.mp3

The -vn option tells ffmpeg to skip the video portion of the file, and produces the MP3 file with the options specified.

So you have some fun videos you would like to upload to YouTube to share with others? You can convert your videos to the Flash Video (FLV) format with the following command:

ffmpeg -i your_movie.avi -ab 56k -ar 44100 -b 200k -r 15 -s 320x240 -f flv output_file.flv

The -r 15 option sets the frame rate of the video to 15 frames per second. The -f flv option forces the output to the FLV file format.

Your buddy in the band has a whole directory of Windows Media Audio (WMA) files of your group's band practice, some of which you would like to have. But, being an advocate of FOSS and a user of Linux, you aren't all that happy having those files in a closed-source, proprietary format. Ffmpeg can come to your rescue!

ffmpeg -i tues-band-practice.wma -acodec libvorbis tues-band-practice.ogg

Without specifying any further options, the output will be at the default bitrate of 64 kb/s. We can increase that to, let's say, 192 kb/s, by instructing ffmpeg to do so:

ffmpeg -i tues-band-practice.wma -acodec libvorbis -ab 192k tues-band-practice.ogg

Summary

As you can see, there are many possibilities with ffmpeg, and certainly many, many more than we have covered here. I urge you to explore these possibilities. Go through the ffmpeg documentation. Bring up the ffmpeg man pages, by typing man ffmpeg at the command line. Or simply do an Internet search for the conversion you are wanting to do. Without a doubt, you should head on over to the ffmpeg web site, http://www.ffmpeg.com/index.html, and have alook around. I have only barely scratched the surface of what is possible with this powerful multimedia tool. And, as I hope I have shown, it's much easier than you might initially think.