Як отримати кількість кадрів у відео у командному рядку 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 або DVD-стилі, розділені на кілька файлів VOB?
шарлатаний кіхот

Відповіді:


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" - це не два символи ^ і 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 /' | хвост -n 1 Ваша команда виходить з ладу, якщо після "кадрів =" немає місця
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
Вітаю за ваше 2-е рішення, яке працює з MPEG-2!
малат

1
Він не працює з контейнерами MKV.
Cenk Alti


Здається, що перший підхід не вдається для файлів, кодованих 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

Зверніть увагу, кількість кадрів вказано на двох рядках тут (2-й рядок виводу та останній вихідний рядок).


Це виглядає як гарна відповідь і працює для деяких файлів, але для деяких файлів VOB у мене немає цих даних у висновку. Я оновив питання з отриманим результатом
Rory

Я очікую (але точно не знаю), що tcprobe вивчає заголовки файлів для цієї інформації. якщо він не включений до заголовка, tcprobe може не спробувати обчислити його. Гарне питання; хотілося б, щоб я мав для вас гарну відповідь.
шарлатаний кіхот

Схоже, це не працює на файлах, кодованих VBR, я не отримую висновок про кількість кадрів. Я отримую роздільну здатність, співвідношення сторін і частоту кадрів.
Старійшина Гік

7

Я виявив, що mediainfo --fullscan inputfile | grep "Frame count"добре працює для більшості файлів.

Системи на базі Debian можуть встановлювати його apt-get install mediainfo

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

Тестовано на зразках .mkv, .m4v, .mp4, flv, vob та .avi на дату редагування.

Джерела: Як отримати інформацію про відеофайли з командного рядка під Linux? і тестування на аромати Ubuntu.

Ви можете знайти медіаінфо, доступну для вашої ОС тут.


4

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

Додайте тривалість. Може бути фантазії з sed / awk, а що ні.

З нашого тестування можу сказати, що наразі воно виявилося найкращим і найнадійнішим. Ви отримуєте точну кількість кадрів і точну тривалість. Навіть із змінною частотою кадрів, яка, як видається, всі інші інструменти, такі як медіаінфо, виглядає гаги.


3

Я виявив, що кількість кадрів насправді вдвічі перевищує тривалість кадрів в секунду * (поняття не маю чому, я би радий знати).

У моєму сценарії я маю:

# 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 означає Frames per Second (або шутер від першої особи: D), а якщо є 30 FPS, просто помножте його на скільки секунд у відео.
Джон Т

Так, Джон, я міг це зрозуміти, але це не пояснює, чому я повинен помножити його на 2, щоб отримати потрібну кількість кадрів ... У моєму випадку, після того, як я обчислив кількість кадрів, я запустив ffmpeg у фон та проаналізували журнали, щоб досягти смужки прогресу. Журнали показують, скільки кадрів пройшло у конверсії. Як тільки все відео було перетворено, кадр № був int (секунди * кадрів в секунду * 2), звідси мій код, але я хотів би знати чому ;-)
phaphink

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

Хммм ... Цікаво. Я спробував на відео, і я отримав seconds*fps=1001.59і tcprobe=1002. Очевидно, tcprobeговорить мені, що мені не потрібно множуватись на два. Чому тоді ffmpeg дає мені число, яке вдвічі більше в журналах при його перетворенні?
phaphink

2
це переплетені кадри? Якщо так, є два поля на кадр, і це може дати вам кількість полів.
стиб

3

Тестовано на Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- розплав мався на увазі як тестовий інструмент для рамки MLT, але він також є потужним багато редакторним відеоредактором, орієнтованим на командний рядок. Він також може бути використаний як мінімалістичний медіаплеєр для аудіо та відеофайлів.

  • -consumerid [: arg] [name = value] *
    Встановити споживача (раковину)

  • xml - Встановіть споживача (раковину) на формат XML

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

Якщо у вас немає розплаву, ви можете встановити його на Ubuntu та інших системах на базі Debian sudo apt-get install melt


1
Це дуже коротко, ви хочете розширити, що це робить, чому це працює і т.д.?
Девід

Це добре працює на h264 mp4 файлах, які не забезпечують кількість кадрів через mediainfo -fullscan filename.
Старійшина Гік

3

Безпосередньо mediainfo, ні греп, ні очікування, ніщо:

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

Іншу інформацію див mediainfo --info-parameters


0

Це можна зробити, додавши та множивши значення, отримані від ffprobe.

Примітка: ffprobe є частиною libav (avconv) - Linux версією ffmpeg.

#your command -
 ffprobe man.avi

Після цього ви отримаєте кількість кадрів в секунду, а також тривалість кліпу.

Перетворіть тривалість кліпу на секунду і помножте це значення на кількість кадрів / секунду.

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


В Ubuntu 14.04 LTS ffprobeвідсутня, але є щось , зване avprobeв libav-tools(який також avconv). Але в моєму боці він не друкує жодної кількості кадрів, принаймні, не для форматів, які я намагався. Це просто друкує, що avprobe -iдрукує, і це, на жаль, лише деякі незначні біти щодо формату. Навіть з -v debugцим лише мені підказують деякі приємні властивості встановленого мого обладнання та програмного забезпечення, але не є жоден біт цікавої інформації про файл / потік для зондування. Можливо, він ховається в деяких із безлічі варіантів, які є в наявності. Хто знає?
Тіно

@Tino ffprobe дійсно доступний як частина пакету ffmpeg. avconv - це fork 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
Старійшина

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]

-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
Старійшина Гік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.