Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding duration/number of frames of WebM using FFMPEG/libavformat

I'm trying to retrieve the duration and number of frames from a WebM file using FFMPEG and libavformat. I'm adapting some code that was initially written to work with MP4s, and when passing an MP4 it seems to work fine.

I have FFMPEG 2.1 compiled with the vp8 parser and decoder and the matroska demuxer.

I have an AVStream pointer to the video stream, *video_st. The code looks for the number of frames in video_st->nb_frames, and for the duration in video_st->duration. These both appear to be 0.

The API docs for for video_st->duration (https://ffmpeg.org/doxygen/trunk/structAVStream.html#a4e04af7a5a4d8298649850df798dd0b) say that "If a source file does not specify a duration, but does specify a bitrate, this value will be estimated from bitrate and file size." I can confirm that that this file does specify a duration and a bitrate (as I tested it on my desktop with ffmpeg -i). So it seems odd that this is returning 0. Perhaps my FFMPEG build configuration is incorrect?

As for nb_frames, the docs say "number of frames in this stream if known or 0". Is there anything I can do if this returns 0? Again, ffmpeg -i does return an estimate for fps; that would be good enough, as I could estimate the number of frames with that and the duration.

Thanks!

like image 781
gcgrant Avatar asked Sep 11 '15 21:09

gcgrant


1 Answers

Why is nb_frames 0?

Mp4 files can have complete indices of all frames in the stream, which allows you to exactly know the number of frames. AVI does this too. WebM allows indices of only frames-of-interest, e.g. keyframes, which means the index is smaller (i.e. smaller file), but it also means you don't know the number of frames unless you parse the whole file.

How to get the duration?

AVStream.duration is the per-stream duration. For many file types, including WebM, only the duration of the entire file is specified in the header, not the duration per-stream. Thus, use AVFormatContext.duration, which is in AV_TIME_BASE units (microseconds). To get an approximate FPS, use AVStream.avg_frame_rate, and then nb_frames can be approximated from there.

like image 169
Ronald S. Bultje Avatar answered Oct 15 '22 00:10

Ronald S. Bultje