Automatically restart an AVPlayer HLS Stream

716 Views Asked by At

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 stalled
  • playerItem!.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.

0

There are 0 best solutions below