Редактировать: Как заметил Малвья, ffmpeg всегда будет точно искать с -ss. Эта проблема является эксклюзивной для avconv.
Если вы укажете опцию -ss
перед опцией -i
, тогда avconv будет неточно вычислять положение кадра.
Сначала вам нужно указать параметр -i
, чтобы avconv знал, что ему нужно «искать» поток, пока он точно не найдет правильную метку времени.
Кроме того, время вашего примера 1.786
не соответствует количеству кадров в секунду -r 25
, которое вы указали в своем примере.
Поскольку 1/25=0.04
любое значение для -ss
должно делиться на 0.04
, чтобы точно указать отдельный кадр.
Следующее должно получить 46-й кадр вашего видео:
avconv -i input_video.h264 -r 25 -ss 1.8 -frames:v 1 output_image.jpg
Если вы хотите получить конкретный кадр по его индексу, вам нужно будет использовать bc
:
avconv -i input_video.h264 -r 25 -ss 0$(echo "scale=2;1000/25" | bc -l) -frames:v 1 output_image.jpg
Где 1000
— это 1001-й кадр видео (поскольку 0/25
— это 1-й кадр).
Обратите внимание, что в отличие от примера @hamboy75 мы передаем -l
(нижний регистр L) в bc
, чтобы он выполнял вычисления с плавающей запятой (и не округлял до ближайшего целого числа). scale=2
используется для получения числа с точностью до 2dp.
Также обратите внимание, что bc
имеет «особенность» вывода чисел меньше 1 без начального нуля (т.е. .04
), которую avconv не понимает. Поэтому нам также нужно вставить начальный нуль перед вычислением 0$()
.
При использовании этой команды вы получите вывод, который выглядит следующим образом
frame= 0 fps= 0 q=0.0 size= 0kB time=10000000000.00 bitrate= 0.0kbit
frame= 0 fps= 0 q=0.0 size= 0kB time=10000000000.00 bitrate= 0.0kbit
frame= 0 fps= 0 q=0.0 size= 0kB time=10000000000.00 bitrate= 0.0kbit
frame= 0 fps= 0 q=0.0 size= 0kB time=10000000000.00 bitrate= 0.0kbit
frame= 0 fps= 0 q=0.0 size= 0kB time=10000000000.00 bitrate= 0.0kbit
Это связано с тем, что avconv просматривает файл, чтобы точно найти запрошенный вами кадр. Таким образом, кадры с большим индексом будут извлекаться дольше, потому что avconv всегда будет «искать» поток с начала потока.
Поэтому может быть более желательным извлекать диапазон кадров:
avconv -i input_video.h264 -r 25 -ss 0$(echo "scale=2;7500/25" | bc -l) -t 0$(echo "scale=2;250/25" | bc -l) output_image_%04d.jpg
В этом примере извлекаются 10-секундные кадры из 5-минутного видео. Конечно, вы также можете просто использовать:
avconv -i input_video.h264 -r 25 -ss 300.0 -t 10.0 | bc -l) output_image_%04d.jpg
Однако помните, что для любой продолжительности менее секунды значение должно быть кратно частоте кадров видео (например, 0.04
для 25 кадров в секунду).
Изображения для каждого кадра будут называться output_image_0001.jpg
, output_image_0002.jpg
, output_image_0003.jpg
и т. д. Если вы хотите выполнить сравнение изображений на извлеченных кадрах, вы можете рассмотреть возможность использования png
вместо jpg
для большей точности.
Обратите внимание, что если вы укажете индекс кадра больше, чем количество кадров, присутствующих в видео, avconv просто извлечет последний найденный кадр. Вы можете рассчитать количество кадров в видео, взглянув на часть Duration:
вывода avconv -i input_video.h264
.
person
richardjsimkins
schedule
04.03.2016