Pre-buffering for AVQueuePlayer

14,568

Solution 1

Ok, I've looked over this problem again and written some code to check out AVQueuePlayer.

jollyCocoa's answer pointed me in the right direction by suggesting to observe the status property on AVPlayerItem. However the documentation doesn't seem to point out that this property (and it's AVPlayerItemStatusReadyToPlay value in particular) might be related to buffering.

However the AVPlayerItem's loadedTimeRanges property seems more related to buffering.

Doing KVO on that array was a bit trickier - the array object itself doesn't change, only it's items do - so I resorted to printing out it's content every second.

What I found out is that a few seconds in the queue's first item, the loadedTimeRanges for the second item shows up a new CMTimeRange with start time 0 and some small duration. The duration can increase up to 60 or so seconds while the previous item keeps playing.

Short answer: AVQueuePlayer will buffer the next AVPlayerItem while playing the current one.

Solution 2

As of iOS 5, it appears that AVQueuePlayer no longer pre-buffers. It did pre-buffer the next track in iOS 4.

I'm not sure why there's been a change or if it's even deliberate on Apple's part or simply a bug. In any case, it's a pain and I'll be submitting a bug to them about it.

Solution 3

Found a work around!!! After many hours of searching, and failed tests, I found a solution that works on iOS 5 and above.

This will play files without any delay in between. Not as convenient if you want to switch between files, but will certainly put everything together for you. It's still possible to keep track of where each file starts, when adding AVURLAsset, keep the CMTime variable, something like:

NSValue *toJumpTo = [NSValue valueWithCMTime:composition.duration];
[array addObject:toJumpTo];

and then just go through the array, checking the current time value and comparing it using CMTimeCompare.

Edit: Was found on this page visible from the web archive (the link currently points to spam).

Solution 4

I've been experimenting with the AVQueuePlayer using movies provided by a server. In this particular test I set up a queuePlayer with AVPlayerItems initialized with URL's to two different video assets of different types. One is an .mp4-file (progressive download), the other one an .m3u8 http-streaming file. It does act a bit funky, I must say.

Depending on the order in which I queue the files I get quite different behavior. If I start with the .mp4-file, the AVPlayerLayer goes blank and silent when the nextItem starts player (the .m3u8-file). If I change the order and start with the m3u8-file, the AVPlayerLayer goes blank but the audio from the second file plays fine.

My impression, from what I've seen so far, is that the AVQueuePlayer does NOT start downloading the next AVPlayerItem before the current AVPlayerItem has finished playing. But I might be wrong.

To be continued I guess...

Edit: Ok, so I've done some more testing and it seems the next items starts downloading before the last item finishes playing. See post below. Stroke the "NOT"...

Edit2: Adding my explanation here instead, since the comment left me with no formatting options. (Best practice for this is welcome, if this is a bad way to handle answer updates)

Anyhow, I iterated through my itemsArray adding observation of the status property using KVO...

[playerItem addObserver: self forKeyPath:@"status" options: 0 context: NULL];

I also set my controller as the observer of the AVPlayerItem Notification AVPlayerItemDidPlayToEndTimeNotification:

[[NSNotificationCenter defaultCenter] addObserver: self
                                         selector: @selector(playerItemDidReachEnd:) 
                                             name: AVPlayerItemDidPlayToEndTimeNotification 
                                           object: nil];

Now I could log the status change of the AVPlayerItem, and it turns out the next AVPlayerItem in the queue is logged with a status change AVPlayerItemStatusReadyToPlay before the current item ends playing back.

My conclusion is therefor that the next item in line starts downloading prior to the current item ends.

However! I create an array with AVPlayerItems which I use to create my player. Reading the AVFoundation docs on AVAssets, I get the impression that these download their assets asynchronously, but I'm still uncertain when these downloads are being initiated by the IAPlayerItem. I still have some funky behavior when I add the .m3u8-file to the queue, which makes me wonder if these assets begin downloading at the time of creation (seems a bit strange to me though).

Share:
14,568

Related videos on Youtube

Mihai Damian
Author by

Mihai Damian

iOS developer

Updated on November 18, 2020

Comments

  • Mihai Damian
    Mihai Damian over 3 years

    Does anyone know if AVQueuePlayer starts buffering the next AVPlayerItem when the current item is about to finish playing?

    I know there's nothing in the docs to suggest this, I'm asking mostly if anyone has observed this kind of behavior or not.

  • jollyCocoa
    jollyCocoa over 13 years
    Ok, so I iterate through the items in the items array, adding observation via KVO... This comment doesn't allow formatting. Editing my main post instead!
  • Xin Guo
    Xin Guo over 12 years
    If you've submitted the bug report, can you openradar it so we can dupe it?
  • Kristian Evensen
    Kristian Evensen about 12 years
    Has there been any progress related to this bug report? My app is affected by the same bug, queueing two locally stored mp4 files results in a nasty halt in playback when AVQueuePlayer moves to the next file.
  • Nick Fishman
    Nick Fishman about 11 years
    @matt-gallagher, did you ever hear back from Apple about the lack of pre-buffering in AVQueuePlayer?
  • Goz
    Goz about 9 years
    Oh wow, that AVComposition trick was EXACTLY what I needed. Cheers! :)
  • James Bush
    James Bush over 7 years
    Loading an AVPlayerItem is not what causes player lag; if you disagree show me code that proves it. I have a working app that loads one AVPlayerItem for each video asset on your iPhone in one collection view cell. You can scroll as fast as you'd like, and the first frame of every video will display as if you were only requesting a single image from the asset. However, a playback lag appears to manifest itself ONLY if it starts while scrolling. That's because you put too many things in one thread and on one queue. Initiate play on a separate thread and queue, and the lag is gone.
  • Mahesh Narla
    Mahesh Narla about 7 years
    will you please provide an example with above code for avqueueplayer
  • Tony Nguyen
    Tony Nguyen over 5 years
    Which piece of code reduces buffering time (aka preload video) ?
  • ov1d1u
    ov1d1u almost 5 years
    You can replace the link with an archived one.
  • StackGU
    StackGU over 3 years
    @JamesBush Interesting comment, could you elaborate more, maybe with some code?