【问题标题】:SeekToTime in AVPlayer stops playing streaming audio, when forwardAVPlayer 中的 SeekToTime 在转发时停止播放流音频
【发布时间】:2016-02-25 14:29:43
【问题描述】:

我正在使用 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)

}

提前致谢。

【问题讨论】:

    标签: ios swift avplayer audio-streaming seektotime


    【解决方案1】:

    这个答案很大程度上基于这个: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) 的信息:here

    【讨论】:

    • 我注意到,当我开始一个实时视频流时,缓冲区从一开始就是空的 (playbackBufferEmpty == true),playbackBufferEmpty 标志永远不会将其状态更改为 false。有没有办法使用 AVFoundation 手动开始缓冲?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    相关资源
    最近更新 更多