#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.