FFMpeg

Between all the ripping of my (legally) purchased DVDs and transcoding them to the proper format for my iPod I found out that most of the applications that I used have something in common (from Videora [free] to Mediacoder (open source). All these applications actually use FFMPEG under the hood: FFMPEG literally accepts many fileformats, open-sourced and runs on too many platforms (it’s highly portable, I guess). Trouble is, since it’s part of the other multi-platform media player (MPlayer) and, particularly, thanks to the legal minefield that is called transcoding, the binaries for FFMPEG are hard to find (well, you can’t miss it now!) (you can also fetch the sources and compile a binary yourself: you’d probably need to get the MingW compiler/environment).

Anyway, all videoconverter applications that I found had either crappy interfaces or they came with that ‘build-in’ Internet browser that allows the developer to push unneeded and unwanted ads to your desktop. So yeah, it shouldn’t be too hard to build your own fricking video converter. You only need to know and study FFMPEG’s commandline options after reading this (boring code after the fold).

Update: Slightly related: the BBC’s programming team released the very first version of their Dirac Video Compression codec.

First of all, I (naturally) wrapped the external calls in an object, which launches a thread, using the method ‘execThread’ as the ThreadStart procedure. I also (surprisingly) discovered that FFMPEG writes logging to the error output (instead of the expected standard output).

The code should be easy to understand (kids-play, kids-play): I decided to use the (synchronous) methods of the process class (reading stream via nprocess.StandardError). You can also use the typical asynchronous calls if you’re into events: in that case you need to flip the specific Events property of the Process object. I also added simple ‘parsing’ for calculating the progress of FFMPEG: not quality code but that wasn’t the point of this.

As additional notes:

- The specific ‘synchXxxx’ methods are the typical .Net style method invokers to the main thread.

- Don’t bother asking about specific FFMPEG command-line arguments. I don’t care.

- Notice that the Windows version of FFMPEG is GPL-ed: this took me by surprise (too). From the notes (in your FFMPEG directory):

This binary build license is GPL, not LGPL, please read COPYING.txt

Code follows:

        private void execthread() {
            Process nprocess = new Process();
            float duration = 0.00F, current = 0.00F;

            nprocess.StartInfo.FileName = Path.Combine(Application.StartupPath, "ffmpeg.exe");
            nprocess.StartInfo.Arguments = @"-i ""C:\myfile.mpg"" -ar 22050 -ab 32 -f flv -s 320×240 -aspect 4:3 -y somemove.flv";
            nprocess.EnableRaisingEvents = false;
            nprocess.StartInfo.UseShellExecute = false;
            nprocess.StartInfo.CreateNoWindow = true;
            nprocess.StartInfo.RedirectStandardOutput = true;
            nprocess.StartInfo.RedirectStandardError = true;
            nprocess.Start();
            StreamReader d = nprocess.StandardError;
            do {
                string s = d.ReadLine();
                if (s.Contains("Duration: ")) {
                    string stime = functions.ExtractDuration(s);
                    duration = functions.TotalStringToSeconds(stime);
                    synchTotal(duration.ToString());
                } else {
                    if (s.Contains("frame=")) {
                        string currents = functions.ExtractTime(s);
                        current = functions.CurrentStringToSeconds(currents);
                        synchCurrent(current.ToString());
                        synchTextOutput(s);
                    }
                }
            } while (!d.EndOfStream);

            nprocess.WaitForExit();           
            nprocess.Close();
        }