Используете FFmpeg в .net?

Итак, я знаю, что это довольно большая проблема, но я хочу написать базовый проигрыватель/конвертер фильмов на С#, используя библиотеку FFmpeg. Однако первое препятствие, которое мне нужно преодолеть, — это обертывание библиотеки FFmpeg в C#. Я скачал ffmpeg, но не смог его скомпилировать в Windows, поэтому скачал для себя предварительно скомпилированную версию. Хорошо, круто. Затем я начал искать обертки C#.

Я осмотрелся и нашел несколько оболочек, таких как SharpFFmpeg (http://sourceforge.net/projects/sharpffmpeg/) и ffmpeg-sharp (http://code.google.com/p/ffmpeg-sharp/). Прежде всего, я хотел использовать ffmpeg-sharp, так как это LGPL, а SharpFFmpeg — это GPL. Тем не менее, у него было довольно много ошибок компиляции. Оказывается, он был написан для компилятора моно, я пытался скомпилировать его с помощью моно, но не мог понять, как это сделать. Затем я начал вручную исправлять ошибки компилятора, но наткнулся на несколько страшных и подумал, что лучше оставить их в покое. Поэтому я отказался от ffmpeg-sharp.

Затем я посмотрел на SharpFFmpeg, и он выглядит так, как я хочу, все функции P/Invoked для меня. Однако это GPL? Оба файла AVCodec.cs и AVFormat.cs выглядят как порты avcodec.c и avformat.c, которые, я думаю, я мог бы портировать сам? Тогда не придется беспокоиться о лицензии.

Но я хочу получить это право, прежде чем я продолжу и начну программировать. Нужно ли мне:

  1. Напишите мою собственную библиотеку C++ для взаимодействия с ffmpeg, затем пусть моя программа C# общается с библиотекой C++, чтобы воспроизводить/конвертировать видео и т. д.

OR

  1. Перенести avcodec.h и avformat.h (это все, что мне нужно?) на С#, используя множество DllImports, и полностью написать его на С#?

Прежде всего учтите, что я не силен в C++, так как редко им пользуюсь, но знаю достаточно, чтобы обойти его. Причина, по которой я думаю, что № 1 может быть лучшим вариантом, заключается в том, что большинство руководств по FFmpeg написаны на С++, и у меня также будет больше контроля над управлением памятью, чем если бы я делал это на С#.

Что вы думаете? Также у вас есть какие-нибудь полезные ссылки (возможно, учебник) по использованию FFmpeg?


person daniel    schedule 27.03.2010    source источник
comment
возможный дубликат оболочки Solid FFmpeg для C#/.NET   -  person Nikolay Shmyrev    schedule 26.11.2013
comment
Почему бы вам не сделать что-то вроде C# -> DirectShow -> FFMPEG? Это может быть оффтопом, но также убедитесь, что вы не попали на ffmpeg.org/shame.html.   -  person Adam Baxter    schedule 03.01.2016


Ответы (5)


Исходному вопросу уже более 5 лет. Тем временем теперь есть решение для решения WinRT от ffmpeg и образец интеграции от Microsoft.

person tobltobs    schedule 15.06.2015
comment
это только для Windows, есть новости для Linux версии? - person Christo S. Christov; 01.06.2016
comment
также упомяните, что это Windows 8 или выше. - person CyberFox; 11.10.2016
comment
это все еще актуально? :) - person AlexandreG; 02.12.2018

несколько других управляемых оболочек, которые вы можете проверить

Написание собственных оболочек взаимодействия в .NET может быть трудоемким и трудоемким процессом. Есть некоторые преимущества в написании библиотеки C++ для взаимодействия, особенно потому, что она позволяет значительно упростить интерфейс, чем код C#. Однако, если вам нужно только подмножество библиотеки, может быть проще выполнить взаимодействие на C#.

