33

I have a video file and I want to get the number of video frames that are in it. I can use ffmpeg to get the length of the video and the FPS. However I can't see anything obvious for the total number of frames.

In theory one should be able to multiply the length (in seconds) by the FPS to get the number of frames, but in this case the length (34.43 seconds) and the framerate (29.97 fps) give a non-integer, which makes me think I'm doing something wrong.

I need to be able to do this on the command line in a totally automated and non-graphical manner. I also need this to be pretty exact, and not an estimate (if that's even possible with video files)

I tried using tcprobe on some files. For some AVI files it works, but for some VOB files, the tcprobe output doesn't have the number of frames. I get this output:

[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]

11 Answers 11

20

This is horrible, and stupid, and slow, but seems to work:

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

It will also work right on truncated files and raw streams(that is why you get nothing for .vob files)

| improve this answer | |
  • That's pretty good. In my experience, it doesn't take that long. A 40 minute file takes about <3seconds to run though. Remember that the "^M" is not the 2 characters ^ and M, you have to press Control-V, and then enter. Instead of your command I used: 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 Your command fails if there's no space after the "frames=" – Rory Jan 5 '10 at 12:23
  • 1
    In Ubuntu 12.04, ffmpeg version git-2013-04-15-a4f03f0, you can omit both | tr ^M '\n' and |tail -n 1. Also, no space after frames= doesn't fail. (Maybe something's changed in the past four years.) – Camille Goudeseune Aug 12 '14 at 19:10
  • for me this return each time different values – CAMOBAP Oct 27 '16 at 7:32
  • 1
    Mediainfo solution works with VOB.. I would recommend that instead. root@lanparty:/mnt/films# mediainfo --fullscan Bugs_Bunny.vob | grep -i frame\ count Frame count : 175715 Frame count : 183218 – kevinf Apr 22 '17 at 21:10
34

ffprobe can be used to get info about a media file:

ffprobe -select_streams v -show_streams input.avi

You will get details about the stream:

nb_frames=159697

Look for nb_frames with grep:

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

That works for avi, mp4 and etc For some containers, it does not show valid value e.g. mpeg.

In that case, this works ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l

| improve this answer | |
16

I posted this on another question. Using the tcprobe tool (from the transcode package), the number of frames is included in the info. Use the -i switch to get an info dump from the file:

$ 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

Note the number of frames is given on two lines here (2nd output line and last output line).

| improve this answer | |
  • That looks like a good answer, and works for some files, but for some VOB files I have, I don't have that data in the output. I've updated the question with the output I get – Rory Dec 18 '09 at 9:58
  • i expect (but don't know for sure) that tcprobe is examining file headers for this info. if it's not included in the header, tcprobe may not attempt a calculation for it. good question; wish i had a good answer for you. – quack quixote Feb 3 '10 at 7:59
  • This doesn't appear to work on VBR encoded files I get no frame count output. I do get resolution, aspect ratio and frame rate. – Elder Geek May 2 '19 at 21:26
8

I've found that mediainfo --fullscan inputfile | grep "Frame count" works nicely for most files.

Debian based systems can install it with apt-get install mediainfo

If you get 2 lines rather than one of output the first line is the video track and the second line is the audio track. It appears that this occurs on files with Variable Bit Rate audio.

Tested on .mkv, .m4v, .mp4, flv, vob and .avi samples as of date of edit.

Sources: How to retrieve video file information from command line under Linux? and testing under Ubuntu flavors.

You can find mediainfo available for your OS here.

| improve this answer | |
4

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

Add up the duration. Could be fancier with sed/awk and what not.

From our testing I can say that for now it has shown to be the best most reliable. You get a precise framecount and exact duration. Even with variable framerate which all other tools like mediainfo seem to go gaga.

| improve this answer | |
4

Directly with mediainfo, no grep, no wait, no nothing:

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

For other information see mediainfo --info-parameters

| improve this answer | |
3

I've found that the number of frames is actually twice the fps*duration (no idea why, I'd be happy know).

In a script of mine, I have:

# 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)

And yes, for some reason I have to get the integer part of it. It doesn't make sense, but this script has always managed to convert my videos properly so far.

