Использование ffmpeg для извлечения нескольких изображений из видео и получения временных меток извлеченных изображений

#video #ffmpeg

#Видео #ffmpeg

Вопрос:

Я использую ffmpeg для извлечения одного кадра (в формате jpeg) каждые пять минут из видео и передачи выходных данных с консоли в текстовый файл, чтобы получить точные временные метки извлеченных кадров.

Команда, которую я использую:

 ffmpeg -i input.avi -ss 00:10:00 -vframes 10 -vf showinfo,fps=fps=1/300 d.jpg amp;> output.txt
  

Где -ss 00:10:00 позволяет мне пропустить вперед 10 минут в видео перед запуском и -vframes 10 позволяет мне снимать только первые 10 кадров (1 кадр за 5 минут).

Это почти нормально работает, за исключением того, что команда выводит информацию для всех кадров, включая те, которые не были записаны в формате jpeg. Вот пример вывода из трех строк:

 [Parsed_showinfo_0 @ 0x2219020] n:11427 pts:11429 pts_time:599.979 pos:48892180 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:6309A75D plane_checksum:[15A29007 1617E1FE D93A3549] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]
[Parsed_showinfo_0 @ 0x2219020] n:11428 pts:11430 pts_time:600.031 pos:48898094 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:B checksum:815D031A plane_checksum:[E004E973 E28CE2D5 F56636B4] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]
[Parsed_showinfo_0 @ 0x2219020] n:11429 pts:11431 pts_time:600.084 pos:48892448 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:6CE2D3C5 plane_checksum:[E983BD86 38B9E198 93B13498] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]
  

Я бы ожидал, что средняя строка с pts_time:600.031 будет первым кадром, извлеченным в виде изображения, но у меня нет возможности отличить его от других кадров с обеих сторон, где изображения не были извлечены.

Кто-нибудь знает способ решить эту проблему?

Спасибо!

Ответ №1:

Вы можете использовать -vf showinfo для получения информации о кадре с помощью ffmpeg . Например, извлечение кадра при смене сцены и получение метки времени для этого конкретного кадра.

 ffmpeg -i image.mp4 -filter:v "select='gt(scene,0.1)',showinfo" -vsync 0 framesd.jpg >amp; output.txt
  

Вы выведете что-то похожее на: [Parsed_showinfo_1 @ 0x25bf900] n: 0 pts: 119357 pts_time:9.95637 …. Наша интересная часть — pts_time, для получения времени используйте следующую команду:

 grep showinfo ffout | grep pts_time:[0-9.]* -o | grep '[0-9]*.[0-9]*' -o > timestamps
  

Вы получите аналогичный результат:

 9.95637
9.98974
15.0281
21.8016
28.208
28.4082
28.5083
  

Комментарии:

1. здесь ffout output.txt

Ответ №2:

В ответ на мой собственный вопрос я нашел обходной путь, хотя я не совсем уверен, как это работает. Определив select аргумент внутри -vf , а также добавив vsync 0 параметр, подобный этому:

 ffmpeg -i input.avi -vframes 10 -vf '[in]select=not(mod(n,300*19.05))[s1];[s1]showinfo[out]' -vsync 0 d.jpg >amp; output.txt
  

… теперь функция возвращает только нужные 10 кадров. Вот пример вывода stderr первых двух кадров:

 [Parsed_showinfo_1 @ 0x21b1b60] n:0 pts:2 pts_time:0.104992 pos:10248 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:1 type:I checksum:F6FDCFBF plane_checksum:[5FB6331C 9D9D7F99 44FB1D0A] mean:[183 126 155 ] stdev:[19.6 0.8 2.8 ]
frame=    1 fps=0.0 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=1.0 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.7 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.5 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.4 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.3 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.3 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.2 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.2 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
[Parsed_showinfo_1 @ 0x21b1b60] n:1 pts:5717 pts_time:300.121 pos:24474150 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:BAECD030 plane_checksum:[F609470E 45F694CE 4BFCF445] mean:[148 126 152 ] stdev:[17.7 0.8 2.3 ]
frame=    2 fps=0.4 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.4 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A   
  

Все еще не уверен, почему это работает или почему каждый frame= ... из них реплицируется так много раз на выходе, но, похоже, он выполняет свою работу!

Ответ №3:

Кроме того, из документации ffmpeg аргумента «-ss»:

При использовании в качестве опции ввода (перед -i) ищет в этом входном файле позицию. Обратите внимание, что в большинстве форматов точный поиск невозможен, поэтому ffmpeg будет искать ближайшую точку поиска перед позицией.

Таким образом, кадр, который / должен / быть возвращен, — это кадр с номером n: 11427.