在 AVPlayer 中使用 SeekToTime 函数向前跳转时,流媒体音频将停止播放

7
我正在使用AVPlayer进行音频流传输,效果不错。但现在我需要制作一个滑块来向前或向后移动音频,就像典型的音乐播放器一样。我使用了seekToTime函数,可以在本地音频文件上很好的工作。但是当我从Web URL流式播放歌曲时,如果我将滑块向前移动大范围,则该函数会停止音频。

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

比如说我只是按下一个按钮来流式播放歌曲,但现在我立即将滑块移动到0秒至100秒。在这种情况下,系统无法工作,会停止播放器,因为缺少那个时间段的数据包。

有人知道如何解决这个问题吗?还是有其他方法?我正在使用SWIFT进行开发。如果需要,我也可以使用任何库,只要它能在SWIFT中运行。这是我的函数:
func forward () {
    timeGap = slider.value
    let preferredTimeScale : Int32 = 1
    let targetTime : CMTime = CMTimeMake(timeGap, preferredTimeScale)

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

}

提前致谢。

1个回答

9
这篇答案的内容主要基于这个链接:https://dev59.com/mWw15IYBdhLWcg3wA3GT#7195954,所有功劳应归于原作者,这只是一篇翻译成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)的更多信息,请单击此处:here

我注意到当我开始实时视频流时,缓冲区从一开始就是空的( playbackBufferEmpty == true ),并且 playbackBufferEmpty 标志永远不会改变其状态为 false。是否有一种使用 AVFoundation 手动启动缓冲的方法? - schmittsfn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接