Как узнать количество кадров в видео в командной строке linux?


30

У меня есть видеофайл, и я хочу получить количество видеокадров в нем. Я могу использовать, ffmpegчтобы получить длину видео и FPS. Однако я не вижу ничего очевидного для общего количества кадров.

Теоретически можно умножить длину (в секундах) на FPS, чтобы получить количество кадров, но в этом случае длина (34,43 секунды) и частота кадров (29,97 кадров в секунду) дают нецелое число, что делает меня думаю, что я делаю что-то не так.

Я должен быть в состоянии сделать это в командной строке полностью автоматизированным и неграфическим способом. Мне также нужно, чтобы это было довольно точно, а не оценка (если это возможно даже с видеофайлами)

Я пытался использовать tcprobeнекоторые файлы. Для некоторых файлов AVI это работает, но для некоторых файлов VOB вывод tcprobe не имеет количества кадров. Я получаю этот вывод:

[tcprobe] MPEG program stream (PS)
[tcprobe] summary for myfile.vob, (*) = not default, 0 = not detected
import frame size: -g 720x480 [720x576] (*)
     aspect ratio: 4:3 (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
                   PTS=2199.3972, frame_time=33ms bitrate=7000 kbps
      audio track: -a 0 [0] -e 48000,16,5 [48000,16,2] -n 0x2000 [0x2000] (*)
                   PTS=2199.2763, bitrate=192 kbps
                   -D 3 --av_fine_ms 20 (frames & ms) [0] [0]

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

это VOB "все в одном" или VOB в стиле DVD, разделенные на несколько файлов?
шарлатан-кихот

Ответы:


17

Это ужасно, глупо и медленно, но, похоже, работает

ffmpeg -i foo.avi -vcodec copy -f rawvideo -y /dev/null 2>&1 | tr ^M '\n' | awk '/^frame=/ {print $2}'|tail -n 1

Он также будет работать прямо на усеченных файлах и сырых потоках (поэтому вы ничего не получаете за файлы .vob)


Это очень хорошо. По моему опыту, это не займет много времени. 40-минутный файл занимает около 3 секунд для запуска. Помните, что «^ M» - это не 2 символа ^ и M, вам нужно нажать Control-V, а затем ввести. Вместо вашей команды я использовал: ffmpeg -i somefile.avi -vcodec copy -f rawvideo -y / dev / null 2> & 1 | tr "^ M" '\ n' | grep '^ frame =' | perl -pe 's / ^ frame = \ s * ([0-9] +) \ s. * $ / \ 1 /' | tail -n 1 Ваша команда не выполняется, если после "frames =" нет пробела
Rory

1
В Ubuntu 12.04, ffmpeg версия git-2013-04-15-a4f03f0, вы можете опустить оба | tr ^M '\n'и |tail -n 1. Кроме того, ни один пробел после frames=не подводит. (Может быть, что-то изменилось за последние четыре года.)
Камиль Гудесюн

для меня это каждый раз возвращаются разные значения
CAMOBAP

1
Решение Mediainfo работает с VOB .. Я бы рекомендовал это вместо. root @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count Количество кадров: 175715 Количество кадров: 183218
kevinf

32

ffprobe может использоваться для получения информации о медиафайле:

ffprobe -select_streams v -show_streams input.avi

Вы получите подробную информацию о потоке:

nb_frames=159697

Ищите nb_framesс grep:

ffprobe -select_streams v -show_streams input.avi 2>/dev/null | grep nb_frames | sed -e 's/nb_frames=//'

Это работает для avi, mp4 и т. Д. Для некоторых контейнеров не отображается допустимое значение, например, mpeg.

В этом случае это работает ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l


Отличная идея. Я немного изменил команду, чтобы она только выбирала видеопоток и фильтровала вывод. Это дает вам только количество кадров.
slhck

1
Поздравляю с вашим вторым решением, которое работает с MPEG-2!
Малат

1
Не работает с контейнерами MKV.
Дженк Алти


Похоже, что первый подход не работает на VBR-кодированных файлах. Второй подход более надежен.
Старейшина Гик

16

Я отправил это на другой вопрос . Используя tcprobeинструмент (из transcodeпакета), количество кадров включается в информацию. Используйте -iпереключатель, чтобы получить информационный дамп из файла:

$ tcprobe -i foo.avi
[tcprobe] RIFF data, AVI video
[avilib] V: 29.970 fps, codec=XVID, frames=38630, width=512, height=384
[avilib] A: 48000 Hz, format=0x55, bits=16, channels=2, bitrate=128 kbps,
[avilib]    53707 chunks, 21768720 bytes, VBR
[tcprobe] summary for foo.avi, (*) = not default, 0 = not detected
import frame size: -g 512x384 [720x576] (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
      audio track: -a 0 [0] -e 48000,16,2 [48000,16,2] -n 0x55 [0x2000] (*)
                   bitrate=128 kbps
           length: 38630 frames, frame_time=33 msec, duration=0:21:28.954

Обратите внимание, что количество кадров указано здесь в двух строках (вторая строка вывода и последняя строка вывода).


Это выглядит как хороший ответ и работает для некоторых файлов, но для некоторых файлов VOB, которые у меня есть, у меня нет этих данных в выводе. Я обновил вопрос с выводом, который я получаю
Рори

я ожидаю (но не знаю наверняка), что tcprobe проверяет заголовки файлов для этой информации. если он не включен в заголовок, tcprobe может не пытаться вычислить его. хороший вопрос; Хотел бы я иметь хороший ответ для вас.
Quackote Quackote

Это не похоже на работу с VBR-кодированными файлами. Я не получаю вывод числа кадров. Я получаю разрешение, соотношение сторон и частоту кадров.
Старейшина Гик

7

Я обнаружил, что это mediainfo --fullscan inputfile | grep "Frame count"прекрасно работает для большинства файлов.

Системы на основе Debian могут установить его с apt-get install mediainfo

Если вы получаете 2 строки, а не одну из выходных данных, первая строка - это дорожка видео, а вторая - звуковая дорожка. Похоже, что это происходит на файлах с переменным битрейтом аудио.

Проверено на образцах .mkv, .m4v, .mp4, flv, vob и .avi на дату редактирования.

Источники: Как получить информацию о видеофайле из командной строки под Linux? и тестирование под Ubuntu.

Вы можете найти mediainfo для вашей ОС здесь.


4

ffprobe -select_streams v -show_frames -count_frames INPUT_FILE | grep pkt_duration_time =

Сложите продолжительность. Может быть моднее с sed / awk, а что нет.

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


3

Я обнаружил, что количество кадров на самом деле вдвое больше длительности fps * (не знаю почему, я был бы рад узнать).

В моем сценарии у меня есть:

# Get duration and fps
duration=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Duration: \([^,]*\), start: .*/\1/p")
fps=$($FFMPEG -i $input 2>&1 | sed -n "s/.*, \(.*\) tb.*/\1/p")

hours=$(echo $duration | cut -d":" -f1)
minutes=$(echo $duration | cut -d":" -f2)
seconds=$(echo $duration | cut -d":" -f3)
# For some reason, we have to multiply by two (no idea why...)
# Get the integer part with cut
frames=$(echo "($hours*3600+$minutes*60+$seconds)*$fps*2" | bc | cut -d"." -f1)

И да, по какой-то причине я должен получить целую часть этого. Это не имеет смысла, но этот скрипт до сих пор всегда правильно конвертировал мои видео.


Потому что FPS означает «Кадры в секунду» (или шутер от первого лица: D), и если есть 30 FPS, просто умножьте его на количество секунд в видео.
Джон Т

Да, Джон, я мог бы понять это, но это не объясняет, почему я должен умножить его на 2, чтобы получить правильное количество кадров ... В моем случае, после того, как я рассчитал количество кадров, я запустил ffmpeg в фон и проанализировали журналы, чтобы сделать индикатор выполнения. Журналы показывают, сколько кадров прошло в преобразовании. Как только все видео было конвертировано, кадр # был int (секунды * fps * 2), отсюда мой код, но я хотел бы знать, почему ;-)
ℝaphink

это любопытно; tcprobeвыход в моем ответе дает # кадров , как ровно секунд * кадров в секунду (округленной вверх). я ожидаю, что вы видите причуду ffmpeg. Вы пытались проанализировать файл с помощью других инструментов, чтобы увидеть, показывают ли они одинаковое количество кадров?
шарлатанство

Хммм ... Интересно. Я попробовал на видео, и я получил seconds*fps=1001.59и tcprobe=1002. Очевидно, tcprobeговорит мне, что мне не нужно умножать на два. Почему тогда ffmpeg дает мне число, которое в два раза больше в журналах при конвертации?
ℝaphink

2
это чересстрочная съемка? Если так, то в каждом кадре два поля, и это может дать вам количество полей.
STIB

3

Проверено на Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- melt задумывался как инструмент тестирования для среды MLT, но он также является мощным многодорожечным редактором видео, ориентированным на командную строку. Он также может использоваться как минималистичный медиаплеер для аудио и видео файлов.

  • -consumerid [: arg] [name = value] *
    Установить потребителя (приемник)

  • xml - Установите для потребителя (приемника) вывод в формате xml

  • <property name="length">nnnn</property>- показывает количество кадров, где nnnnзаменяется целым числом, равным количеству кадров

Если у вас нет melt, вы можете установить его в Ubuntu и других системах на основе Debian с sudo apt-get install melt


1
Это очень коротко, вы хотите подробнее рассказать о том, что он делает, почему он работает и т. Д.?
Дэвид

Это хорошо работает на файлах mp2 h264, которые не предоставляют framecount через mediainfo -fullscan filename.
Старейшина Гик

3

Прямо с mediainfo, без grep, без ожидания, без ничего

mediainfo --Inform='Video;%FrameCount%' $the_file

Для получения дополнительной информации см. mediainfo --info-parameters


0

Вы можете сделать это, добавив и умножив значения, полученные из ffprobe.

Примечание: ffprobe является частью libav (avconv) - версии ffmpeg для Linux.

#your command -
 ffprobe man.avi

Когда вы сделаете это, вы получите количество кадров в секунду, а также продолжительность клипа.

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

Не забудьте округлить число до ближайшего.


В Ubuntu 14.04 LTS ffprobeотсутствует, но есть нечто , называемое avprobeв libav-tools(который также avconv). Но на моей стороне он не печатает любое количество кадров, по крайней мере, не для форматов, которые я пробовал. Он просто печатает, что avprobe -iпечатает тоже, и это, к сожалению, лишь незначительные детали формата. Даже с -v debugэтим он говорит только о некоторых хороших свойствах моего оборудования и установленного программного обеспечения, но ни о какой интересной информации о файле / потоке для исследования. Возможно, это скрывается в некоторых из множества доступных вариантов. Кто знает?
Тино

@Tino ffprobe действительно доступен как часть пакета ffmpeg. avconv является вилкой ffmpeg и вызвал некоторую путаницу. См .: stackoverflow.com/questions/9477115/…
Старейшина Гик

@ElderGeek Для Ubuntu 14.04 LTS нет ffmpegв официальных репозиториях. Ссылка, которую вы дали правильно, гласит: FFmpeg вернулся в Ubuntu 15.04 "Vivid Vervet". , Однако ситуация изменилась, так как 16.04 LTS отсутствует.
Тино

@Tino Это действительно факт. Однако я бы не стал приравнивать недоступность к не существует в хранилищах. Вы заметите, что он доступен для Trusty (14.04) здесь: ffmpeg.org/download.html
Elder Geek

0

линукс

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]

-2

Лучший метод: (Прямой расчет правильных параметров, подтвержденный ffmpeg)

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"

Результат ->

r_frame_rate=24000/1001
duration=8177.794625

Расчет ->

Frames=24000/1001*8177.794625=196071 (exactly... ;P)

Доказательство ->

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
shareeditdeleteflag

Я получаю r_frame_rate = 25/1 длительность = N / A
Старейшина Geek
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.