Получить количество кадров с помощью ffmpeg - PullRequest
86 голосов
/ 07 января 2010

Кто-нибудь знает, как получить общее количество кадров из видеофайла с помощью ffmpeg? Вывод ffmpeg при рендеринге показывает текущий кадр, и мне нужно количество кадров, чтобы вычислить прогресс в процентах.

Ответы [ 13 ]

115 голосов
/ 07 февраля 2015

Примечание. Наличие списка редактирования в MP4 / M4V / M4A / MOV может повлиять на номер вашего кадра. См. Изменить списки ниже.


ffprobe: запрос контейнера

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Это быстрый метод.
  • Не все форматы (такие как Matroska) сообщают о количестве кадров, что приводит к выводу N/A. См. Другие методы, перечисленные ниже.

ffprobe: подсчитать количество кадров

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Это медленный метод.
  • Добавьте параметр -skip_frame nokey только для подсчета ключевых кадров.

ffmpeg: подсчитать количество кадров

Если у вас нет ffprobe, вы можете использовать ffmpeg вместо:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Это довольно быстрый метод.
  • См. frame= рядом с концом вывода консоли.
  • Добавьте параметр ввода -discard nokey (до -i) только для подсчета ключевых кадров.

Редактировать списки

Игнорировать список редактирования MP4 / M4V / M4A / MOV с параметром ввода -ignore_editlist 1. По умолчанию не игнорировать список редактирования.

Что означают опции ffprobe

  • -v error Это скрывает вывод "информации" (информация о версии и т. Д.), Что облегчает анализ.

  • -count_frames Подсчитать количество кадров на поток и сообщить об этом в соответствующем разделе потока.

  • -select_streams v:0 Выбор только видеопотока.

  • -show_entries stream=nb_frames или -show_entries stream=nb_read_frames Показать только запись для nb_frames или nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1 Установите формат вывода (он же «писатель») на default, не печатайте ключ каждого поля (nokey=1) и не печатайте верхний и нижний колонтитулы раздела (* 1081) *). Есть более короткие альтернативы, такие как -of csv=p=0.

Также см.


MediaInfo

Хорошо известный инструмент mediainfo может выводить количество кадров:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4Box

Для файлов MP4 / M4V / M4A.

MP4Box из gpac может показывать количество кадров:

MP4Box -info input.mp4

Обратитесь к строке Media Info на выходе для рассматриваемого видеопотока:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

В этом примере видеопоток имеет 2525 кадров.


boxdumper

Для файлов MP4 / M4V / M4A / MOV.

boxdumper - простой инструмент от l-smash. Это выведет большое количество информации. Под разделом stsz в поле размера образца указано количество кадров в sample_count. В этом примере вход имеет 1900 видеокадров:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Помните, что файл может содержать более одного stsz атома.
23 голосов
/ 31 июля 2012

В Unix это работает как шарм:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
13 голосов
/ 07 января 2010

Вместо этого рассчитайте время.

Это то, что я делаю, и это прекрасно работает для меня и многих других.) Во-первых, найдите длину видео в следующем фрагменте:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

Вы сможете последовательно и безопасно найти Duration: hh:mm:ss.nn для определения размера исходного видеоклипа. Затем для каждой строки обновления (CR, без LF) вы можете проанализировать текст для текущей отметки времени, в которой она находится:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

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

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

Если у вас есть время, это простая математика: time / durration * 100 = % done.

8 голосов
/ 07 января 2010

Попробуйте что-то вроде:

ffmpeg -i "path to file" -f null /dev/null

Он записывает номер кадра в stderr, поэтому вы можете извлечь из него последний кадр.

8 голосов
/ 07 января 2010

Не все форматы хранят количество своих кадров или общую продолжительность - и даже если они это делают, файл может быть неполным - поэтому ffmpeg по умолчанию не определяет ни один из них точно.

Вместо этого попробуйте перейти к концу файла и прочитать время, а затем посчитать текущее время, пока вы идете.

В качестве альтернативы вы можете попробовать AVFormatContext->nb_index_entries или обнаруженную длительность, которая должна хорошо работать, по крайней мере, на неповрежденных AVI / MOV, или библиотеку FFMS2, которая, вероятно, слишком медленная, чтобы ее беспокоить для индикатора выполнения.

7 голосов
/ 28 апреля 2015

Вы можете использовать ffprobe для получения номера кадра с помощью следующих команд

  1. первый метод

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

, которые говорят, чтобы напечатать данные в json формате

select_streams v скажет ffprobe просто дать нам video потоковые данные, и если вы удалите их, он также даст вам audio информацию

и вывод будет выглядеть как

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2. Вы можете использовать

ffprobe -v error -show_format -show_streams video_name

, который даст вам потоковые данные, если вы хотите выбрать такую ​​информацию, как частота кадров, используйте следующую команду

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

, которые дают числовую базу для вашей видеоинформации, проблема в том, что при использовании этого метода возможно получить N/A в качестве вывода.

для получения дополнительной информации проверьте эту страницу Советы FFProbe

4 голосов
/ 15 июля 2010

попробуйте это:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
2 голосов
/ 04 августа 2014

Единственное точное, что мне удалось сделать, это следующее:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

Чтобы убедиться, что это работает с видео:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
2 голосов
/ 11 июля 2013

на основе ответа сту. Вот как я нашел частоту кадров для видео с моего мобильного телефона. я выполнил следующую команду некоторое время. я позволил подсчету кадров приблизиться к ~ 10000, прежде чем я потерял терпение и нажал ^ C:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

затем я взял две строки информации из этой строки, которая начинается с "frame =", счетчика кадров 7989 и времени 00: 04: 26.30 Сначала нужно преобразовать время в секунды, а затем разделить количество кадров на секунды, чтобы получить «количество кадров в секунду». "число кадров в секунду" - это ваша частота кадров.

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

частота кадров для моего видео составляет 30 кадров в секунду.

1 голос
/ 09 ноября 2017

Извините за ответ necro, но, возможно, он понадобится (поскольку я не нашел решения для последних выпусков ffmpeg.

С ffmpeg 3.3.4 я нашел, что можно найти со следующим:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

В конце будет выведено количество кадров. У меня сработало на видео с аудио. Это дает в два раза больше строки «nb_frames», но первой строкой было фактическое количество кадров в видео, которое я тестировал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...