77

So I know its a fairly big challenge but I want to write a basic movie player/converter in c# using the FFmpeg library. However, the first obstacle I need to overcome is wrapping the FFmpeg library in c#. I've downloaded ffmpeg but couldn't compile it on Windows, so I downloaded a precompiled version for me. Ok awesome. Then I started looking for C# wrappers.

I have looked around and have found a few wrappers such as SharpFFmpeg (http://sourceforge.net/projects/sharpffmpeg/) and ffmpeg-sharp (http://code.google.com/p/ffmpeg-sharp/). First of all, I wanted to use ffmpeg-sharp as its LGPL and SharpFFmpeg is GPL. However, it had quite a few compile errors. Turns out it was written for the mono compiler, I tried compiling it with mono but couldn't figure out how. I then started to manually fix the compiler errors myself, but came across a few scary ones and thought I'd better leave those alone. So I gave up on ffmpeg-sharp.

Then I looked at SharpFFmpeg and it looks like what I want, all the functions P/Invoked for me. However its GPL? Both the AVCodec.cs and AVFormat.cs files look like ports of avcodec.c and avformat.c which I reckon I could port myself? Then not have to worry about licencing.

But I want to get this right before I go ahead and start coding. Should I:

  1. Write my own C++ library for interacting with ffmpeg, then have my C# program talk to the C++ library in order to play/convert videos etc.

OR

  1. Port avcodec.h and avformat.h (is that all i need?) to c# by using a whole lot of DllImports and write it entirely in C#?

First of all consider that I'm not great at C++ as I rarely use it but I know enough to get around. The reason I'm thinking #1 might be the better option is that most FFmpeg tutorials are in C++ and I'd also have more control over memory management than if I was to do it in c#.

What do you think? Also would you happen to have any useful links (perhaps a tutorial) for using FFmpeg?

2
  • possible duplicate of Solid FFmpeg wrapper for C#/.NET Commented Nov 26, 2013 at 2:17
  • Why don't you do something like C# -> DirectShow -> FFMPEG? This may be offtopic but also make sure you do not end up on ffmpeg.org/shame.html Commented Jan 3, 2016 at 13:23

7 Answers 7

34

The original question is now more than 5 years old. In the meantime there is now a solution for a WinRT solution from ffmpeg and an integration sample from Microsoft.

Sign up to request clarification or add additional context in comments.

3 Comments

that's only for windows, any news for a linux version?
also mention that's it's Windows 8 or above.
is this still up to date ? :)
28

a few other managed wrappers for you to check out

Writing your own interop wrappers can be a time-consuming and difficult process in .NET. There are some advantages to writing a C++ library for the interop - particularly as it allows you to greatly simplify the interface that the C# code. However, if you are only needing a subset of the library, it might make your life easier to just do the interop in C#.

7 Comments

Hi Mark! All I need is a wrapper that should expose one method: public static void Convert(string sourcePath, string targetPath, MediaType mediaType) (MediaType should refer to an enum that specifies the target filetype e.g. AVI, MP4, MP3 etc.), will it be a time consumer to develop a wrapper just for the conversion capabilities of ffmpeg (I just need basic conversion so my device can play some files of unsupported formats). Any clue? Can you please redirect me to where I can start from? Is it indeed that simple? Thanks!
isn't there some library like swig to auto-wrap the interop details for you?
@Shimmy if all you want to do is convert files, the easiest way to do that is with the ffmpeg command line.
@DavidChappelle That's what I ended up doing, I built a .NET wrapper with async progress reporting.
Can we download FFv1 dll for image conversion?
|
8

You can use this nuget package:

Install-Package Xabe.FFmpeg

I'm trying to make easy to use, cross-platform FFmpeg wrapper.

You can find more information about this at Xabe.FFmpeg

More info in documentation

Conversion is simple:

var conversion = await FFmpeg.Conversions.FromSnippet.ToMp4(Resources.MkvWithAudio, output);
await conversion.Start();

2 Comments

I inserted using Xabe.FFmpeg; but Resources is red in my IDE.
Resources are used only for tests in that project. You should pass there path to your file
6

