【问题标题】:How do you get smooth high-rate playback from AVPlayer?如何从 AVPlayer 获得流畅的高速播放?
【发布时间】:2015-08-01 12:11:13
【问题描述】:

AVPlayer 有一个名为rate 的属性,用于控制播放速率。 1.0 是正常速度,而 2.05.0 等值应分别以 2x 和 5x 播放。

每当我将播放速率值设置为高于1.0(比如10.0)时,播放就会非常断断续续,并且由于播放器跟不上,看起来大量帧正在丢失。

但是,QuickTime Player 中的相同值(对于同一部电影)可以在 2x, 5x, 10x, 30x and 60x 的速率下产生流畅的播放(由 QuickTime Player 报告)。

我创建了一个测试 OS X 应用程序,它只包含一个 AVPlayerView 和两个用于设置播放速率的按钮。 1.0 的速率按预期工作,但 10.0 的速率会产生非常不稳定的播放。

但是,AVPlayerView 有一个奇怪的怪癖,如果您在播放时间轴上单击鼠标以寻找另一个位置(当它以 10 倍的速度播放并且断断续续时),那么 AVPlayerView 将“修复”播放电影将以 10 倍流畅播放。只需点击播放时间线即可。

有谁知道如何以 1x 以外的速率获得流畅的播放?这显然不是硬件问题或文件大小问题,因为 QuickTime Player 和 AVPlayerView 都可以做到。

尝试

这个question 表明这可能是一个音频问题(事实上,QuickTime Player 和 AVPlayerView 在转发时都会使音频静音),但我尝试禁用所有音轨、静音所有音轨或更改音频音高算法似乎没有什么不同。即使没有音频,播放仍然断断续续。

我也尝试过停止播放,然后使用新的速率调用 prerollAtRate:completionHandler,但这也没有什么不同。

QuickTime Player 和 AVPlayerView 是如何实现以 10x、30x 甚至 60x 的速率流畅播放电影的?

【问题讨论】:

  • 你找到解决这个问题的方法了吗?如果是,那是什么?
  • 不,抱歉。我最终不得不构建自己的解决方案,但它并没有我想要的那么好。从长远来看,我认为最好的播放体验需要更深入地挖掘并在使用 AVPlayer 之外处理帧解码。
  • 在 macos 10.12.3/Xcode 8.2.1 下,我已经确认了以上几点:速度高达 2.0 没有问题,但将 AVPlayer.rate 设置为大于 2.0 的值会导致播放断断续续;使用 AVPlayerView 更改播放速率可实现所有速度的流畅播放;首先将速率设置为 0.0,然后调用 prerollAtRate(atRate:, completionHandler:) 并在完成处理程序中将速率设置为高并不能解决问题;仅使用视频轨道创建 AVMutableComposition 不能解决问题;禁用音轨并不能解决问题。
  • 还可能值得注意的是,这显然是 AVFoundation 的一个黑暗角落,即使对于 Apple 的文档人员来说也是如此:AVSimplePlayerOSX 示例代码提供了一个快进按钮来显示此问题。

标签: macos cocoa avfoundation avplayer appkit


【解决方案1】:

这只是一种解决方法。

当播放速率从 0.0 更改为较大值时,如果这是自上次调用 AVPlayer.replaceCurrentItem 以来播放速率的第一个零到非零的转换,则播放流畅(并且音频自动静音)。这是必要的第一个这样的转换:仅仅先将速率设置为 0.0,然后再设置为所需的速率是行不通的。

因此,例如,这将在高速下产生流畅的播放:

func setPlayerRate(player: AVPlayer, rate: Float) {
    // AVFoundation wants us to do most things on the main queue.
    DispatchQueue.main.async {
        if (rate == player.rate) {
            return
        }
        if (rate > 2.0 || rate < -2.0) {
            let playerItem = player.currentItem
            player.replaceCurrentItem(with: nil)
            player.replaceCurrentItem(with: playerItem)
            player.rate = rate
        } else {
            // No problems "out of the box" with rates in the range [-2.0,2.0].
            player.rate = rate
        }
    }
}

【讨论】:

  • 换出 AVPlayerItem 或重新定时 AVComposition 中的媒体轨道都是有效的(如果不是严厉的话)获得更流畅播放的方法。但是,如果您希望允许用户在实时播放期间更改播放速率,它们并不是很好的解决方案。这种行为在具有“慢速”拨盘的视频应用程序中很常见。 QuickTime Player 的自省表明(尽管尚未证实)对于某些播放速率,它会重复调用 seekTime...,可能会依赖自定义 timeBase,并且可能会进行一些解码/缓存技巧以获得更好的性能。
  • ...轻松改变播放速度确实是我想做的事情!既然你提到了它,我构建了一个显示电影预览的东西,就像 Final Cut Pro X 一样,当你将鼠标悬停在它们上面时,缩略图中的单元格会显示视频。我感到很沮丧,它运行得这么好,即使是在到处乱扔鼠标的时候,但事实并非如此。我只是不够聪明,无法考虑以这种方式应用 seekTime。谢谢!我会试试这个。这也将规避高速播放时某些通知丢失的错误。
  • 对于用户只需在其上移动鼠标即可浏览的小型视频缩略图,通过调整您所寻求的时间和允许的容差,您可能会获得足够的性能。如果您寻找“关键帧”而不是任意时间,解码几乎是瞬时的。由于时间精度在视频预览中并不重要,因此您可能需要考虑调整您寻求的时间,使其落在关键帧上或非常接近关键帧。有关使用 AVSampleCursor 识别关键帧的更多详细信息,请参阅技术说明 TN2404
猜你喜欢
  • 2011-09-20
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
相关资源
最近更新 更多