IOS AVPlayer get fps

10,858

Solution 1

Use AVAssetTrack's nominalFrameRate property.

Below method to get FrameRate : Here queuePlayer is AVPlayer

-(float)getFrameRateFromAVPlayer
{
  float fps=0.00;
  if (self.queuePlayer.currentItem.asset) {
    AVAssetTrack * videoATrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];
    if(videoATrack)
    {
        fps = videoATrack.nominalFrameRate;
    }
  }
  return fps;
}

Solution 2

Swift 4 version of the answer:

let asset = avplayer.currentItem.asset

let tracks = asset.tracks(withMediaType: .video)

let fps = tracks?.first?.nominalFrameRate

Remember to handle nil checking.

Solution 3

There seems to be a discrepancy in this nominalFrameRate returned for the same media played on different versions of iOS. I have a video I encoded with ffmpeg at 1 frame per second (125 frames) with keyframes every 25 frames and when loading in an app on iOS 7.x the (nominal) frame rate is 1.0, while on iOS 8.x the (nominal) frame rate is 0.99. This seems like a very small difference, however in my case I need to navigate precisely to a given frame in the movie and this difference screws up such navigation (the movie is an encoding of a sequence of presentation slides). Given that I already know the frame rate of the videos my app needs to play (e.g. 1 fps) I can simply rely on this value instead of determining the frame rate dynamically (via nominalFrameRate value), however I wonder WHY there is such discrepancy between iOS versions as far as this nominalFrameRate goes. Any ideas?

Solution 4

The rate value on AVPlayer is the speed relative to real time to which it's playing, eg 0.5 is slow motion, 2 is double speed.

As Paresh Navadiya points out a track also has a nominalFrameRate variable however this seems to sometimes give strange results. the best solution I've found so far is to use the following:

CMTime frameDuration = [myAsset tracksWithMediaType:AVMediaTypeVideo][0].minFrameDuration;
float fps = frameDuration.timescale/(float)frameDuration.value;

The above gives slightly unexpected results for variable frame rate but variable frame rate has slightly odd behavior anyway. Other than that it matches ffmpeg -i in my tests.

EDIT ----

I've found sometimes the above gives time kCMTimeZero. The workaround I've used for this is to create an AVAssetReader with a track output,get the pts of the first frame and second frame then do a subtraction of the two.

Solution 5

I don't know anything in AVPlayer that can help you to calculate the frame rate.

AVPlayerItem rate property is the playback rate, nothing to do with the frame rate.

The easier options is to obtain a AVAssetTrack and read its nominalFrameRate property. Just create an AVAsset and you'll get an array of tracks.

Or use AVAssetReader to read the video frame by frame, get its presentation time and count how many frames are in the same second, then average for a few seconds or the whole video.

Share:
10,858

Related videos on Youtube

user346443
Author by

user346443

Updated on September 15, 2022

Comments

  • user346443
    user346443 over 1 year

    Im trying to figure out how to retrieve a videos frame rate via AVPlayer. AVPlayerItem has a rate variable but it only returns a value between 0 and 2 (usually 1 when playing). Anybody have an idea how to get the video frame rate?

    Cheers

  • Nico
    Nico about 11 years
    nominalFrameRate is the easiest way. Starting from an AVPlayer, you can get its currentItem, then the item's tracks, then every track's assetTrack, then each asset track's nominalFrameRate. Note that movies can have multiple video tracks, and some (audio-only) have no video tracks at all.
  • AddisDev
    AddisDev almost 11 years
    Excellent answer, helped me greatly.
  • AddisDev
    AddisDev over 10 years
    This seems to no longer work in iOS 7. nominalFrameRate is returning 0 for the same video that it returns a correct value in previous iOS versions. Is anyone else experiencing this? I put in a bug report to Apple.
  • Paresh Navadiya
    Paresh Navadiya over 9 years
    @user346443 can please accept the answer as it will help other to find correct answer.
  • Jan
    Jan over 9 years
    for me this returns only 0.0. Running on iOS 8.0
  • Dinesh Iyer
    Dinesh Iyer over 8 years
    I am getting the same behaviour on Yosemite. I have some sample videos at 10 fps and 20 fps. Mavericks reports this correctly. However, on Yosemite, these get reported as 9.9010 and 18.1818 respectively.
  • Crashalot
    Crashalot about 8 years
    Did you solve this? If you encoded the video with 125 frames per second, shouldn't the correct frame rate be 125 and not 1.0 (on iOS 7)?
  • Crashalot
    Crashalot about 8 years
    @DineshIyer would it be invalid to round up the frame rate to the nearest integer?
  • Dinesh Iyer
    Dinesh Iyer about 8 years
    @Crashalot: I do not believe that rounding up is correct in all cases. 29.97 is a common frame rate and rounding up in that case will be wrong. I was surprised why this happens only for Mavericks and higher.