Использование avconv для получения одного кадра из видео h264 в заданное время

Я хочу использовать avconv для получения одного изображения в указанное время из видеофайла.

Я прочитал о libav достаточно, чтобы думать, что знаю, что делаю, но недостаточно, чтобы знать на самом деле.

Я пробовал:

avconv -ss 00:00:01.786 -r 25 -i input_video.h264 -frames 1 output_image.jpg

а также использовать t, чтобы избежать параметра «кадры»:

avconv -ss 00:00:01.786 -r 25 -i input_video.h264 -t 0.01 output_image.jpg

и передаются в секундах, а не в формате чч:мм:сс.ххх:

avconv -ss 1.786 -r 25 -i input_video.h264 -t 0.01 output_image.jpg

Я вижу, что когда для ss установлено значение 0 (это «0», «00:00:00.000», «0,0» и т. д.), output_image — это только первый кадр видео. Как и ожидалось.

Любое другое значение ss — даже 0,0001 — дает мне последний кадр видео.

Я использую последнюю версию avconv из репозитория Raspbian wheezy. Такое поведение кажется мне ошибкой, но я не знаю других тонкостей потокового видео достаточно хорошо, чтобы быть уверенным.

Кто-нибудь знает, что я делаю неправильно?



Дополнительный вопрос: я действительно хотел бы получить целую кучу этих изображений из одного видео. Объединение команд вместе, казалось, работало раньше, то есть:

avconv -ss 1.786 -r 25 -i input_video.h264 -t 0.01 output_image1.jpg 
-ss 3.454 -r 25 -i input_video.h264 -t 0.01 output_image2.jpg
-ss 5.823 -r 25 -i input_video.h264 -t 0.01 output_image3.jpg
-ss etc,etc.

но я вернулся к одиночным изображениям, чтобы отладить эту проблему. Предполагая, что первая проблема решена, это лучший способ структурировать эту команду или есть лучший?


person Samson Mustang    schedule 14.08.2014    source источник
comment
Хорошо, я перешел на ноутбук и выполнил те же команды, используя в качестве входных данных полнометражный фильм. Я вижу эффект, когда я увеличиваю точку поиска каждую секунду, выходное изображение не продвигается вперед по отснятому материалу, как вы ожидаете. Вместо этого вывод остается неизменным в течение нескольких секунд, а затем переходит к совершенно другому изображению. Как будто -ss seek не может переходить к точным точкам и вместо этого должен переходить между ключевыми кадрами или чем-то еще.   -  person Samson Mustang    schedule 14.08.2014
comment
возможно, вы стали жертвой быстрого и точного поиска trac.ffmpeg.org/wiki/Seeking %20с%20FFmpeg   -  person rogerdpack    schedule 15.08.2014
comment
Возможно, но я прочитал эту страницу и понял, что быстрый поиск (-ss перед -i) теперь выполняется с точностью до кадра (я понял это, потому что читал это на этой странице, а также на нескольких других) - хотя, если это не так, это было бы конечно объяснить поведение.   -  person Samson Mustang    schedule 20.08.2014
comment
может быть, это исправление в FFmpeg, но не в avconv?   -  person rogerdpack    schedule 20.08.2014


Ответы (2)


Редактировать: Как заметил Малвья, 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
comment
ffmpeg может точно искать, когда ss используется в качестве параметра ввода — см. запись для -ss. Это было правдой в течение достаточно долгого времени. - person Gyan; 04.03.2016

в моем случае я хотел изображение каждые 60 секунд первые 3 минуты...

для я в {0..3} ; do avconv -ss echo $i*60.0 | bc -i input_video.h264 -frames:v 1 -y out$i.jpg ; Готово

Если вам это нужно в определенное время, вы можете немного изменить это: 9.

person hamboy75    schedule 07.01.2016