#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.