• 1
Votes
name

I am using AVQueuePlayer to play a list of remote audio files. I want to implement repeat all by default.

My approach, I am observing AVPlayerItemDidPlayToEndTime notification and I add the playerItem to the back of the Queue when it has finished playing.

The nextAudio(notification: Notification) is not running at all. Need help on this or better still a better way to implement infinite play.

func playAudio(_ items: [AVPlayerItem]) {

    let avPlayerVC = AVPlayerViewController()
    let player = AVQueuePlayer(items: items)
    player.actionAtItemEnd = .pause
    avPlayerVC.player = player

    for item in items {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(FilesViewController.nextAudio(notification:)),
                                               name: .AVPlayerItemDidPlayToEndTime, object: item)
    }

    present(avPlayerVC, animated: true) {
        self.player.play()
    }
}

@objc func nextAudio(notification: Notification) {
    debugPrint("nextAudio was called")
    guard player != nil else { return }
    debugPrint("AVPlayerItemDidPlayToEndTime notif info  (notification.userInfo)")
    if let currentItem = notification.userInfo!["object"] as? AVPlayerItem {
        currentItem.seek(to: kCMTimeZero)
        self.player.advanceToNextItem()
        self.player.insert(currentItem, after: nil)
    }

I am sure you already figured it out but I just encountered myself and decided to answer anyways:

It looks like it is not delivered when you specify an object of notification (which should be a proper way BTW). may be a bug in iOS...

You need to pass nil instead:

NotificationCenter.default.addObserver(self, selector: #selector(videoDidPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)

Then in the method you should check in the notification's object is your player item. Documentation is actually not consistent because Apple states that notification's object is a AVplayer but it is a AVPlayerItem:

@objc
    private func videoDidPlayToEnd(_ notification: Notification) {
        guard let playerItem = notification.object as? AVPlayerItem, let urlAsset = playerItem.asset as? AVURLAsset else { return }
    gpLog("Sender urlAsset: (urlAsset.url.absoluteString)")
        // Compare an asset URL.
    }
  • 1
Reply Report