GPL-compiled ffmpeg can be used from non-GPL program (commercial project) only if it is invoked in the separate process as command line utility; all wrappers that are linked with ffmpeg library (including Microsoft's FFMpegInterop) can use only LGPL build of ffmpeg.

You may try my .NET wrapper for FFMpeg: Video Converter for .NET (I'm an author of this library). It embeds FFMpeg.exe into the DLL for easy deployment and doesn't break GPL rules (FFMpeg is NOT linked and wrapper invokes it in the separate process with System.Diagnostics.Process).

3 Comments

This does invoke ffmpeg.exe though doesn't it - rather than using the dll.
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
@dingo_d Thanks for notice, I've added more details to the answer.
3

A solution that is viable for both Linux and Windows is to just get used to using console ffmpeg in your code. I stack up threads, write a simple thread controller class, then you can easily make use of what ever functionality of ffmpeg you want to use.

As an example, this contains sections use ffmpeg to create a thumbnail from a time that I specify.

In the thread controller you have something like

List<ThrdFfmpeg> threads = new List<ThrdFfmpeg>();

Which is the list of threads that you are running, I make use of a timer to Pole these threads, you can also set up an event if Pole'ing is not suitable for your application. In this case thw class Thrdffmpeg contains,

public class ThrdFfmpeg
{
    public FfmpegStuff ffm { get; set; }
    public Thread thrd { get; set; }
}

FFmpegStuff contains the various ffmpeg functionality, thrd is obviously the thread.

A property in FfmpegStuff is the class FilesToProcess, which is used to pass information to the called process, and receive information once the thread has stopped.

public class FileToProcess
{
    public int videoID { get; set; }
    public string fname { get; set; }
    public int durationSeconds { get; set; }
    public List<string> imgFiles { get; set; }
}

VideoID (I use a database) tells the threaded process which video to use taken from the database. fname is used in other parts of my functions that use FilesToProcess, but not used here. durationSeconds - is filled in by the threads that just collect video duration. imgFiles is used to return any thumbnails that were created.

I do not want to get bogged down in my code when the purpose of this is to encourage the use of ffmpeg in easily controlled threads.

Now we have our pieces we can add to our threads list, so in our controller we do something like,

        AddThread()
        {
        ThrdFfmpeg thrd;
        FileToProcess ftp;

        foreach(FileToProcess ff in  `dbhelper.GetFileNames(txtCategory.Text))`
        {
            //make a thread for each
            ftp = new FileToProcess();
            ftp = ff;
            ftp.imgFiles = new List<string>();
            thrd = new ThrdFfmpeg();
            thrd.ffm = new FfmpegStuff();
            thrd.ffm.filetoprocess = ftp;
            thrd.thrd = new   `System.Threading.Thread(thrd.ffm.CollectVideoLength);`

         threads.Add(thrd);
        }
        if(timerNotStarted)
             StartThreadTimer();
        }

Now Pole'ing our threads becomes a simple task,

private void timerThreads_Tick(object sender, EventArgs e)
    {
        int runningCount = 0;
        int finishedThreads = 0;
        foreach(ThrdFfmpeg thrd in threads)
        {
            switch (thrd.thrd.ThreadState)
            {
                case System.Threading.ThreadState.Running:
                    ++runningCount;


 //Note that you can still view data progress here,
    //but remember that you must use your safety checks
    //here more than anywhere else in your code, make sure the data
    //is readable and of the right sort, before you read it.
                    break;
                case System.Threading.ThreadState.StopRequested:
                    break;
                case System.Threading.ThreadState.SuspendRequested:
                    break;
                case System.Threading.ThreadState.Background:
                    break;
                case System.Threading.ThreadState.Unstarted:


//Any threads that have been added but not yet started, start now
                    thrd.thrd.Start();
                    ++runningCount;
                    break;
                case System.Threading.ThreadState.Stopped:
                    ++finishedThreads;


//You can now safely read the results, in this case the
   //data contained in FilesToProcess
   //Such as
                    ThumbnailsReadyEvent( thrd.ffm );
                    break;
                case System.Threading.ThreadState.WaitSleepJoin:
                    break;
                case System.Threading.ThreadState.Suspended:
                    break;
                case System.Threading.ThreadState.AbortRequested:
                    break;
                case System.Threading.ThreadState.Aborted:
                    break;
                default:
                    break;
            }
        }


        if(flash)
        {//just a simple indicator so that I can see
         //that at least one thread is still running
            lbThreadStatus.BackColor = Color.White;
            flash = false;
        }
        else
        {
            lbThreadStatus.BackColor = this.BackColor;
            flash = true;
        }
        if(finishedThreads >= threads.Count())
        {

            StopThreadTimer();
            ShowSample();
            MakeJoinedThumb();
        }
    }

Putting your own events onto into the controller class works well, but in video work, when my own code is not actually doing any of the video file processing, poling then invoking an event in the controlling class works just as well.

Using this method I have slowly built up just about every video and stills function I think I will ever use, all contained in the one class, and that class as a text file is useable on the Lunux and Windows version, with just a small number of pre-process directives.

Comments

0

Hey I looked into all of the provided solutions and did not find anything usable with ffmpeg versions up to date. I realy liked the Xabe approach.

For me the biggest problem was downloading ffmpeg based on platform. After I had it donwload I used it with cli wrap to execute functions same as if you would have used it via terminal

If it helps I released my implementation for the cross platform downloader

https://gist.github.com/Dominent/0c70566cde6d3178cec6adf7305a7e82

Comments

0

Faced with this same problem, and upset with the available options, I started on a tool myself called [FFcommander](https://github.com/harper-rhett/FFCommander). It allows you to speak to FFmpeg with C# by sending command line commands. It has an API for common features that abstract the commands completely. I plan to expand it in the future to cover much more ground but for the time being it should be really easy to develop off of as well.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.