// listening for current item change self.audioQueueObserver = self.playerQueue?.observe(\.currentItem, options: [.new]) { [weak self] (player, _) in print("media item changed...") } // listening for current item status change self.audioQueueStatusObserver = self.playerQueue?.currentItem?.observe(\.status, options: [.new, .old], changeHandler: { (playerItem, change) in if playerItem.status == .readyToPlay { print("current item status is ready") } }) // listening for buffer is empty self.audioQueueBufferEmptyObserver = self.playerQueue?.currentItem?.observe(\.playbackBufferEmpty, options: [.new]) { [weak self] (_, _) in print("buffering...") } // listening for event that buffer is almost full self.audioQueueBufferAlmostThereObserver = self.playerQueue?.currentItem?.observe(\.playbackLikelyToKeepUp, options: [.new]) { [weak self] (_, _) in print("buffering ends...") } // listening for event that buffer is full self.audioQueueBufferFullObserver = self.playerQueue?.currentItem?.observe(\.playbackBufferFull, options: [.new]) { [weak self] (_, _) in print("buffering is hidden...") } // listening for event about the status of the playback self.audioQueueStallObserver = self.playerQueue?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { (playerItem, change) in if #available(iOS 10.0, *) { switch (playerItem.timeControlStatus) { case AVPlayerTimeControlStatus.paused: print("Media Paused") case AVPlayerTimeControlStatus.playing: print("Media Playing") case AVPlayerTimeControlStatus.waitingToPlayAtSpecifiedRate: print("Media Waiting to play at specific rate!") } } else { // Fallback on earlier versions } }) // listening for change event when player stops playback self.audioQueueWaitingObserver = self.playerQueue?.observe(\.reasonForWaitingToPlay, options: [.new, .old], changeHandler: { (playerItem, change) in if #available(iOS 10.0, *) { print("REASON FOR WAITING TO PLAY: ", playerItem.reasonForWaitingToPlay?.rawValue as Any) } else { // Fallback on earlier versions } })