8

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

我打电话player.rate = 1.0恢复。但是,如果流暂停 > 1 分钟,则不再播放。在这种情况下,我需要重新创建 AVPlayerItem 以使其再次工作。

那么我怎样才能抓住这种情况,让我知道播放没有恢复呢?

  • 我在player.rate. 虽然它停留在1.0。玩家不玩了!
  • 我在currentItem.playbackBufferEmpty. 但在这种情况下不会调用它。
  • 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()
4

1 回答 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.evalatingBufferingRate 模式。此时 AVPlayerItem.status 实例为 readToPlay。

在撰写本文时,每当收到 startCommand 时,我都会重置 AVplayer 以确保。但这似乎很笨拙。寻找更顺畅的解决方案。

于 2018-03-27T04:22:32.940 回答