swift2 AVPlayer在暂停+一些等待后无法恢复

2vuwiymt  于 2022-11-06  发布在  Swift
关注(0)|答案(3)|浏览(208)

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

  • AVPlayerStatus.失败返回假
  • AVPlayerStatus.ReadyToPlay返回真

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

pcrecxhr

pcrecxhr1#

实际上,没有任何迹象表明,当恢复后很长一段时间的播放器是在地狱。(除了在我的测试中,我看到,在这种情况下,从AVPlayerItem收到的 meta是空的)
无论如何..从我从互联网上收集的(没有适当的文档),当你暂停,播放器将继续在后台缓冲..如果你试图恢复后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()
        ...
    }
    ...
}
mznpcxlj

mznpcxlj2#

假设您在发出.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以确保万无一失。但这似乎很笨重。正在寻找一个更流畅的解决方案。

xurqigkl

xurqigkl3#

我在目标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];

}

相关问题