I have an AVPlayer that is used to play an HLS audio stream using the following code.
var playerItem: AVPlayerItem?
var player: AVPlayer?
func playStream(_ stream: String) {
let url = URL(string: stream)!
let asset = AVAsset(url: url)
playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: requiredAssetKeys)
player = AVPlayer(playerItem: playerItem)
// Register as an observer of the player item's status property
playerItem!.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = true
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)
controller.view.frame = videoFrame
navigationController?.pushViewController(controller, animated: true)
player?.play()
}
Everything plays well however I have the following issues:
Sometimes the AVPlayer just pauses or stops the streams even when I am connected to a network and the AVPlayer gets stuck sometimes after a long period of playback time 20 mins - 45 mins - 1 hours - 2 hours. At times I cannot restart the player even by tapping the play button and on restarting the app it works - seems like the AVPlayer had to be reinitialized
While playing the stream, in between, sometimes the connection strength drops, like in an elevator, reachability shows that the device is connected to the network so it tries to connect to fetch data from the stream, but it is unable to and when a stable internet connection returns, the stream is unable to connect unless I quit the app and restart
To solve the above, I have added some listeners like:
- Listening to the reachability (connected / disconnected)
NotificationCenter.default.addObserver(self, selector: #selector(playBackStalled(_:)), name: .AVPlayerItemPlaybackStalled, object: nil)to check if AVPlayer has stalledplayerItem!.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: &playerItemContext)to check if the player has failed
These work sometimes only.
What I want is a reliable way to know if:
- The player has stalled / failed
- The app has a proper connection to be able to play an HLS stream
- If the player has failed for some reason, the AVPlayer gets torn down properly and automatically reinitializes when a stable network returns
Thanks in advance for any ideas / suggestions.