IOS AVPlayer获得fps

IOS AVPlayer获得fps,ios,avplayer,frame-rate,Ios,Avplayer,Frame Rate,我想知道如何通过AVPlayer检索视频帧速率。AVPlayerItem有一个速率变量,但它只返回0到2之间的值(播放时通常为1)。有人知道如何获得视频帧速率吗 干杯在AVPlayer中,我不知道任何可以帮助您计算帧速率的东西 AVPlayerItemrate属性是播放速率,与帧速率无关 更简单的选择是获取AVAssetTrack并读取其nominalFrameRate属性。只要创建一个AVAsset,你就会得到一组曲目 或者使用avassetrack逐帧读取视频,获取其显示时间并计算同一秒中有

我想知道如何通过AVPlayer检索视频帧速率。AVPlayerItem有一个速率变量,但它只返回0到2之间的值(播放时通常为1)。有人知道如何获得视频帧速率吗


干杯

AVPlayer
中,我不知道任何可以帮助您计算帧速率的东西

AVPlayerItem
rate
属性是播放速率,与帧速率无关


更简单的选择是获取
AVAssetTrack
并读取其
nominalFrameRate
属性。只要创建一个
AVAsset
,你就会得到一组曲目


或者使用
avassetrack
逐帧读取视频,获取其显示时间并计算同一秒中有多少帧,然后平均几秒钟或整个视频。

使用
avassetrack的
属性

下面是获取
帧率的方法:这里
queuePlayer
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;
}

对于在不同版本的iOS上播放的相同媒体,返回的标称帧率似乎存在差异。我有一个视频,我用ffmpeg以每秒1帧(125帧)的速度编码,每25帧有一个关键帧,在iOS 7.x上加载应用程序时,(标称)帧速率为1.0,而在iOS 8.x上(标称)帧速率为0.99。这似乎是一个非常小的差异,但是在我的例子中,我需要精确地导航到电影中的给定帧,而这种差异会破坏这种导航(电影是一系列演示幻灯片的编码)。鉴于我已经知道我的应用程序需要播放的视频的帧速率(例如1 fps),我可以简单地依赖这个值,而不是动态地(通过nominalFrameRate值)确定帧速率,但是我想知道为什么iOS版本之间会有如此大的差异。有什么想法吗?

AVPlayer上的速率值是相对于播放实时的速度,例如0.5是慢动作,2是双倍速度

正如帕雷什·纳瓦迪亚指出的那样,轨迹也有一个nominalFrameRate变量,但这似乎有时会给出奇怪的结果。到目前为止,我找到的最佳解决方案是使用以下方法:

CMTime frameDuration = [myAsset tracksWithMediaType:AVMediaTypeVideo][0].minFrameDuration;
float fps = frameDuration.timescale/(float)frameDuration.value;
上面给出了对于可变帧速率的稍微出乎意料的结果,但是可变帧速率无论如何都有稍微奇怪的行为。除此之外,它在我的测试中匹配ffmpeg-i

编辑----


我发现有时上面给出的时间kCMTimeZero。我使用的解决方法是创建一个带有轨迹输出的Avassetrader,获取第一帧和第二帧的pts,然后将两者相减。

Swift 4版本的答案:

let asset = avplayer.currentItem.asset

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

let fps = tracks?.first?.nominalFrameRate

请记住处理零检查。

这将不再有效,API已更改,此帖子已过时( swift 4答案也很酷,这是答案相似

您可以从
AVPlayerItem
获取视频曲目,并在那里检查FPS。:)

private var numberOfRenderingFailures=0
func isVideoRendering()->Bool{
guard let currentItem=player.currentItem else{return false}
//检查我们是否正在播放视频曲目
让isRendering=currentItem.tracks.contains{($0.assetTrack?.mediaType==.video)&($0.currentVideoFrameRate>5)}
如果是招标{
numberOfRenderingFailures=0
返回真值
}
numberOfRenderingFailures+=1
如果渲染失败次数<5{
返回真值
}
返回错误
}

nominalFrameRate
是最简单的方法。从AVPlayer开始,您可以获取其
currentItem
,然后获取该项目的
曲目
,然后获取每个曲目的
assetTrack
,然后获取每个曲目的
名义帧率
。请注意,电影可以有多个视频曲目,有些(仅音频)根本没有视频曲目。回答得很好,对我帮助很大。这在iOS 7中似乎不再适用。nominalFrameRate对于在以前的iOS版本中返回正确值的同一视频返回0。还有其他人经历过这种情况吗?我向苹果公司提交了一份错误报告。@user346443可以接受这个答案,因为它将帮助其他人找到正确的答案。对我来说,这个结果只返回0.0。在iOS 8.0上运行,我在优胜美地上也有同样的表现。我有一些10帧和20帧的视频样本。小牛队正确地报告了这一点。然而,在约塞米蒂,这些分别被报告为9.9010和18.1818。你解决了这个问题吗?如果您以每秒125帧的速度对视频进行编码,那么正确的帧速率不应该是125而不是1.0(在iOS 7上)?@DineshIyer将帧速率四舍五入到最接近的整数是否无效?@Crashalot:我不相信四舍五入在所有情况下都是正确的。29.97是常见的帧速率,在这种情况下,四舍五入是错误的。我很惊讶为什么这只发生在小牛和更高级别的球员身上。
private var numberOfRenderingFailures = 0
func isVideoRendering() -> Bool {
    guard let currentItem = player.currentItem else { return false }

    // Check if we are playing video tracks
    let isRendering = currentItem.tracks.contains { ($0.assetTrack?.mediaType == .video) && ($0.currentVideoFrameRate > 5) }
    if isRendering {
        numberOfRenderingFailures = 0
        return true
    }
    numberOfRenderingFailures += 1
    if numberOfRenderingFailures < 5 {
        return true
    }
    return false
}