Самый быстрый способ извлечь определенный кадр из видео (PHP/ffmpeg/ что угодно)

У меня есть веб-страница, на которой (помимо прочего) необходимо извлечь определенный кадр из видео, загруженного пользователем. Пользователь ищет в проигрывателе определенную часть.mp4, затем нажимает кнопку, и ajax-вызов запускается на php-скрипт, который берет.mp4 и точное время из видео, и использует его для извлечения рамка "миниатюра".

Мое текущее решение использует php exec команда:

exec("ffmpeg -i $videoPath -ss $timeOffset -vframes 1 $jpgOutputPath");

... который прекрасно работает, за исключением того, что он медленный, как патока. Я предполагаю, что ffmpeg - это слишком много для работы, и я мог бы добиться большего успеха, используя базовые библиотеки или что-то в этом роде... однако я понятия не имею, как это сделать.

В идеале я не хочу устанавливать что-либо, что требует реального "процесса установки"... то есть, удаление исполняемого файла в папку с моим веб-приложением - это нормально, но я бы предпочел не запускать установщик. Кроме того, решение должно быть в состоянии работать на Mac, Linux и Windows (хотя Linux является главным приоритетом).

Что я могу сделать, чтобы ускорить этот процесс?

Благодарю.

2 ответа

Решение

Конечно, вы можете написать код на C/C++ и связать его с -lav*, в основном создав упрощенную версию ffmpeg только для извлечения фреймов, и, возможно, даже сделайте это как расширение php (также я бы не стал запускать его как тот же пользователь не говоря уже о том же процессе). Но маловероятно, что результат будет быстрее, потому что вы только избежите некоторого разветвления и накладных расходов на настройку, но вашей вероятной проблемой на самом деле является декодирование, которое все равно будет таким же.

Вместо этого вы должны сначала изучить использование ffmpeg в режиме быстрого поиска (или в быстром / точном гибридном режиме). В их вики говорится о быстром поиске:

Параметр -ss должен быть указан до -i:

ffmpeg -ss 00:03:00 -i Underworld.Awakening.avi -frames: v 1 out1.jpg

В этом примере будет создан один кадр изображения (out1.jpg) где-то на третьей минуте от начала фильма. Ввод будет проанализирован с использованием ключевых кадров, что очень быстро. Недостатком является то, что он также завершит поиск на некотором ключевом кадре, не обязательно находящемся в указанное время (00:03:00), поэтому поиск будет не таким точным, как ожидалось.

Быстрый поиск менее точен, но чертовски быстрее, поскольку ffmpeg фактически не нужно декодировать (большую часть) фильма во время поиска, в то время как быстрый / точный гибридный режим является хорошим компромиссом. Прочитайте вики-страницу для всех доступных вариантов.

Изменить 14/06/10:

Начиная с FFmpeg 2.1, при транскодировании с использованием ffmpeg (т. Е. Без потокового копирования), -ss теперь точен, даже если используется как опция ввода. Предыдущее поведение можно восстановить с помощью опции -noaccurate_seek. (источник)

Таким образом, в версии 2.1+ "гибридный" поиск больше не требуется для получения точных результатов, когда речь идет о перекодировании (и сохранении в .jpeg это перекодировать). Достаточно сделать обычный быстрый поиск (-ss ... -i ...) вместо медленного поиска (-i ... -ss ...).

В C/C++ с использованием библиотек ffmpeg напрямую (как упомянул nmaier, но не предоставил ресурсы для): у меня была такая же проблема, и мне потребовалось много работы, но теперь я реализовал функцию извлечения кадров в C++ напрямую, используя библиотеки ffmpeg (в рамках QT Framework, но это все равно должно помочь для простого C++).

См. функцию QImage Video::ffmpegLib_captureAt(const int процент, const int ofDuration) в моем проекте Video simili дубликат файла Video.cpp, это должен быть очевидный пример: https://github.com/theophanemayaud/video-simili-duplicate-cleaner/blob/master/QtProject/app/video.cpp

Другие вопросы по тегам