Macos 如何从AVPlayer获得平滑的高速播放?

Macos 如何从AVPlayer获得平滑的高速播放?,macos,cocoa,avfoundation,avplayer,appkit,Macos,Cocoa,Avfoundation,Avplayer,Appkit,AVPlayer有一个名为rate的属性,用于控制播放速率1.0为正常速度,而2.0或5.0等值应分别以2倍和5倍的速度播放 每当我将播放速率值设置为高于1.0(比如10.0)时,播放会非常不平稳,而且由于播放器无法跟上,看起来大量帧被丢弃 但是,QuickTime Player中的相同值(使用相同的电影)会以2x、5x、10x、30x和60x的速率平滑播放(正如QuickTime Player所报告的那样) 我创建了一个测试OSX应用程序,它只包含一个AVPlayerView和两个用于设置播放

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

每当我将播放速率值设置为高于
1.0
(比如
10.0
)时,播放会非常不平稳,而且由于播放器无法跟上,看起来大量帧被丢弃

但是,QuickTime Player中的相同值(使用相同的电影)会以
2x、5x、10x、30x和60x的速率平滑播放(正如QuickTime Player所报告的那样)

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

然而,
AVPlayerView
有一个奇怪的怪癖,如果你用鼠标点击播放时间线来寻找另一个位置(当它以10倍的速度播放时),那么
AVPlayerView
将“修复”播放,电影将以10倍的速度平稳播放。只需点击播放时间线

有人知道如何在1x以外的速率下实现平滑播放吗?这显然不是硬件问题或文件大小问题,因为QuickTime Player和AVPlayerView都可以做到这一点

尝试

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

我还尝试停止播放,然后用新的速率调用
prerollAtRate:completionHandler
,但这也没有什么区别


QuickTime Player和AVPlayerView正在做什么,以10倍、30倍甚至60倍的速度平滑播放电影?

这只是一个解决办法

当播放速率从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
        }
    }
}
func setPlayerRate(播放器:AVPlayer,速率:Float){
//AVFoundation希望我们在主队列上完成大部分工作。
DispatchQueue.main.async{
如果(速率==玩家速率){
返回
}
如果(速率>2.0 | |速率<-2.0){
让playerItem=player.currentItem
player.replaceCurrentItem(带:nil)
player.replaceCurrentItem(带:playerItem)
player.rate=速率
}否则{
//“开箱即用”的费率在[-2.0,2.0]范围内没有问题。
player.rate=速率
}
}
}

您找到这个问题的解决方案了吗?如果是,那是什么?不,对不起。我最终不得不构建自己的解决方案,但它没有我想要的那么好。从长远来看,我认为最好的播放体验需要更深入的挖掘,并在使用AVPlayer之外处理帧解码。在macos 10.12.3/Xcode 8.2.1下,我已经证实了上述一些:速度高达2.0不会出现问题,但设置
AVPlayer。速率
大于2.0会导致播放不平稳;使用AVPlayerView更改播放速率可使所有速度的播放都平滑;首先将速率设置为0.0,然后调用
prerollatate(atRate:,completionHandler:)
并在完成处理程序中设置较高的速率,但这并不能解决问题;仅使用视频曲目创建AVMutableComposition无法解决问题;禁用音轨并不能解决问题。同样值得注意的是,这显然是AVFoundation的一个黑暗角落,即使对于苹果的文档编制人员来说也是如此:AVSimplePlayerOSX示例代码提供了一个显示此问题的快进按钮。可能重复交换AVPlayerItem,或者在AVComposition中对媒体曲目进行重新计时,这两种方法都是有效的,即使不是很费力,也能使播放更加流畅。但是,如果您希望允许用户在实时播放过程中更改播放速率,那么它们并不是很好的解决方案。这种行为在具有“点动”拨号的视频应用程序中很常见。QuickTime Player的自省表明(尽管尚未确认),对于某些播放速率,它会重复调用
seekTime…
,很可能是摆脱了一个自定义的时基,可能是为了更好的性能做了一些解码/缓存的技巧……而轻松地改变播放速度确实是我希望能够做到的事情!既然你提到了这一点,我还构建了一个东西,它可以像Final Cut Pro X一样显示电影预览,当你将鼠标放在它们上面时,缩略图中的单元格会显示视频。我感到沮丧的是,它工作得如此之好,即使在扔鼠标的时候,但事实并非如此。我只是不够聪明,没有想到用这种方式应用seekTime。谢谢我要试试这个。这也将避免在高速播放时丢失某些通知的错误。对于用户只需在其上移动鼠标即可通过的小视频缩略图,通过播放您寻求的时间和允许的公差,您可能会获得足够的性能。如果你寻找一个“关键帧”,而不是一个任意的时间,解码几乎是瞬间的。因为定时精度在一个系统中并不重要