Recording video with unknown framerate with FFmpeg
Asked Answered
R

2

11

I am recording video with FFmpeg and I would like the frame rate it is written with to at least be in the right ballpark. Right now I take the frame rate that my input claims to have and use that to set the frame rate (time_base) for my output video stream. However this is sometimes wildly different from the actual frame rate that I am getting (I have seen a stream claiming 50 fps but publishing at 9 fps).

What I would like to do is use a elapsed timer and count the frames I record to calculate the actual frame rate I recorded at when I am finished recording. I would seem though that the frame rate is set in my AVStream is used in avcodec_open2 before I write any frames. If I set it later (such as while I am writing frames) while ffplay can play it (complaining that the time increment bits is 6 not 4) other video players cannot. Is there a way to set the frame rate for the whole file after writing the frames? If not is there a way to tell the frames themselves some sort of timestamp or frame rate while I am recording that will result in a valid recorded file?

Rattly answered 13/4, 2016 at 15:35 Comment(4)
hi, I will look more, but just wanted to ask about avconv. found it after a quick google search, looks like it can change a file's frame rate. perhaps you could write the file at an arbitrary frame rate and then after detecting the real rate, finish writing and run avconv with the new rate? just a thought, not a real answer ;) will keep looking though. let me know.Following
avconv is the binary name for the libav project. (superuser.com/questions/507386/…) has a pretty decent summary of all the names which had me confused for quite some time. Anything avconv does should be possible with the libraries it uses.Rattly
were you able to solve the issue? I have the same issue too(Andresandresen
@Andresandresen See my answer down below. Basically you set the timebase to the granularity of your timer, then every frame set the PTS to the elapsed time.Rattly
R
3

The trick seems to be to use AVCodecContext time_base and AVFrame pts in a more intelligent way than I was. If you are recording with a fixed frame rate then time_base is set to 1/framerate and the pts is just a incremented number for the recorded frame.

Instead now I start a elapsed timer when I begin my recording and set time_base to 1 over the granularity of the timer (in my case it has millisecond accuracy so 1000). I set frame pts to the amount of elapsed time before it is encoded. This combination results in a video file with a variable framerate that plays back correctly.

Rattly answered 24/7, 2017 at 19:29 Comment(0)
N
0

Chris. You need to develop new video stream write engine. So if you set frame rate as [N], the writing engine write frames as per rate.

  • Checking Timestamp For Each Frame When Writing
  • If you have less frames than N for a second, you need to make duplicate frames.
  • If you have more frames than N for a second, you need to drop some frames.

Before writing, you need to specify exact framerate.

And your video file writing engine has to work with specified framerate.

You can implement this by using ffmpeg.

Nowak answered 3/11, 2016 at 3:51 Comment(1)
This seems like the best you could do with a variable frame rate but what if it were fixed and unknown? In the case I presented the stream claims 50 fps but is actually 9 so while your approach would work I would be recording over 5 times more frames than I would need to. Basically this to work well still requires that you know the frame rate before you start.Rattly

© 2022 - 2024 — McMap. All rights reserved.