| improve this answer | |
  • Because FPS stands for Frames Per Second (or first person shooter :D ) and if there's 30 FPS simply multiply it by how many seconds are in the video. – John T Dec 17 '09 at 16:38
  • Yes John, I could figure that out, but that doesn't explain why I have to multiply it by 2 to get the right amount of frames... In my case, after I calculated the amount of frames, I launched ffmpeg in the background and analyzed the logs to make a progress bar. The logs show how many frames have passed in the conversion. Once the whole video was converted, the frame # was int(seconds*fps*2), hence my code, but I'd like to know why ;-) – ℝaphink Dec 17 '09 at 17:08
  • that's curious; the tcprobe output in my answer gives the # of frames as exactly seconds*fps (rounded up). i expect you're seeing a quirk of ffmpeg. have you tried analyzing the file with other tools to see if they show the same number of frames? – quack quixote Dec 17 '09 at 17:34
  • Hmmm... Interesting. I tried on a video and I got seconds*fps=1001.59 and tcprobe=1002. So obviously, tcprobe tells me I don't need to multiply by two. Why then does ffmpeg give me a number that is twice as big in the logs when it's converting? – ℝaphink Dec 17 '09 at 17:55
  • 2
    is it interlaced footage? If so there are two fields per frame, and it could be giving you the number of fields. – stib Jun 14 '14 at 8:28
3

Tested on Ubuntu.

melt icecap.mp4 -consumer xml
  • melt - melt was meant as a test tool for the MLT framework, but it is also a powerful multitrack command line oriented video editor. It could also used as an minimalistic media player for audio and video files.

  • -consumer id[:arg] [name=value]*
    Set the consumer (sink)

  • xml - Set the consumer (sink) to xml formatted output

  • <property name="length">nnnn</property> - shows the number of frames, where nnnn is replaced by an integer number that equals the number of frames

If you don't have melt you can install it on Ubuntu and other Debian based systems with sudo apt-get install melt

| improve this answer | |
  • 1
    This is very short, do you want to expand on what it does, why it works, etc? – David Dec 3 '15 at 20:42
  • This works well on h264 mp4 files which don't provide the framecount via mediainfo -fullscan filename. – Elder Geek Jun 6 '16 at 17:28
0

You can do this by adding and multiplying the values you get from ffprobe .

Note: ffprobe is part of libav(avconv) - the linux version of ffmpeg.

#your command -
 ffprobe man.avi

When you do this you will get the number of frames per/second and also the duration of the clip.

Convert the duration of the clip to second's and the multiply that value by the number of frames/second.

Remember to round up number to the nearest.

| improve this answer | |
  • On Ubuntu 14.04 LTS ffprobe is unavailable, but there is something called avprobe in libav-tools (which also provides avconv). But at my side it does not print any number of frames, at least not for the formats I tried. It just prints, what avprobe -i prints, too, and this is just some minor bits about the format, sadly. Even with -v debug it only tells me some nice properties of my hardware and software installed, but not a single bit of interesting information about the file/stream to probe. Perhaps it hides in some of the myriads of options which are available. Who knows? – Tino Feb 1 '15 at 2:27
  • @Tino ffprobe is indeed available as part of the ffmpeg package. avconv is a fork of ffmpeg and caused some confusion. See: stackoverflow.com/questions/9477115/… – Elder Geek Jun 9 '16 at 14:11
  • @ElderGeek For Ubuntu 14.04 LTS there is no ffmpeg in the official repositories. The link you gave correctly states it: FFmpeg returned in Ubuntu 15.04 "Vivid Vervet".. However situation now changed as 16.04 LTS is out. – Tino Jun 9 '16 at 16:02
  • @Tino That is indeed a fact. However I wouldn't equate unavailable with doesn't exist in the repositories. You'll note it's available for Trusty (14.04) here: ffmpeg.org/download.html – Elder Geek Jun 11 '16 at 19:48
0

linux

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

ruby

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
| improve this answer | |
-2

Best method: (Direct by calculating right parameters, confirmed by 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"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

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

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

Here

frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x

Output

video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
shareeditdeleteflag
| improve this answer | |
  • I get r_frame_rate=25/1 duration=N/A – Elder Geek May 12 '19 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.