AVPlayer暂停后不能恢复播放并出现等待时间问题

7

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

  • AVPlayerStatus.Failed返回false

  • AVPlayerStatus.ReadyToPlay返回true

我应该重新初始化带有url的播放器才能让它工作。现在我想要这样做,如果播放器可以播放,我想要只调用.play(),但如果不能播放,我想要重新初始化它,我的问题是如何检测播放器是否可播放?顺便说一下,它是一个带有.pls扩展名的广播链接。


我相信状态检查是在那60秒延迟之后完成的,对吗? - sailens
是的,我确实在60秒暂停后进行了这两个检查。 - turushan
我认为我正在遇到同样的问题:https://dev59.com/fZbfa4cB1Zd3GeqPt3S3 - funkenstrahlen
@AliKıran即使 .play() 也无法工作,所以寻找任何时间也没有帮助。 - turushan
你找到了解决问题的方法吗? - Yuchen
显示剩余2条评论
3个回答

1

事实上,在长时间暂停后恢复播放时,并没有迹象表明播放器处于中间状态。 (除了在我的测试中,我发现在这种情况下从AVPlayerItem接收到的元数据为空)

不管怎样...从我从互联网上搜集到的信息来看(并没有适当的文档),当您暂停时,播放器将在后台继续缓冲...如果您在50-60秒后尝试恢复它,它就无法做到。在这里,停止功能会很有用。

我的解决方案: 设置一个简单的定时器,检查是否已经过了那50秒,并且如果是,则更新标志以知道在调用恢复方法时,我想要从新的播放器开始。

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()
        ...
    }
    ...
}

0

我正在发布我的Objective-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];

}

0
假设您在发出.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时,我都会重置AVplayer以确保播放。但这似乎很笨重。寻找更流畅的解决方案。

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