AVPlayer没有触发playbackBufferEmpty事件,但也没有播放

8

我使用AVPlayer通过互联网播放音频直播。如果暂停时间超过1分钟,我想恢复播放。

我调用player.rate = 1.0来恢复播放。然而,如果流被暂停超过1分钟,则不再播放。在这种情况下,我需要重新创建AVPlayerItem才能使其再次工作。

那么我该如何捕获这种情况,以便知道播放没有恢复?

  • 我尝试了对player.rate进行KVO。但它仍然保持为1.0。播放器没有播放!
  • 我尝试了对currentItem.playbackBufferEmpty进行KVO。但在这种情况下它没有被调用。
  • currentItem.status没有切换到.Failed。它根本没有改变。

在这种情况下,AVPlayer似乎什么也没做。有什么想法吗?

我构建了一个Playground代码来演示这个问题:

import UIKit
import AVFoundation

// keep it running forever so it plays audio
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(true)

class AVPlayerTest {

    let player = AVPlayer()
    let streamurl = NSURL(string: "http://detektor.fm/stream/mp3/musik/")!

    func startTest() {
        let item = AVPlayerItem(URL: streamurl)
        player.replaceCurrentItemWithPlayerItem(item)
        player.play()

        // give it some start time to build a buffer
        NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: #selector(timerTickedToPause), userInfo: nil, repeats: false)
    }

    @objc func timerTickedToPause(timer: NSTimer) {
        player.pause()
        // pause now for some time. 90s is not enough.
        NSTimer.scheduledTimerWithTimeInterval(120, target: self, selector: #selector(timerTickedToPlay), userInfo: nil, repeats: false)
    }

    @objc func timerTickedToPlay(timer: NSTimer) {
        // try to resume playback

        print(player.rate)

        player.play()

        print(player.rate)

        // check in some seconds if it recovered
        NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: #selector(timerTickedCheck), userInfo: nil, repeats: false)
    }

    @objc func timerTickedCheck(timer: NSTimer) {

        // it reports rate = 1.0 but is not playing here though!
        // there is no way to know for me it did not recover here!?
        print(player.rate)

        // recover by creating a new item works
        let item = AVPlayerItem(URL: streamurl)
        player.replaceCurrentItemWithPlayerItem(item)
        player.play()
    }
}

let test = AVPlayerTest()
test.startTest()

这看起来是同样的问题:https://dev59.com/45bfa4cB1Zd3GeqPoA99 - funkenstrahlen
是的,完全正确。它可以用于固定(非直播)视频,但在直播中会失败,我总是使用 item :/ 重新初始化播放器。如果这个问题得到解决,请也在我的帖子中发布一下。 - turushan
我完全可以重新创建AVPlayerItem。然而,我需要知道它是否失败了。 - funkenstrahlen
没有时间尝试,但有一个建议,你可以尝试使用player.pause()然后是player.play(),并在此之后检查速率是否为1。 - turushan
我已经在调试器中完成了这个操作。player.pause()player.play() 就像苹果在其文档中所述的那样,相当于将 player.rate 设置为 01。调用 player.rate = 1 后,它不会播放,但 rate 保持在 1 - funkenstrahlen
显示剩余5条评论
1个回答

7
使用AVPlayer实例的timeControlStatus属性,可以“指示当前是否正在播放、无限期暂停或在等待适当的网络条件时被挂起”。
let status = player.timeControlStatus

switch status {
case .paused:
    print("timeControlStatus.paused")

case .playing:
    print("timeControlStatus.playing")

case .waitingToPlayAtSpecifiedRate:
    print("timeControlStatus.waitingToPlayAtSpecifiedRate")
    if let reason = player.reasonForWaitingToPlay {

        switch reason {
        case .evaluatingBufferingRate:
            print("reasonForWaitingToPlay.evaluatingBufferingRate")

        case .toMinimizeStalls:
            print("reasonForWaitingToPlay.toMinimizeStalls")

        case .noItemToPlay:
            print("reasonForWaitingToPlay.noItemToPlay")

        default:
            print("Unknown \(reason)")
        }
    }

}

我也遇到了同样的问题,但在我的情况下,当我处于暂停状态时进入后台,当我回到前台时,.play()方法不起作用。它会卡在waitingToPlayAtSpecifiedRate.evaluatingBufferingRate模式下。

此时,AVPlayerItem.status实例已经是readToPlay。

目前,在收到startCommand时,我重置了AVPlayer以确保正常播放。但这种解决方法并不完美。寻找更加优秀的解决方案。


以前不知道 timeControlStatus,但它似乎像魔法一样工作,非常好的答案! - Benjamin Jimenez
我不得不在AVPlayer中重新加载资产,因为出现了同样的问题。这一定与流属性有关。我正在播放来自一个提供者的音频流 - 在中断后它们可以正常播放。来自另一个提供者的流在中断后永远无法播放(如果有人发现这些信息相关,则它们是VAST广告)。 - thedazed

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