Получить количество кадров с помощью ffmpeg

113

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

Hansl
источник
1
superuser.com/questions/84631/…
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功 03 апр.'16

Ответы:

158

Примечание. Наличие списка редактирования в 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) и не печатать заголовок и нижний колонтитул раздела ( noprint_wrappers=1). Есть более короткие альтернативы, такие как -of csv=p=0.

Также см


медиа информация

Известный 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 кадров.


самосвал

Для файлов 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атома.
llogan
источник
5
Или, если вам нужна более высокая скорость и если nb_frames достаточно надежен, упростите как:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
juanitogan
Это выводит ответ дважды для меня (т.е. 2600 \ n 2600). Какая-то конкретная причина, по которой это могло произойти?
jbodily
@jbodily Мой пример или пример juanitogan? Я не могу дублировать это, используя тоже. Здесь не с чем работать.
llogan
+1, не в последнюю очередь потому, что, в отличие от слишком многих других ответов о любом инструменте командной строки, этот фактически объясняет все параметры командной строки. Спасибо.
Ray
1
Обратите внимание, что первый вариант, запрос контейнера, фактически обрабатывает файл из-за count_frames. См. Комментарий @ juanitogan.
agieNick02
24

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

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
транквилизатор
источник
3
Действительно хороший. Просто не нужно копировать аудиопоток. Вы можете использовать -an instat.
rekire
1
@PrakharMohanSrivastava Проверьте этот ответ
Антонио
4
На самом деле, это кажется быстрым и надежным:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Тимоти Зорн
1
@Michael спасибо за улыбку с моим утренним кофе :-)
Ллойд Мур
1
@TimothyZorn Ты сделал мой день!
Mladen Danic,
13

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

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

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.

Стю Томпсон
источник
1
Простите за глупость, но как я могу указать время / продолжительность, если продолжительность в формате чч: мм: сс.нн, а время всегда в формате xx.yy?
Омар Али
2
@Omar, Как разработчик .NET, я создаю TimeSpanиз него, а затем использую currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). TimeSpan также предоставляет мощную функцию синтаксического анализа, проверьте это,
Шимми Вейцхандлер
отличное решение, мое время в чч: мм: сс: мс, поэтому я полагаю, что за эти 3 года FFMPEG улучшил формат времени вывода.
ElektroStudios
1
Обратите внимание, что на выходе консоли может быть указано 29,97, но это сокращение от 30000/1001. То же самое для 23,98, что составляет 24000/1001, а 59,94 - это 60000/1001.
llogan
Обратите внимание: это не работает для видео с переменной частотой кадров (очевидно).
Тимоти Зорн
8

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

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

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

Алекс Стрэндж
источник
8

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

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

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

a1kmm
источник
8

Вы можете использовать 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

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

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Жюльен
источник
Не работает с *.ts. Результатом будет пустая строка.
Виктор Полевой,
3

Поскольку мой комментарий получил несколько голосов, я решил оставить его в качестве ответа:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

Это должно быть быстро, так как кодирование не выполняется. ffmpegпросто демультиплексирует файл и как можно быстрее прочитает (декодирует) первый видеопоток. Первая grepкоманда захватит текст, показывающий фрейм. Вторая grepкоманда возьмет только номер из этого. Команда tailпросто покажет последнюю строку (окончательное количество кадров).

Тимоти Цорн
источник
2

чтобы основываться на ответе Стю. вот как я узнал частоту кадров видео со своего мобильного телефона. Некоторое время я выполнял следующую команду. Я позволил счетчику кадров приблизиться к ~ 10 000, прежде чем я набрался терпения и нажал ^ 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 кадров в секунду.

Маргарет
источник
2

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

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
Ллойд Мур
источник
Я поддержал ваш ответ, но это сработает, только если видео не содержит звука. Если он содержит, то этот будет работать:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

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

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

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

В конце будет выведено количество кадров. У меня это сработало с видео со звуком. Тем не менее, он дает дважды строку "nb_frames", но первая строка - это фактическое количество кадров в видео, которые я тестировал.

acidrums4
источник
Спасибо @ acidrums4. Проверено, что этот метод работает с последней версией из github, которую я построил сегодня.
Paul J
1

Я использую php_ffmpeg, тогда я могу получать все времена и все кадры фильма. Как показано ниже

$input_file='/home/strone/workspace/play/CI/abc.rmvb';
$ffmpegObj = new ffmpeg_movie($input_file);
echo $ffmpegObj->getDuration();
    echo $ffmpegObj->getFrameCount();

А потом подробности на странице.

http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

Синъюэ
источник
1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Джерард Венсинк
источник
Частота кадров обычно рассчитывается из двух параметров. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Округлено ffmpeg до: 23,98 Продолжительность = часы * 3600 + минуты * 60 + секунды. остаток = 8177,91 Параметр продолжительности = 8177,794625 Но кадры = 24000/1001 * 8177,794625 = 196071 дает точное количество кадров. (Без шуток).
Джерард Венсинк
0

linux

ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null

Рубин

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
Ярослав Малык
источник