1

I am trying to play files consecutively with no gap in between. The first thing I tried was using AVQueuePlayer:

let player = AVQueuePlayer()

let playerItem1 = ...
let playerItem2 = ...

player.insert(playerItem1, after: nil)
player.insert(playerItem2, after: nil)

player.play()

This works great and exactly as expected. However, there are some shortcoming of AVQueuePlayer and I've decided to instead use AVPlayer with a custom queue implementation. The problem I am facing is that although AVQueuePlayer is a subclass of AVPlayer, I cannot get AVPlayer to be gapless. Here's how the code is set up:

let playerItem1 = ...
let playerItem2 = ...

let player = AVPlayer(playerItem: playerItem1)

NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem)

player.play()

@objc func playerDidFinishPlaying() {
    player.replaceCurrentItem(with: nextPlayerItem)
    player.play()
}

As you can see, I detect the end of playback of the first item with the AVPlayerItemDidPlayToEndTime notification, and then begin playback of the second item. But with this implementation there is a gap between the two items.

How can I change this so that it behaves more like AVQueuePlayer, with no gap?

(Please note that I am not interested in using AVAudioEngine at this time.)

Hello
  • 219
  • 2
  • 7
  • What are the shortcomings of `AVQueuePlayer`? Since it extends `AVPlayer`, `AVPlayer` is going to have the same shortcomings I would think. – HangarRash Mar 03 '23 at 04:08
  • You can do with two `AVPlayer` instance. So first initialise one player and start observing progress(50%), if it cross target progress then initialise other player and make sure you call `AVPlayer.prepareToPlay()`. once first player finished then replace that with second player – SPatel Mar 03 '23 at 08:41
  • @HangarRash I think you have it backwards. Since `AVQueuePlayer` extends `AVPlayer`, it is a more specific type of player. If `AVQueuePlayer` has some shortcomings, we can go back to the more general `AVPlayer` and work from there, creating a new subclass of it that has the desired functionality. – Hello Mar 03 '23 at 16:52
  • @SPatel I've actually already tried this too. I had everything loaded, and when the first item is done, immediately start the second player (which was already loaded and prepared). But there is still a gap. Is it possible that `AVPlayerItemDidPlayToEndTime` isn't called quickly enough? Is there a better way to detect the end? – Hello Mar 03 '23 at 16:54
  • try by replacing prepareToPlay with AVPlayer.play() then immediately pause it DispatchQueue.main.async { AVPlayer.pause() } – SPatel Mar 04 '23 at 12:00

0 Answers0