暂停后,AVPlayer无法恢复+等待

时间:2016-04-14 08:11:02

标签: swift swift2 avplayer

.pause()如果我调用.play()确定它继续但是如果我在.pause()之后等待30-60秒并尝试.play()它有时无法播放,

  • AVPlayerStatus.Failed返回false

  • AVPlayerStatus.ReadyToPlay返回true

我应该使用url重新初始化播放器以使其正常工作。 现在我想这样做,如果玩家可以玩,我想只调用.play()但是如果没有,我想重新初始化它,我的问题是如何检测玩家是否可玩?顺便说一下,它是一个扩展名为.pls的无线电链接

3 个答案:

答案 0 :(得分:1)

实际上并没有迹象表明在很长一段时间后球员处于不稳定状态时恢复。 (除非在我的测试中我看到在这种情况下从AVPlayerItem接收的元数据为空)

无论如何..从我从互联网上收集到的内容(此处没有适当的文档),当你暂停时,播放器会在后台保持缓冲,如果你试图恢复50-60秒之后它就不能了。停止功能在这里会很好。

我的解决方案: 一个简单的计时器,用于检查50秒是否通过,如果是,则更新标志,以便知道在调用resume方法时我想要在新的播放器上启动。

func pausePlayer() {
   ..
    player.pause()
   ..

    // Will count to default 50 seconds or the indicated interval and only then set the bufferedInExcess flag to true
    startCountingPlayerBufferingSeconds()
    bufferedInExcess = false
}


func startCountingPlayerBufferingSeconds(interval: Double = 50) {
    timer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: Selector("setExcessiveBufferedFlag"), userInfo: nil, repeats: false)
}

func setExcessiveBufferedFlag() {
    if DEBUG_LOG {
        print("Maximum player buffering interval reached.")
    }
    bufferedInExcess = true
}

func stopCountingPlayerBufferingSeconds() {
    timer.invalidate()
}

func resumePlayer() {
    if haveConnectivity() {
        if (.. || bufferedInExcess)  {
            startPlaying(true)
        } else {
            ..
            player.play
        }
       ..
    }
}

func startPlaying(withNewPlayer: Bool = false) {
    if (withNewPlayer) {
        if DEBUG_LOG {
            print("Starting to play on a fresh new player")
        }

        // If we need another player is very important to fist remove any observers for
        // the current AVPlayer/AVPlayerItem before reinitializing them and add again the needed observers
        initPlayer()

        player.play()
        ...
    }
    ...
}

答案 1 :(得分:1)

假设您在发出.play()之前检查过AVPlayerItem.status ==。playable

然后使用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)")
        }
    }

}

在我的情况下,它会遇到waitingToPlayAtSpecifiedRate.evaluatingBufferingRate模式。 此时,AVPlayerItem.status实例是readToPlay。

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

答案 2 :(得分:0)

我在目标c上发布我的解决方案。所以我在按下暂停按钮时添加了一个计时器,如果那个计时器在85秒后触发(在那些秒缓冲停止之后),那么我将布尔值设置为YES,并且当恢复音频时如果该布尔值为YES则我创建一个新的播放器。

-(void)play{
if (self.player){

    if (self.bufferingExpired){
        self.bufferingExpired = NO;
        [self initializePlayerWithStation:self.currentStation];
    }else{
        [self.player play];
    }

    [self.resumeTimer invalidate];
    self.resumeTimer = nil;
    }

}

-(void)pause{

    if (self.player){
        [self.player pause];
        [[NSNotificationCenter defaultCenter]postNotificationName:kNotificationAudioPaused object:nil];
        self.resumeTimer = [NSTimer scheduledTimerWithTimeInterval:kResumeStreamingTimer target:self selector:@selector(addNewPlayerItemWhenResuming) userInfo:nil repeats:NO];
    }

}

-(void)addNewPlayerItemWhenResuming{
    self.bufferingExpired = YES;
}

-(void)initializePlayerWithStation:(RadioStation*)station{
    _currentStation = station;
    _stream_url = station.url;

    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:_stream_url];

    if (self.player != nil){
        [[self.player currentItem] removeObserver:self forKeyPath:@"status"];

    }

    [item addObserver:self forKeyPath:@"status" options:0 context:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemFailedToPlayToEndTime:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:item];

    self.player = [AVPlayer playerWithPlayerItem:item];

}