Как кодировать / декодировать видео с помощью C #? - PullRequest
13 голосов
/ 02 декабря 2009

Немного предыстории, мне было поручено исправить несколько «мелких» ошибок и поддерживать это решение для потоковой передачи видео по сети между двумя экземплярами нашего приложения. Решение было написано кем-то, кого уже нет, поэтому в коде есть некоторая загадка, а также некоторые действительно забавные подводные камни. Решение было написано с использованием ffmpeg с кодом C ++, написанным, чтобы обернуть код, связанный с кодированием / декодированием, а также часть потокового кода. Затем этот C ++ был обернут SWIG, чтобы он мог взаимодействовать с C # и передавать видеокадры туда, где они отображаются, используя VideoRendererElement , который находится в элементе управления WPF. Основная причина, по которой кадры передаются, заключается в том, что у нас есть несколько пользовательских протоколов, которые нам нужны для отправки видеоданных, и те, которые записаны с использованием C #, поэтому, когда видеокадры передаются, мы оборачиваем их в наши собственные пакеты и отправляем их по проводам , Это решение работает, и мы можем передавать потоковое видео, используя наши собственные протоколы, хотя обслуживать и работать с ним - это просто кошмар.

Мой вопрос, есть ли лучший способ сделать это? Я ищу способы работать на более низком уровне с видеоданными (в C #), чтобы я мог взять видеокадры и упаковать их в наши собственные пакеты и отправить их, чтобы иметь возможность получать и восстанавливать видео на Другая сторона. ffmpeg, кажется, является распространенным решением, но я столкнулся с большим количеством проблем с ним, и проблема GPL / LGPL, я думаю, является проблемой.

Основной поток, которого я хочу достичь, видеофайл -> кодировать -> завернуть в пакет -> отправить по проводу по протоколу X -> получить видеоданные из пакета -> декодировать -> отобразить / сохранить на диск

Ответы [ 7 ]

6 голосов
/ 03 декабря 2009

DirectShow - ваш друг. DirectShow - это низкоуровневый слой, используемый большинством оконных «мультимедийных» приложений, таких как Media Player, Audio Encoders и т. Д.

Даже если эта библиотека была создана для собственных разработчиков, вы можете получить к ней доступ из управляемого мира благодаря DirectShow.net. http://directshownet.sourceforge.net Это хорошо известная и стабильная управляемая оболочка для DirectShow.

Единственное, что вам нужно сделать, это немного изучить DirectShow, чтобы понять концепцию графов и фильтров, а затем создать свои собственные фильтры и графы для использования возможностей DirectShow!

4 голосов
/ 03 декабря 2009

В нашем проекте мы используем Microsoft Expression Encoder. Это не бесплатно. Он может конвертировать видео в разные форматы и размеры, извлекать эскизы и т. Д.

Вот пример:

using Microsoft.Expression.Encoder;

//...
//skiped
//...

MediaItem mediaItem = new MediaItem(videoToEncode.SourceFilePath);
mediaItem.ApplyPreset(PresetFilePath);

Job job = new Job();
job.ApplyPreset(PresetFilePath); // path to preset file, where settings of bit-rate, codec etc
job.MediaItems.Add(mediaItem);

job.EncodeProgress += OnProgress;
job.EncodeCompleted += EncodeCompleted;

job.DefaultMediaOutputFileName = "{OriginalFilename}.encoded.{DefaultExtension}";
job.CreateSubfolder = false;

job.OutputDirectory = videoToEncode.EncodedFilePath;
job.Encode();
2 голосов
/ 03 декабря 2009

У меня были всевозможные проблемы с использованием ffmpeg, обернутого в DLL. Мой видео проект был довольно прост - мне просто нужно было конвертер, чтобы взять один эскиз из WMV.

Попробовав только то, что вы описали, я решил просто скопировать двоичный файл ffmpeg.exe в мой проект как внешнюю библиотеку. это также аккуратно решает любые проблемы с лицензированием кода, AFAIK ...

        Guid temp = Guid.NewGuid();

        // just throw our ffmpeg commands at cmd.exe
        System.Diagnostics.ProcessStartInfo psi = 
            new System.Diagnostics.ProcessStartInfo("cmd.exe");

        psi.WorkingDirectory = Page.MapPath(@"~\Lib\ffmpeg.rev12665");

        psi.UseShellExecute = false;
        psi.RedirectStandardError = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardInput = true;

        System.Diagnostics.Process ps = System.Diagnostics.Process.Start(psi);

        StreamReader outputReader = ps.StandardOutput;
        StreamReader errorReader = ps.StandardError;
        StreamWriter inputWrite = ps.StandardInput;

        // uses extra cheap logging facility
        inputWrite.WriteLine("echo \"Ripping " + copiedFile + " " + 
            temp.ToString() + "\" >> log.txt");

        inputWrite.WriteLine("ffmpeg.exe -i \"" + copiedFile + 
            "\" -f image2 -vframes 1 -y -ss 2 tmp\\" + temp.ToString() + 
            ".jpg");

        inputWrite.WriteLine("exit");

        ps.WaitForExit(3000);

        if (ps.HasExited)
        {
            string thumbFile = Page.MapPath(@"~\Lib\ffmpeg.rev12665\tmp") + 
                @"\" + temp.ToString() + ".jpg";
            // ...
        }

Ваша командная строка ffmpeg может сильно отличаться от моего примера, но это самый стабильный способ, который я нашел для получения миниатюр. Другие вещи, которые я нашел в Интернете относительно ffmpeg, в частности, не имели этого решения (на основе cmd.exe), но это единственное, с чем я хорошо работал. Удачи!

0 голосов
/ 03 декабря 2009

Мы конвертируем видеофайлы в различные выходные форматы (avi, flv, mp4, divx и т. Д.) Для нашего приложения медиаданных. Поскольку мы всегда работали с CLI-приложениями для конвертации медиаданных (поговорим о растеризации файлов EPS в JPG с использованием ImageMagick / GS), мы в значительной степени полагались на FFMPEG-CLI.

В нашей специальной среде мы использовали «тупые» UNIX-серверы в качестве машин преобразования (здесь установлены только библиотеки sshd, ffmpeg, misc. Ffmpeg и samba). Они управляются через CLI PuTTy из C # (веб-сервис WCF) через команды SSH для выполнения реального преобразования.

Вызов ffmpeg происходит через ssh и специализируется для каждого TransformationType. CLI-шпатлевка запускается через пространство имен System.Diagnostics.Process в C #, события для выходных сообщений и сообщений об ошибках обрабатываются для целей ведения журнала.

Интернет предоставляет множество ресурсов по таким вопросам, как «Как я могу конвертировать mpg в flv с помощью ffmpeg?», Небольшое исследование поможет вам. Поскольку речь идет о приложении, защищенном авторским правом, я не могу опубликовать полные выдержки из кода. Но это должно дать вам архитектурное представление о надежном и быстром бэкенде кодирования видео с использованием C #.

0 голосов
/ 03 декабря 2009

Вы также можете взглянуть на различные Microsoft Windows Media SDK, которые доступны для загрузки. В проекте несколько лет назад мы использовали SDK для Windows Media Format для извлечения миниатюр из загруженного видео. Эти SDK также имеют пример кода .NET.

0 голосов
/ 03 декабря 2009

Я написал VideoRendererElement, когда не было эффективных способов рендеринга видео в WPF (v3.0). Он использует некоторые хакеры, чтобы заставить его работать.

Если вы хотите немного упростить вещи, отбросьте VRE и используйте InteropBitmap для рендеринга (WriteableBitmap в порядке, но не так эффективно). Также удалите SWIG и сделайте свою C ++ dll CLI / C ++ dll, так что вы можете напрямую общаться с C ++ из C # (и наоборот).

Другой путь, по которому вы можете пойти, - это просто создать исходный фильтр DirectShow, содержащий ваши вещи для транспорта / декодирования, и вы можете использовать что-то вроде моего WPF MediaKit , чтобы он отображался в WPF (он использует D3DImage. 0 хаков).

Кроме того, не бойтесь LGPL. Пока вы храните его в своей собственной DLL и не меняете источник, вы находитесь в пределах лицензионных ограничений.

0 голосов
/ 02 декабря 2009

Что вы можете попробовать посмотреть на это SharpFFmpeg . Он лицензирован с использованием GPL, хотя вы можете увидеть, как они написали свою оболочку, и вы сможете написать свой собственный или получить идеи о том, как исправить ваше текущее решение.

Редактировать:

На code.google.com есть похожая оболочка ffmpeg-sharp , которая использует LGPL - вы можете использовать ее в коммерческих приложениях. Я подозреваю, что обе эти обертки делают одно и то же, хотя SharpFFmpeg старше и, вероятно, более зрелый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...