Извлечение индекса ключевых кадров из видео с помощью ffmpeg

17

Я использую ffmpeg для извлечения ключевых кадров из видео. Это команда:

ffmpeg -i test2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 160x90 -f image2 thumbnails-%02d.jpeg

Как я могу получить индекс каждого ключевого кадра, извлеченного в видео? Например, для первого I-кадра индекс будет равен 0, для второго - 24 и т. Д.

Фатен Халифа
источник
возможно дубликат superuser.com/questions/669716/...
user236012
Изучите использование ffprobe, а затем обработайте вывод, чтобы получить индекс?
dstob
@dstob Не могли бы вы объяснить, что вы имеете в виду? как я новичок в ffmpeg.
Фатен Халифа
@LordNeckbeard Номер кадра в видеокадрах, напр. первый кадр видео будет с индексом 0 Я хочу знать индекс каждого ключевого кадра в видеокадрах.
Фатен Халифа
Вы хотите, чтобы номер кадра был напечатан на миниатюре (на самом изображении)?
ллоган

Ответы:

21

Как упомянуто @dstob, вы можете использовать, ffprobeчтобы получить I-кадры и связанную с ними информацию. ffprobeпоставляется с некоторыми статическими сборками на странице загрузки и может быть также собран из исходного кода.

Предполагается, что вы работаете в Linux / Unix:

Извлечь кадры и типы кадров

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1

Команда grepфильтрует Iв них строки и подсчитывает их индекс (используя -nопцию). Команда cutвыбирает только первый столбец выходных данных (индекс). Обратите внимание, что этот индекс основан на 1, а не на 0.

Переименовать выходные файлы на основе индекса

Вы можете фактически передать эти индексы в список:

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1 > frame_indices.txt

Затем составьте список всех миниатюр:

ls -1 thumbnails*.jpeg > thumbnails.txt

Затем вставьте эти два вместе:

paste thumbnails.txt frame_indices.txt > combined.txt

Список теперь содержит имя миниатюры и индекс. Выполните переименование на основе этого:

while read -r thumbnail index; do
  newIndex=$(echo $index - 1 | bc) # subtract 1 from the index
  mv -- "$thumbnail" "thumbnail-$newIndex.jpeg"  # rename file
done < combined.txt

Выше будет переименовать thumbnail-01.jpegв thumbnail-0.jpeg. Обратите внимание, что в выходном индексе нет нуля. Если вы хотите добавить к нулю, скажем, 5 цифр, используйте printf:

newIndex=$(printf '%05d' $(echo $index - 1 | bc))

В Windows вы бы сделали то же самое, ffprobeно по-разному проанализировали результат. Не знаю, как выполнить переименование там, хотя.

slhck
источник
Эта ошибка отображается: «grep» не распознается как внутренняя или внешняя команда, работающая программа или пакетный файл.
Faten Khalifa
2
Это потому что ты на Windows. Как я уже сказал, этот ответ предполагает Linux или Unix. Вы не были более конкретны в своем вопросе. Вы можете добиться того же в Windows, используя Cygwin или аналогичные слои GNU / Linux для Windows.
Slhck
Это огромная помощь, спасибо. Одно исправление: я думаю, что показатели в вашей первой команде отключены в три раза, потому что для каждой строки есть [FRAME]строка и строка. [/FRAME]pict_type
Джек О'Коннор
2
@ JackO'Connor Если вы используете -of csvопцию для, в кадре будет только одна строка ffprobe. Однако вы описываете формат вывода по умолчанию.
Slhck
0

Если вы хотите использовать FFMPEG, как указано ранее, вы можете перечислить весь или частичный список, а также создать jpg со следующими:

ffmpeg.exe \
  -i "C:\Users\UserName\Desktop\jpegs and list\VideoName.mp4" \
  -t 15 \
  -vf select="eq(pict_type\,PICT_TYPE_I)" \
  -vsync 2 \
  -s 160x90 \
  -f image2 thumbnails-%02d.jpeg \
  -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"

Удалить -t 15без ограничения по времени или изменить в соответствии с костюмом. Удалить -s 160x90 -f image2 thumbnail-%02d.jpegили изменить в соответствии с уменьшением миниатюр.

Budman1
источник
В Windows 7 CMD это не удается в \. Изменение \ на ^ вызывает ошибку в: I ". У вас есть версия, которая работает в Windows?
ChrisJJ