web-dev-qa-db-ja.com

.netでFFmpegを使用していますか?

だから私はそれがかなり大きな課題であることを知っていますが、FFmpegライブラリを使用してc#で基本的なムービープレーヤー/コンバーターを書きたいです。ただし、私が克服しなければならない最初の障害は、c#でFFmpegライブラリをラップすることです。 ffmpegをダウンロードしましたが、Windowsでコンパイルできなかったため、プリコンパイル済みバージョンをダウンロードしました。 Ok awesome。その後、C#ラッパーを探し始めました。

私は周りを見て、SharpFFmpeg( http://sourceforge.net/projects/sharpffmpeg/ )やffmpeg-sharp( http://code.google .com/p/ffmpeg-sharp / )。まず、LGPLとしてffmpeg-sharpを使用し、SharpFFmpegはGPLでしたかった。ただし、かなりの数のコンパイルエラーがありました。モノコンパイラ用に作成されたことが判明したため、モノでコンパイルしようとしましたが、方法がわかりませんでした。それから私は自分でコンパイラーのエラーを手動で修正し始めましたが、いくつかの恐ろしいものに出くわし、それらを放っておいたほうがいいと思いました。だから私はffmpeg-sharpをあきらめた。

次に、SharpFFmpegを見ると、P/Invokedのすべての機能が必要なように見えます。しかし、そのGPL? AVCodec.csファイルとAVFormat.csファイルはどちらも、自分で移植できると考えているavcodec.cとavformat.cのポートのように見えますか?その後、ライセンスを心配する必要はありません。

しかし、先に進んでコーディングを開始する前に、これを正しく取得したいと思います。したほうがいい:

  1. Ffmpegとやり取りするための独自のC++ライブラリを作成し、ビデオなどを再生/変換するためにC#プログラムとC++ライブラリとの対話を行います。

OR

  1. Avcodec.hおよびavformat.h(必要なのはそれだけですか?)をDllImportsを使用してC#に移植し、完全にC#で記述しますか?

まず、C++を使うことはめったにないので、私はC++が得意でないことを考慮してください。私が#1がより良い選択肢であると考えている理由は、ほとんどのFFmpegチュートリアルがC++であり、C#で行うよりもメモリ管理をより細かく制御できるからです。

どう思いますか?また、FFmpegを使用するための便利なリンク(おそらくチュートリアル)がありますか?

61
daniel

元の質問は5年以上前です。その間、 ffmpeg のWinRTソリューションと Microsoft の統合サンプルのソリューションがあります。

29
tobltobs

あなたがチェックアウトするためのいくつかの他のマネージドラッパー

独自の相互運用ラッパーを作成することは、.NETで時間がかかり、困難なプロセスになる可能性があります。相互運用のためにC++ライブラリを記述することには、特にC#コードのインターフェイスを大幅に簡素化できるという利点があります。ただし、ライブラリのサブセットのみが必要な場合は、C#で相互運用するだけで済む場合があります。

23
Mark Heath

GPLでコンパイルされたffmpegは、コマンドラインユーティリティとして別のプロセスで呼び出された場合にのみ、非GPLプログラム(商用プロジェクト)から使用できます。 ffmpegライブラリ(MicrosoftのFFMpegInteropを含む)にリンクされているすべてのラッパーは、ffmpegのLGPLビルドのみを使用できます。

FFMpeg用の.NETラッパーを試してみてください: Video Converter for .NET (私はこのライブラリの作成者です)。 FFMpeg.exeをDLLに簡単に展開でき、GPLルールに違反しません(FFMpegはリンクされておらず、ラッパーはSystem.Diagnostics.Processを使用して別のプロセスで呼び出します)。

5

このnugetパッケージを使用できます:

Install-Package Xabe.FFmpeg

使いやすいクロスプラットフォームFFmpegラッパーを作成しようとしています。

これについての詳細は Xabe.FFmpeg で見つけることができます。

詳細は ドキュメント

変換は簡単です:

IConversionResult result = await Conversion.ToMp4(Resources.MkvWithAudio, output).Start();
5
Tomasz Żmuda

LinuxとWindowsの両方で実行可能なソリューションは、コードでコンソールffmpegを使用することに慣れることです。スレッドを積み重ねて、単純なスレッドコントローラークラスを作成すると、ffmpegの機能を使用したいときに簡単に利用できます。

例として、これには、ffmpegを使用して、指定した時間からサムネイルを作成するセクションが含まれます。

スレッドコントローラーには次のようなものがあります

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

実行中のスレッドのリストです。これらのスレッドをポーリングするためにタイマーを使用します。Pole'ingがアプリケーションに適さない場合は、イベントを設定することもできます。この場合、Thrdクラスのthrdffmpegには、

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

FFmpegStuffにはさまざまなffmpeg機能が含まれています。thrdは明らかにスレッドです。

FfmpegStuffのプロパティは、FilesToProcessクラスです。これは、呼び出されたプロセスに情報を渡し、スレッドが停止すると情報を受け取るために使用されます。

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(データベースを使用)は、スレッド化されたプロセスに、データベースから取得したビデオを使用するよう指示します。 fnameは、FilesToProcessを使用する関数の他の部分で使用されますが、ここでは使用されません。 durationSeconds-ビデオの継続時間を収集するスレッドによって埋められます。 imgFilesは、作成されたサムネイルを返すために使用されます。

この目的が簡単に制御できるスレッドでffmpegの使用を促進することである場合、コードに行き詰まりたくありません。

これでスレッドリストに追加できる部分ができたので、コントローラーで次のようなことを行います。

        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();
        }

スレッドをポーリングするのは簡単なタスクになりました。

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();
        }
    }

独自のイベントをコントローラークラスに入れることはうまく機能しますが、ビデオ作業では、自分のコードが実際にビデオファイル処理を行っていない場合、ポーリングしてから制御クラスのイベントを呼び出すことも同様に機能します。

このメソッドを使用して、私はゆっくりとすべてのビデオと静止画の機能を構築しました。これはすべて、1つのクラスに含まれ、そのクラスはテキストファイルとしてLunuxおよびWindowsバージョンで使用できますが、ほんの少しだけです前処理ディレクティブの。

2
Bob

ここから簡単なffmpegラッパー.NETを試すことができます: http://ivolo.mit.edu/post/Convert-Audio-Video-to-Any-Format-using-C.aspx

2
Ilya