person Mark Heath    schedule 29.03.2010
comment
Привет Марк! Все, что мне нужно, это оболочка, которая должна предоставлять один метод: public static void Convert(string sourcePath, string targetPath, MediaType mediaType) (MediaType должен ссылаться на перечисление, указывающее тип целевого файла, например AVI, MP4, MP3 и т. д.), будет ли потребитель времени разрабатывать оболочку только для возможностей преобразования ffmpeg (мне просто нужно базовое преобразование, чтобы мое устройство могло воспроизводить некоторые файлы неподдерживаемых форматов). Любая подсказка? Не могли бы вы перенаправить меня туда, откуда я могу начать? Это действительно так просто? Спасибо! - person Shimmy Weitzhandler; 30.08.2011
comment
разве нет какой-нибудь библиотеки, например swig, для автоматического переноса деталей взаимодействия? - person rogerdpack; 07.08.2013
comment
@Shimmy, если все, что вы хотите сделать, это конвертировать файлы, самый простой способ сделать это — с помощью командной строки ffmpeg. - person David Chappelle; 16.01.2014
comment
@DavidChappelle Вот что я в итоге сделал: я создал оболочку .NET с асинхронными отчетами о ходе выполнения. - person Shimmy Weitzhandler; 17.01.2014
comment
Можем ли мы загрузить FFv1 dll для преобразования изображений? - person thevan; 25.04.2015
comment
У FFMpeg-Sharp нет API для записи видео. - person Dmitri Nesteruk; 26.12.2019

Скомпилированный под GPL ffmpeg можно использовать из программы, не относящейся к GPL (коммерческий проект), только если он вызывается в отдельном процессе как утилита командной строки; все оболочки, связанные с библиотекой ffmpeg (включая Microsoft FFMpegInterop), могут использовать только сборку LGPL ffmpeg.

Вы можете попробовать мою оболочку .NET для FFMpeg: Video Converter для .NET (я автор этой библиотеки). Он встраивает FFMpeg.exe в DLL для простоты развертывания и не нарушает правила GPL (FFMpeg НЕ связан, и оболочка вызывает его в отдельном процессе с System.Diagnostics.Process).

person Vitaliy Fedorchenko    schedule 08.09.2013
comment
Это вызывает ffmpeg.exe, хотя и не использует dll. - person James; 22.04.2014
comment
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. – Из обзора - person dingo_d; 03.01.2016
comment
@dingo_d Спасибо за внимание, я добавил в ответ больше деталей. - person Vitaliy Fedorchenko; 03.01.2016

Вы можете использовать этот пакет nuget:

Install-Package Xabe.FFmpeg

Я пытаюсь сделать простую в использовании кроссплатформенную оболочку FFmpeg.

Дополнительную информацию об этом можно найти на странице Xabe.FFmpeg.

Дополнительные сведения см. в документации.

Преобразование простое:

var conversion = await FFmpeg.Conversions.FromSnippet.ToMp4(Resources.MkvWithAudio, output);
await conversion.Start();
person Tomasz Żmuda    schedule 27.09.2017

Решение, подходящее как для Linux, так и для Windows, состоит в том, чтобы просто привыкнуть к использованию консольного ffmpeg в вашем коде. Я складываю потоки, пишу простой класс контроллера потока, после чего вы можете легко использовать любую функциональность ffmpeg, которую хотите использовать.

В качестве примера, это содержит разделы, использующие ffmpeg для создания миниатюры из указанного мной времени.

В контроллере потока у вас есть что-то вроде

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

Это список потоков, которые вы запускаете, я использую таймер для поля этих потоков, вы также можете настроить событие, если полирование не подходит для вашего приложения. В этом случае класс 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();
        }
    }

Помещение ваших собственных событий в класс контроллера работает хорошо, но в работе с видео, когда мой собственный код фактически не выполняет какую-либо обработку видеофайла, поляризация с последующим вызовом события в управляющем классе работает так же хорошо.

Используя этот метод, я постепенно создал почти все функции видео и фото, которые, я думаю, когда-либо буду использовать, все они содержатся в одном классе, и этот класс в виде текстового файла можно использовать в версиях для Lunux и Windows с небольшим числом. предварительных директив.

person Bob    schedule 15.07.2016