Our Blog

Using FFMpeg with c#

by BillyTheKid April 08, 2009 07:14

Video is becoming more pervasive on the web and any of you that have been asked to work with video, have probably looked at FFMpeg.  For those who don’t know, it’s a command line video (and audio) conversion tool, and it’s open source.

For this example, I’m going to write a small class in c# which will use the System.Diagnostics.Process class to run ffmpeg and parse the video size, duration and frame rate from the output.  I’ll run ffmpeg like this “ffmpeg –i myvideo.avi” without specifying an output file and redirect the error stream to get the info I want.  Here is what the output looks like on the command line.

ffmpeg_out

To use the class, first we pass the file name of the video in the constructor:

Technoponics.Video.FFMpeg v = new Technoponics.Video.FFMpeg("myvideo.avi");

Then you call the CheckVideo method, which will then fill in the Width, Height, Fps and Duration public properties.

v.CheckVideo();
Console.WriteLine("Video Size: "+v.Width+"x"+v.Height);

Here is the code for the FFMpeg class (ffmpeg.cs file):

using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace Technoponics.Video {

class FFMpeg {

public string Width {get {return _width;} set {}}
public string Height {get {return _height;} set {}}
public string Fps {get {return _fps;} set {}}
public string Duration {get {return _duration;} set {}}
public string FileName {get {return _filename;} set {_filename = value;}}
public bool IsVideo {get {return _foundInput0;} set {}}

private static string _width;
private static string _height;
private static string _fps;
private static string _duration;
private static string _filename;
private static bool _foundInput0 = false;

public FFMpeg() {
_filename=@"d:\ffmpeg\arts10.flv";
}

public FFMpeg(string File) {
_filename=File;
}

public void CheckVideo() {

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.EnableRaisingEvents=false;
p.StartInfo.FileName=@"d:\ffmpeg\ffmpeg.exe";
p.StartInfo.Arguments="-i "+_filename;
p.StartInfo.CreateNoWindow = false;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = false;

p.ErrorDataReceived += new DataReceivedEventHandler(checkVideoHandler);

p.Start();
p.BeginErrorReadLine();
p.WaitForExit();
p.Close();

}

private static void checkVideoHandler(object sender, DataReceivedEventArgs outLine) {
if (!String.IsNullOrEmpty(outLine.Data)) {
string tmp = outLine.Data.Trim();

// looks ok, probably a video
if (Regex.IsMatch(tmp,"^Input #0")) _foundInput0=true;

// get the duration
Match m = Regex.Match(tmp,@"^Duration: (\d+:\d+:\d+\.\d+),");
if (_foundInput0 && m.Success) _duration=m.Groups[1].Captures[0].ToString();

// get width, height, fps and pixelformat
if (_foundInput0 && Regex.IsMatch(tmp,@"^Stream #0\.0(\(eng\))?: Video: ")) {
_width=tmp.Split(',')[2].Trim().Split(' ')[0].Split('x')[0];
_height=tmp.Split(',')[2].Trim().Split(' ')[0].Split('x')[1];
_fps=tmp.Split(',')[3].Trim().Split(' ')[0];
}


}
}

}

}


To test my class I created a small console app.  Here the source code for testapp.cs:

using System;

namespace TPN {

class Console_Test {

static void Main(string[] args) {

if (args.Length==0) {
Console.WriteLine("usage: testapp.exe [filename]");
Environment.Exit(0);
}

Technoponics.Video.FFMpeg v = new Technoponics.Video.FFMpeg(args[0].ToString());
v.CheckVideo();

Console.WriteLine("Video Size: "+v.Width+"x"+v.Height);
Console.WriteLine("Duration: "+v.Duration+" / "+TimeSpan.Parse(v.Duration).TotalSeconds+" seconds");
Console.WriteLine("FPS: "+v.Fps);

}
}
}

To compile the the testapp on the command line you would use the following:

csc /target:exe testapp.cs ffmpeg.cs

Then when running my test app on a video file, I get the following output:

testapp_out

There are many things you can do with ffmpeg, here are a few examples.

Take a screen grab from a video:

ffmpeg -i myvideo.avi -ss 00:00:15 -s 640x480 -f mjpeg -an -r 1 -vframes 1 thumb.jpg

Grab a 30 second sample from a video:

ffmpeg -i myvideo.avi -ss 00:05:01 -t 00:00:30 myvideo_sample.avi

I have successfully used ffmpeg from an ASP.Net page, but you need to make sure the page using it runs as a user that has execute permissions by using impersonation (in web.config).  The other issue you will need to overcome in order to use it with ASP.Net would be the execution timeout of an ASP.Net thread/page.  Converting a large video could and will take more time than the default execution timeout, so some strategy of putting it into a background thread will be required. 

FFMpeg Win32 Builds

Tags: ,

Coding | English

Comments

05/28/2009 12:22:49 #

You are my HERO. Thanks for the example. I have been struggling for hours looking at 'Standard' output when apparently I should be looking at 'Error' output.

Phil

06/30/2009 21:59:11 #

this is very helpful.Thankss!

Fatih Turkey

08/13/2009 00:57:04 #

Excellent tutorial, it looks quite concise!

I'm a bit confused as to the line:
Technoponics.Video.FFMpeg v = new Technoponics.Video.FFMpeg("myvideo.avi");

Obviously its not a C# type, but I can't you that you've imported anything?
I'm obviously missing something here so please enlighten me Smile

Thanks

Ric United Kingdom

08/13/2009 00:58:55 #

Please forget that stupid comment, I haven't woken up. Blonde moment maybe.

AWESOME tutorial

Ric United Kingdom

Comments are closed