首页 文章

AVPlayer不会触发playbackBufferEmpty,但也不会播放

提问于
浏览
7

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

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

所以 how can I catch this case, so I know the playback did not recover?

  • 我在 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()

1 回答

  • 2

    使用"indicates whether playback is currently in progress, paused indefinitely, or suspended while waiting for appropriate network conditions."的AVPlayer实例"indicates whether playback is currently in progress, paused indefinitely, or suspended while waiting for appropriate network conditions."

    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)")
            }
        }
    
    }
    

    我有同样的问题但在我的情况下,如果我在暂停状态下进入后台,则会发生这种情况 . 当我回到forground .play()不起作用 . 它会遇到waitingToPlayAtSpecifiedRate.evaluatingBufferingRate模式 . 此时,AVPlayerItem.status实例是readToPlay .

    在收到startCommand时写入此时,我重置AV播放器以确保 . 但这似乎很笨拙 . 寻找更顺畅的解决方案 .

相关问题