【问题标题】:IOS AVPlayer get fpsIOS AVPlayer获取fps
【发布时间】:2012-05-19 16:16:28
【问题描述】:

我试图弄清楚如何通过 AVPlayer 检索视频帧速率。 AVPlayerItem 有一个 rate 变量,但它只返回一个介于 0 和 2 之间的值(播放时通常为 1)。有人知道如何获得视频帧速率吗?

干杯

【问题讨论】:

    标签: ios avplayer frame-rate


    【解决方案1】:

    使用AVAssetTrack'snominalFrameRateproperty

    获取FrameRate的方法如下:这里queuePlayerAVPlayer

    -(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 7。nominalFrameRate 为相同的视频返回 0,它在以前的 iOS 版本中返回正确的值。还有其他人遇到这种情况吗?我向 Apple 提交了错误报告。
    • @user346443 可以请接受答案,因为它会帮助其他人找到正确的答案。
    • 对我来说这只返回 0.0。在 iOS 8.0 上运行
    【解决方案2】:

    Swift 4 版本的答案:

    let asset = avplayer.currentItem.asset
    
    let tracks = asset.tracks(withMediaType: .video)
    
    let fps = tracks?.first?.nominalFrameRate
    

    记得处理 nil 检查。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我在优胜美地得到了同样的行为。我有一些 10 fps 和 20 fps 的示例视频。小牛队正确地报告了这一点。但是,在 Yosemite 上,它们分别报告为 9.9010 和 18.1818。
      • 你解决了吗?如果您以每秒 125 帧的速度对视频进行编码,那么正确的帧速率不应该是 125 而不是 1.0(在 iOS 7 上)吗?
      • @DineshIyer 将帧速率四舍五入到最接近的整数是否无效?
      • @Crashalot:我不认为四舍五入在所有情况下都是正确的。 29.97 是一个常见的帧速率,在这种情况下四舍五入是错误的。我很惊讶为什么这只发生在小牛队和更高的队。
      【解决方案4】:

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

      正如 Paresh Navadiya 指出的那样,轨道也有一个nominalFrameRate 变量,但这似乎有时会产生奇怪的结果。到目前为止,我发现的最佳解决方案是使用以下方法:

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

      上面给出了可变帧速率的稍微意外的结果,但可变帧速率无论如何都会有一些奇怪的行为。除此之外,它在我的测试中与 ffmpeg -i 匹配。

      编辑----

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

      【讨论】:

        【解决方案5】:

        我不知道AVPlayer 中的任何内容可以帮助您计算帧速率。

        AVPlayerItemrate属性为播放速率,与帧率无关。

        更简单的选择是获取AVAssetTrack 并读取其nominalFrameRate 属性。只需创建一个AVAsset,您将获得一系列曲目。

        或使用AVAssetReader逐帧读取视频,获取其呈现时间并计算同一秒内有多少帧,然后平均几秒钟或整个视频。

        【讨论】:

        • nominalFrameRate 是最简单的方法。从 AVPlayer 开始,您可以获取其 currentItem,然后是项目的 tracks,然后是每个轨道的 assetTrack,然后是每个资产轨道的 nominalFrameRate。请注意,电影可以有多个视频轨道,有些(仅音频)根本没有视频轨道。
        【解决方案6】:

        这行不通了,API 已经改变,而且这篇文章已经过时了。 :( swift 4的答案也很酷,这个答案是相似的。

        您从AVPlayerItem 获取视频轨道,然后检查那里的 FPS。 :)

        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
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-22
          • 2015-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多