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.
First I observe for playback stalling
Then I force playback continuation
This is probably not the best way of doing it, but I'm using it until I find something better :)
I am working with video files, so there's more to my code than you need, but the following solution should pause the player when it hangs, then check every 0.5 second to see whether we've buffered enough to keep up. If so, it restarts the player. If the player hangs for more than 10 seconds without restarting, we stop the player and apologize to the user. This means you need the right observers in place. The code below is working pretty well for me.
properties defined / init'd in a .h file or elsewhere:
partial .m:
Hope it helps!
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:
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 middle2) 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):And that's it! problem solved
Edit: By the way the library used is libextobjc
in very bad network
playbackLikelyToKeepUp
most probably to be false.use
kvo
to observeplaybackBufferEmpty
is better, more sensitive to if existing buffer data that can be used for playback .if the value change to true you can call play method to continue playback.I had a similar issue. I had some local files i wanted to play, configured the AVPlayer and called [player play], the player stops at frame 0 and wouldn't play anymore until i called play again manually. The accepted answer was impossible for me to implement due to faulty explanation, then i just tried delaying the play and magically worked
For web videos i also had the problem, i solve it using wallace's answer.
When creating the AVPlayer add an observer:
}
Remember to remove observer before dismissing the view
Accepted answer gives a possible solution to the problem, but it lacks flexibility, also it's hard to read. Here's more flexible solution.
Add observers:
Handler:
Magic:
The "[self availableDuration]" is optional, but you can manually launch playback based on amount of video available. You can change how often the code checks whether enough video is buffered. If you decide to use the optional part, here's the method implementation:
Don't forget the cleanup. Remove observers:
And possible pending calls to handle stalled video: