tags:

views:

1087

answers:

4

Does anyone know how to fetch the number of total frames from a video file using ffmpeg? The render output of ffmpeg shows the current frame and I need the frame count to calculate the progress in percent.

A: 

Not all formats store their frame count or total duration - and even if they do, the file might be incomplete - so ffmpeg doesn't detect either of them accurately by default.

Instead, try seeking to the end of the file and read the time, then count the current time while you go.

Alternatively, you can try AVFormatContext->nb_index_entries or the detected duration, which should work on fine at least undamaged AVI/MOV, or the library FFMS2, which is probably too slow to bother with for a progress bar.

alex strange
A: 

Try something like:

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

It writes the frame number to stderr, so you can retrieve the last frame from this.

a1kmm
+1  A: 

Calculate it based on time, instead.

That's what I do and it works great for me, and many others.) First, find the length of the video in the below snippet:

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

You'll should be able to consistently and safely find Duration: hh:mm:ss.nn to determine the source video clip size. Then, for each update line (CR, no LF) you can parse the text for the current time mark it is at:

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    

Just becareful to not always expect perfect output from these status lines. They can include error messages like here:

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    

Once you have the time, it is simple math: time / durration * 100 = % done.

Stu Thompson
Excuse me for being stupid but how can I do time / duration when duration is in hh:mm:ss.nn format and time is always xx.yy format?
Omar
@Omar: Write code to convert. 75.23 == 00:01:15.23
Stu Thompson
A: 

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '

Julien