Если у вас есть свободные циклы ЦП, вы можете извлекать из нескольких видео параллельно:parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Оле Танге,
Ответы:
156
Если этап кодирования JPEG слишком требователен к производительности, вы всегда можете сохранить несжатые кадры как изображения BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Это также имеет то преимущество, что не вызывает большей потери качества из-за квантования путем перекодирования в JPEG. (PNG также не имеет потерь, но кодирование обычно занимает гораздо больше времени, чем JPEG.)
Это приводит к тому, что на моей машине пропадает много кадров. Могу я сказать ffmpeg, чтобы он все рендерил?
Evi1M4chine 07
45
@ Evi1M4chine, просто удалите параметр -r, и все кадры будут извлечены
studioj
14
Я хотел бы добавить, что, хотя JPEG не очень сильно влияет на процессор, несжатые растровые изображения действительно очень тяжелы для хранилища, поэтому я сомневаюсь, что вы получите более высокую пропускную способность с BMP по сравнению с JPEG.
Маркус Мюллер
4
Чтобы извлечь все кадры:ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
fiatjaf
10
Вы имеете в виду ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png, правда? (вам не хватало -i)
Джошуа
68
Наткнулся на этот вопрос, так что вот быстрое сравнение. Сравните эти два разных способа извлечения одного кадра в минуту из видео длительностью 38 мин 07 сек:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1 мин. 36,0 29 сек.
Это занимает много времени, потому что ffmpeg анализирует весь видеофайл, чтобы получить желаемые кадры.
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0 мин. 4,689 сек.
Это примерно в 20 раз быстрее. Мы используем быстрый поиск для перехода к желаемому временному индексу и извлечения кадра, а затем вызываем ffmpeg несколько раз для каждого временного индекса. Обратите внимание, что -accurate_seekэто значение по умолчанию
, и убедитесь, что вы добавили -ssперед параметром ввода видео -i.
bcне родной пакет Ubuntu, а можно использовать Баш: let "i = $i * 60". Кстати - отличная идея
Гилад Майани
3
Хороший совет добавлял -ssраньше -i. В противном случае будет декодировано все видео, а ненужные кадры будут отброшены
MoustafaAAtta
2
Поскольку это вершина Google, я хотел бы отметить, что в 2018 году этот подход по-прежнему приносит дивиденды. Лучшим результатом кажется запуск одного ffmpegядра на ядро вашего хоста, что (для bmp) дает почти линейное улучшение скорости (пока вы не столкнетесь с каким-либо другим узким местом, например с диском).
Knetic
Это должен быть принятый ответ, поскольку вопрос касается «самого быстрого способа». Очевидно, вам нужно знать переменную выхода для цикла for с помощью ffprobe, который, я думаю, все еще быстрее по сравнению с другими методами.
iamprem
9
Если вы точно знаете, какие кадры извлекать, например 1, 200, 400, 600, 800, 1000, попробуйте использовать:
Я использую это с конвейером для монтажа Imagemagick, чтобы получить предварительный просмотр 10 кадров из любых видео. Очевидно номера кадров, которые вам нужно выяснить, используяffprobe
Я пытаюсь, ffmpeg -i "input URL" -vf fps=1/5 out%d.png где входной URL-адрес должен быть ссылкой https.
x2212,
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Кишан Вагела,
1
В моем случае мне нужны кадры хотя бы каждую секунду. Я использовал подход «искать к» выше, но мне было интересно, могу ли я распараллелить задачу. Здесь я использовал N процессов с подходом FIFO:
/unix/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
По сути, я раздвоил процесс с помощью &, но ограничил количество одновременных потоков до N.
В моем случае это улучшило подход «искать» с 26 до 16 секунд. Единственная проблема заключается в том, что основной поток не выходит обратно на терминал, так как stdout переполняется.
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Ответы:
Если этап кодирования JPEG слишком требователен к производительности, вы всегда можете сохранить несжатые кадры как изображения BMP:
Это также имеет то преимущество, что не вызывает большей потери качества из-за квантования путем перекодирования в JPEG. (PNG также не имеет потерь, но кодирование обычно занимает гораздо больше времени, чем JPEG.)
источник
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, правда? (вам не хватало-i
)Наткнулся на этот вопрос, так что вот быстрое сравнение. Сравните эти два разных способа извлечения одного кадра в минуту из видео длительностью 38 мин 07 сек:
1 мин. 36,0 29 сек.
Это занимает много времени, потому что ffmpeg анализирует весь видеофайл, чтобы получить желаемые кадры.
0 мин. 4,689 сек.
Это примерно в 20 раз быстрее. Мы используем быстрый поиск для перехода к желаемому временному индексу и извлечения кадра, а затем вызываем ffmpeg несколько раз для каждого временного индекса. Обратите внимание, что
-accurate_seek
это значение по умолчанию , и убедитесь, что вы добавили-ss
перед параметром ввода видео-i
.Обратите внимание, что лучше использовать
-filter:v -fps=fps=...
вместо,-r
поскольку последнее может быть неточным. Хотя билет отмечен как исправленный , у меня все же возникли некоторые проблемы, так что лучше перестраховаться.источник
bc
не родной пакет Ubuntu, а можно использовать Баш:let "i = $i * 60"
. Кстати - отличная идея-ss
раньше-i
. В противном случае будет декодировано все видео, а ненужные кадры будут отброшеныffmpeg
ядра на ядро вашего хоста, что (для bmp) дает почти линейное улучшение скорости (пока вы не столкнетесь с каким-либо другим узким местом, например с диском).Если вы точно знаете, какие кадры извлекать, например 1, 200, 400, 600, 800, 1000, попробуйте использовать:
Я использую это с конвейером для монтажа Imagemagick, чтобы получить предварительный просмотр 10 кадров из любых видео. Очевидно номера кадров, которые вам нужно выяснить, используя
ffprobe
.
Небольшое объяснение:
+
означает OR и*
AND\,
просто экранирует,
символ-vsync vfr -q:v 2
этого вроде не работает, но я не знаю почему - кто-нибудь?источник
Я попробовал. 3600 кадров за 32 секунды. ваш метод очень медленный. Вы должны попробовать это.
источник
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
где входной URL-адрес должен быть ссылкой https.ffmpeg -i file.mpg -vf fps=1 %d.jpg
В моем случае мне нужны кадры хотя бы каждую секунду. Я использовал подход «искать к» выше, но мне было интересно, могу ли я распараллелить задачу. Здесь я использовал N процессов с подходом FIFO: /unix/103920/parallelize-a-bash-for-loop/216475#216475
По сути, я раздвоил процесс с помощью &, но ограничил количество одновременных потоков до N.
В моем случае это улучшило подход «искать» с 26 до 16 секунд. Единственная проблема заключается в том, что основной поток не выходит обратно на терминал, так как stdout переполняется.
источник
Это сработало для меня
ffmpeg -i file.mp4 -vf fps=1 %d.jpg
источник