7

我正在使用 AVPlayer 流式传输音频。它运作良好。但现在我需要制作一个滑块来前后移动音频,就像典型的音乐播放器一样。我使用了seekToTime非常适用于本地音频文件的功能。但是当我从 web url 流式传输歌曲时,当我转发大范围的滑块时,该功能会停止音频。

我的猜测是歌曲正在被下载,如果我将滑块向前移动大范围,那么可能是系统在那段时间没有下载歌曲数据包,所以它会停止播放器。

可以说我只是按了一个按钮来播放歌曲,但现在我在 0 到 100 秒时立即移动滑块。在这种情况下,系统不工作并停止播放器。由于当时缺少数据包。

有谁知道如何克服这个问题或有任何其他方法。我正在使用 SWIFT 进行开发。如果它可以快速工作,我也愿意使用任何库。这是我的功能:

func forward () {
    timeGap = slider.value
    let preferredTimeScale : Int32 = 1
    let targetTime : CMTime = CMTimeMake(timeGap, preferredTimeScale)

    player.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

}

提前致谢。

4

1 回答 1

9

这个答案很大程度上基于这个:https ://stackoverflow.com/a/7195954/765298 。任何和所有的功劳都应该去那里,因为这只是对 swift 的翻译。

您可以正确地假设,当向前寻找尚未缓冲但播放器停止的部分时。问题是它仍然缓冲数据,但在准备好时不会自动启动。因此,将链接的答案改写为 swift :

要设置您的观察者:

player.currentItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .New, context: nil)
player.currentItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .New, context: nil)

请注意,为了能够观察值,传递的值self需要继承自NSObject.

并处理它们:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

    guard keyPath != nil else { // a safety precaution
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
        return
    }

    switch keyPath! {
        case "playbackBufferEmpty" :
            if player.currentItem!.playbackBufferEmpty {
                print("no buffer")
                // do something here to inform the user that the file is buffering
            }

        case "playbackLikelyToKeepUp" :
            if player.currentItem!.playbackLikelyToKeepUp {
                self.player.play()
                // remove the buffering inidcator if you added it
            }
    }
}

您还可以从当前播放中获取有关可用时间范围的信息(如果您没有自己创建,AVPlayerItem您可以通过它访问它)。player.currentItem这使您能够向用户指示文件的哪些部分已准备就绪。

与往常一样,您可以在文档中阅读更多内容:AVPlayerItemAVPlayer

要阅读有关键值观察 (KVO) 的更多信息:这里

于 2015-11-27T12:23:06.497 回答