Обработка видеокадров в C # (FFMPEG медленно)

#c# #performance #video #ffmpeg

#c# #Производительность #Видео #ffmpeg

Вопрос:

Я пытаюсь извлечь кадры из видео mp4, чтобы обработать их.

А именно, в видеоизображении есть водяной знак / временная метка, которые я хочу использовать для автоматического объединения видео вместе. Дата создания видео недостаточна для этой задачи. введите описание изображения здесь

Также часть извлечения текста из видео с помощью AI в порядке.

Однако FFMPEG кажется ужасно медленным. исходное видео имеет разрешение 1080p / 60 кадров в секунду (примерно 1 ГБ на 5 минут видео).

До сих пор я пробовал два метода, используя Accord.Оболочка FFMPEG:

 public void GetVideoFrames(string path)
{
    using (var vFReader = new VideoFileReader())
    {
        // open video file
        vFReader.Open(path);
        // counter is beeing used to extract every xth frame (1 Frame per second)
        int counter = 0;
        for (int i = 0; i < vFReader.FrameCount;i   )
        {
            counter  ;
            if (counter <= 60)
            {
                _ = vFReader.ReadVideoFrame();
                continue;
            }
            else
            {
                Bitmap frame = vFReader.ReadVideoFrame();
                // Process Bitmap
            }
        }
    }
}
  

Другая попытка:

 for (int i = 0; i < vFReader.FrameCount;i = 60)
{
    // notice here, I am specifying which exact frame to extract
    Bitmap frame = vFReader.ReadVideoFrame(i);
    // process frame
}
  

Второй метод — это то, что я попробовал первым, и он совершенно неосуществим. По-видимому, FFMPEG выполняет новый поиск для каждого конкретного кадра, и, таким образом, операция занимает все больше и больше времени для каждого обработанного кадра.
Уже после 5 кадров для создания одного кадра требуется примерно 4 секунды.

По крайней мере, первый метод, похоже, не страдает от этой проблемы так сильно, но для получения кадра все равно требуется примерно 2 секунды. С такой скоростью я быстрее обрабатываю видео вручную.

Что-то не так с моим подходом? Также я скорее не хочу иметь решение, в котором мне нужно отдельно устанавливать сторонние библиотеки на целевой машине. Итак, если есть какие-либо альтернативы, я был бы рад попробовать их, но, похоже, практически все в stack overflow указывают либо на ffmpeg, либо на opencv.

Комментарии:

1. Разве вы не извлекаете каждый отдельный кадр в виде изображения? Почему вы ожидаете, что это будет быстро? Когда вы говорите «сшивать видео вместе», что именно вы имеете в виду?

2. нет. Метод 1 (быстрее) действительно извлекает каждый отдельный кадр и сбрасывает большинство из них. Конечно, это чертовски медленно. Вот почему я сначала использовал метод 2, ожидая, что ffmpeg будет выполнять поиск из последней известной позиции в потоке. Но, по-видимому, он ищет из позиции 0 каждый раз. Таким образом, метод 2 (должен) не вытягивать каждый отдельный кадр, но его путь намного медленнее.

3. Хорошо, значит, вы будете отображать их бок о бок или что-то в этом роде после их синхронизации?

4. Пару лет назад я реализовал такую функциональность с помощью DirectShow (пользовательские фильтры, написанные на C ). Это было очень быстро. Я думаю, вам следует переключиться на native, если вам нужна производительность.

5. Для этого вы можете использовать DirectShow или Media Foundation. Это собственные технологии Windows. Вам не нужно беспокоиться о декодировании видеоформатов и прочем. Это будет сделано Windows за вас. Вы можете получить доступ к данным видеокадров, выполнить поиск по вашим видео, закодировать видео обратно и т.д.

Ответ №1:

Я думаю, что проблема не в FFmpeg, а в том, что оболочка Accord выполняет поиск. Я бы рекомендовал использовать ffmpeg непосредственно за один проход для извлечения кадров, поскольку у него есть опции для извлечения только ключевых кадров или каждых X кадров (или вы можете просто использовать встроенные временные метки видео …). Но если вы хотите продолжить свой путь, то, возможно, рассмотрите возможность передачи нужного индекса кадра вместо цикла for — это должно быть быстрее, и, возможно, вы сможете его распараллелить.

Но будет намного быстрее сделать все это в отдельном процессе ffmpeg.