ffmpeg извлекает изображения из нескольких выбранных моментов времени

744
Jakob Winter

У меня есть видеофайл, и мне нравится извлекать одно изображение из (около 1500) определенных временных точек (expl. -Ss 00:50, ss 00:67, ss: 01:70 ...)

Есть ли способ сделать это? Я попытался использовать эту команду:

ffmpeg.exe -ss 00:50 -i all.avi -t 00:00:01 -vframes 1 images-filename_%03d.png 

Это прекрасно работает для одной картинки, но есть ли способ сделать это для такого количества конкретных временных точек?

У кого-нибудь есть совет?

1

2 ответа на вопрос

1
slhck

Добавьте несколько временных меток в качестве параметров для selectфильтра.

ffmpeg -i input.mp4 -filter:v \ "select='eq(t\,1.5)+eq(t\,10)+eq(t\,20)'" \ -vsync drop images-filename_%03d.png 

Если фильтр оценивается как true, он выводит кадр, поэтому добавление проверок, сравнивающих временную метку кадра tс определенной временной меткой в ​​секундах (например, 1.5), даст вам все кадры в этих временных метках.

Я добавил [улучшенную версию] (https://superuser.com/a/1330042/598963) этого ответа. Leon 5 лет назад 0
Интересный подход! В последние годы не очень много работал с частичной частотой кадров, но они вызывают много проблем. slhck 5 лет назад 0
1
Leon

Этот ответ улучшает @slhck «s ответ, который может не работать в некоторых ситуациях.

Одна тонкость в выборе кадров по (приблизительной) временной метке заключается в том, что фактическая временная метка кадра может не быть точно равна требуемой временной метке. Например, в видео с частотой кадров 23,98 (24000/1001) нет кадра с отметкой времени 1,0 - ближайший кадр имеет значение отметки времени 1,001.

Выражение eq(t, specific_timepoint)оценивается как истинное, только если tоно точно равно specific_timepoint. Поэтому он не сможет выбрать кадр в ситуации, описанной выше. В качестве обходного пути мы можем выбрать первый кадр, следующий сразу за желаемой временной меткой, т.е. кадр, значение временной метки которого больше или равно указанному моменту времени, в то время как метка времени его предыдущего кадра была меньше указанного момента времени. Выражение выбора для одного момента времени будет

lt(prev_pts * TB,timepoint) * gte(pts * TB,timepoint)

Обратите внимание, что я намеренно не использовал более короткий вариант

between(timepoint, prev_pts*TB, pts*TB)

что эквивалентно

lte(prev_pts * TB,timepoint) * gte(pts * TB,timepoint)

поскольку он выберет два последовательных кадра, когда значение метки времени (первого) одного из них точно соответствует указанному значению момента времени.

Пример выбора фреймов, соответствующих или сразу после временных точек 1.5, 10 и 20:

ffmpeg -i input.mp4 -filter:v \ "select='lt(prev_pts*TB\,1.5)*gte(pts*TB\,1.5) \ +lt(prev_pts*TB\,10)*gte(pts*TB\,10) \ +lt(prev_pts*TB\,20)*gte(pts*TB\,20)'" \ -vsync drop images-filename_%03d.png 

Похожие вопросы