AVPlayer stops playing and doesn't resume again

iAmd picture iAmd · Oct 10, 2013 · Viewed 30.2k times · Source

In my application I have to play audio files stored on a web server. I'm using AVPlayer for it. I have all the play/pause controls and all delegates and observers there which work perfectly fine. On playing small audio files everything works great.

When a long audio file is played it also starts playing fine but after some seconds the AVPlayer pauses the playing (most probably to buffer it). The issue is it doesn't resume on its own again. It keeps in a pause state and if I manually press the play button again it plays smoothly again.

I want to know why AVPlayer doesn't resume automatically and how can I manage to resume the audio again without user pressing the play button again? Thanks.

Answer

Jpellat picture Jpellat · Nov 11, 2013

Yes, it stops because the buffer is empty so it has to wait to load more video. After that you have to manually ask for start again. To solve the problem I followed these steps:

1) Detection: To detect when the player has stopped I use the KVO with the rate property of the value:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"rate"] )
    {

        if (self.player.rate == 0 && CMTimeGetSeconds(self.playerItem.duration) != CMTimeGetSeconds(self.playerItem.currentTime) && self.videoPlaying)
        {
            [self continuePlaying];
        }
      }
    }

This condition: CMTimeGetSeconds(self.playerItem.duration) != CMTimeGetSeconds(self.playerItem.currentTime) is to detect the difference between arriving at the end of the video or stopping in the middle

2) Wait for the video to load - If you continue playing directly you will not have enough buffer to continue playing without interruption. To know when to start you have to observe the value playbackLikelytoKeepUp from the playerItem (here I use a library to observe with blocks but I think it makes the point):

-(void)continuePlaying
 {

if (!self.playerItem.playbackLikelyToKeepUp)
{
    self.loadingView.hidden = NO;
    __weak typeof(self) wSelf = self;
    self.playbackLikelyToKeepUpKVOToken = [self.playerItem addObserverForKeyPath:@keypath(_playerItem.playbackLikelyToKeepUp) block:^(id obj, NSDictionary *change) {
        __strong typeof(self) sSelf = wSelf;
        if(sSelf)
        {
            if (sSelf.playerItem.playbackLikelyToKeepUp)
            {
                [sSelf.playerItem removeObserverForKeyPath:@keypath(_playerItem.playbackLikelyToKeepUp) token:self.playbackLikelyToKeepUpKVOToken];
                sSelf.playbackLikelyToKeepUpKVOToken = nil;
                [sSelf continuePlaying];
            }
                    }
    }];
}

And that's it! problem solved

Edit: By the way the library used is libextobjc