How do I get the number of frames in a video on the linux command line?

30

17

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]

Rory

Posted 2009-12-17T16:17:15.720

Reputation: 1 547

1http://stackoverflow.com/questions/2017843/fetch-frame-count-with-ffmpeg – Ciro Santilli 新疆改造中心法轮功六四事件 – 2016-04-03T21:23:07.990

your equation will give you a good ballpark estimate; just round the floating-pt result up. if you need an exact number of frames you'll need to examine the file directly -- your estimate might be off by one or two in either direction due to the particulars of the video codec. – quack quixote – 2009-12-17T18:47:17.023

are these all-in-one-file VOBs or DVD-style split-into-multiple-file VOBs? – quack quixote – 2009-12-18T16:55:50.677

Answers

18

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)

user23307

Posted 2009-12-17T16:17:15.720

Reputation: 5 915

1In 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 – 2014-08-12T19:10:03.620

for me this return each time different values – CAMOBAP – 2016-10-27T07:32:47.407

1Mediainfo 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 – 2017-04-22T21:10:17.813

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 – 2010-01-05T12:23:59.890

32

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

Aftershock

Posted 2009-12-17T16:17:15.720

Reputation: 487

1Congrats for your 2nd solution which works with MPEG-2 ! – malat – 2015-03-25T11:20:57.413

1It does not work with MKV containers. – Cenk Alti – 2015-12-22T09:31:07.680

1

nb_frames=N/A on this file: http://web.archive.org/web/20180117220713/http://techslides.com/demos/sample-videos/small.webm

– Ciro Santilli 新疆改造中心法轮功六四事件 – 2018-01-17T22:08:10.620

It seems that the first approach fails on VBR encoded files. The second approach is more reliable. – Elder Geek – 2019-05-02T21:31:09.790

Good idea. I modified the command a little so that it only selects the video stream, and filters the output. That gives you just the number of frames. – slhck – 2014-06-13T14:31:08.620

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

quack quixote

Posted 2009-12-17T16:17:15.720

Reputation: 37 382

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 – 2010-02-03T07:59:27.787

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 – 2019-05-02T21:26:44.280

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 – 2009-12-18T09:58:48.327

7

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.

Elder Geek

Posted 2009-12-17T16:17:15.720

Reputation: 417

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.

Guillaume Blain

Posted 2009-12-17T16:17:15.720

Reputation: 41

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

neoneye

Posted 2009-12-17T16:17:15.720

Reputation: 725

1This is very short, do you want to expand on what it does, why it works, etc? – David – 2015-12-03T20:42:05.393

This works well on h264 mp4 files which don't provide the framecount via mediainfo -fullscan filename. – Elder Geek – 2016-06-06T17:28:19.357

3

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

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

For other information see mediainfo --info-parameters

xenoid

Posted 2009-12-17T16:17:15.720

Reputation: 7 552

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.

ℝaphink

Posted 2009-12-17T16:17:15.720

Reputation: 3 531

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 – 2009-12-17T16:38:38.440

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(secondsfps2), hence my code, but I'd like to know why ;-) – ℝaphink – 2009-12-17T17:08:13.557

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 – 2009-12-17T17:34:21.930

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 – 2009-12-17T17:55:34.367

you're watching output during encoding, not examining a file post-encode, right? could be a bug in the output code. could be something in the encoding process such that that output makes sense. i expect you'd have to examine the code to figure it out for sure. – quack quixote – 2009-12-17T18:44:02.443

Yes, I'm watching the output during encoding to make a progress bar. – ℝaphink – 2009-12-17T18:47:25.200

i ran mediainfo filename.mp4 | grep -i fram and saw a line which says Format settings, ReFrames : 2 frames. this seems related. – mulllhausen – 2014-04-24T05:23:45.083

2is it interlaced footage? If so there are two fields per frame, and it could be giving you the number of fields. – stib – 2014-06-14T08:28:40.900

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]

Yaroslav Maluk

Posted 2009-12-17T16:17:15.720

Reputation: 1

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.

JJAtairu

Posted 2009-12-17T16:17:15.720

Reputation: 1

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 – 2015-02-01T02:27:17.100

@Tino ffprobe is indeed available as part of the ffmpeg package. avconv is a fork of ffmpeg and caused some confusion. See: http://stackoverflow.com/questions/9477115/what-are-the-differences-and-similarities-between-ffmpeg-libav-and-avconv

– Elder Geek – 2016-06-09T14:11:43.700

@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 – 2016-06-09T16:02:47.137

@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: https://ffmpeg.org/download.html

– Elder Geek – 2016-06-11T19:48:46.507

-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

Gerard Wensink

Posted 2009-12-17T16:17:15.720

Reputation: 1

I get r_frame_rate=25/1 duration=N/A – Elder Geek – 2019-05-12T12:12:16.390