Avplayer Stops Playing Video After Buffering

AVPlayer stops playing video after buffering

Since iOS 10.x, you can make some buffer settings, for example you can decide how many seconds you'll need to buffering your video:

    if #available(iOS 10.0, tvOS 10.0, OSX 10.12, *) {
avPlayer?.automaticallyWaitsToMinimizeStalling = .playWhenBufferNotEmpty
//preferredForwardBufferDuration -> default is 0, which means `AVPlayer` handle it independently, try more seconds like 5 or 10.
playerItem.preferredForwardBufferDuration = TimeInterval(5)
}

AVPlayer stops playing and doesn't resume again

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

AVPlayer audio out of sync after seek

I resolved it by switching from mp4 to m3u8.
m3u8 is a playlist information file so I was then able to stream from cloudinary instead.



Related Topics



Leave a reply



Submit