Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift AVPlayer可以';t暂停后继续+;一些等待_Swift_Swift2_Avplayer - Fatal编程技术网

Swift AVPlayer可以';t暂停后继续+;一些等待

Swift AVPlayer可以';t暂停后继续+;一些等待,swift,swift2,avplayer,Swift,Swift2,Avplayer,在.pause()之后,如果我调用.play(),它会继续,但如果我在.pause()之后等待30-60秒,然后尝试.play(),它有时会无法播放 AVPlayerStatus.Failed返回false AVPlayerStatus.ReadyToPlay返回true 我应该用url重新初始化播放器以使其工作。 现在我想这样做,如果播放器可以播放,我只想调用.play(),但如果不能,我想重新初始化它,我的问题是如何检测播放器是否可以播放?顺便说一句,它是一个带有.pls扩展名的无线电链

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

  • AVPlayerStatus.Failed返回false

  • AVPlayerStatus.ReadyToPlay返回true

我应该用url重新初始化播放器以使其工作。
现在我想这样做,如果播放器可以播放,我只想调用.play(),但如果不能,我想重新初始化它,我的问题是如何检测播放器是否可以播放?顺便说一句,它是一个带有.pls扩展名的无线电链接,确实没有迹象表明,当在一段长时间后恢复时,玩家处于不稳定状态。 (除了在我的测试中,我看到在这种情况下,从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()
        ...
    }
    ...
}
-(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];

}

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

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

}

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

然后使用AVPlayer实例的timeControlStatus,该实例“指示播放当前是否正在进行、是否无限期暂停,或是在等待适当的网络条件时暂停。”

在我的例子中,它被困在WaitingToplayatsSpecifiedRate.evaluatingBufferingRate模式。 此时,AVPlayerItem.status实例为readToPlay


在写这篇文章的时候,无论何时收到startCommand,我都会重置AVplayer以确保安全。但这看起来很笨重。正在寻找更平滑的解决方案。

我相信状态检查是在60秒延迟后完成的,对吗?是的,我确实在60秒暂停后进行了这两项检查。我不知道为什么会发生这种情况:我想我面临的是同一个问题:您没有重新初始化,而是尝试查找currentTime?