How to control AVPlayer buffering

Viewed 520

I'm using an AVPlayer to play a remote progressive download (i.e. non-HLS) video. But, I can't figure out how to control its buffering behavior.

I would like to pre-fetch 2 seconds of the video before it's ready to play, and also to stop buffering when the video is paused.

Here's my setup:

let asset = AVURLAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
let player = AVPlayer()

I tried the following, without success:

// doesn't start buffering
playerItem.preferredForwardBufferDuration = 2.0
// doesn't stop buffering
playerItem.preferredForwardBufferDuration = 2.0
player.replaceCurrentItem(with: playerItem)

I tried player.automaticallyWaitsToMinimizeStalling = true in both cases, and in combination with various player.pause() or player.rate = 0 - doesn't work.

A potential approach that comes to mind is to observe for loadedTimeRanges until the first 2 seconds loaded and set current item of the player to nil.

let c = playerItem.publisher(for: \.loadedTimeRanges, options: .new)
                  .compactMap { $0.first as? CMTimeRange }
                  .sink { 
                      if $0.duration.seconds - $0.start.seconds > 2 {
                         player.replaceCurrentItem(with: nil)

                      }
                  }

This would work for pre-buffer, but it doesn't work for pausing, because it makes the video blank instead of paused. (And at this point, I feel I'm attempting to reimplement/interfere with some core buffering functionality)

0 Answers
Related