Play AVQueuePlayer without gap and freeze

I use AVQueuePlayer to play a sequence of movies that are downloaded from URLs.
I tried to initialize the player instance with an array of all AVPlayerItems that I need to play.

 player = [[AVQueuePlayer queuePlayerWithItems:playerItemsArray] 

But in this case, AVQueuePlayer loads the initial part of each AVPlayerItem before starting playback. This is frustrating when frozen, and the application does not respond for several seconds.

It is possible to add only the first AVPlayerItem to the players queue, monitor its state and add the second element to the queue only when the first reaches the end, but in this case there will be a gap between the playback of the two elements caused by initialization and buffering of the second AVPlayerItem .

Is there a way to organize seamless playback of multiple videos without freezing?
Should I use other players for this?

Thanks in advance.

+6
source share
3 answers

Solution found.

When a new AVPlayerItem added to the AVQueuePlayer player will wait synchronously until the source part of the player element is buffered.

So, in this case, the player element must be buffered asynchronously, after which it can be added to the queue.
This can be done using [AVURLAsset loadValuesAsynchronouslyForKeys: completionHandler:]

For instance:

 AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; NSArray *keys = [NSArray arrayWithObject:@"playable"]; [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() { dispatch_async(dispatch_get_main_queue(), ^ { AVPlayerItem *playerItem = [[[AVPlayerItem alloc] initWithAsset:asset] autorelease]; [player insertItem:playerItem afterItem:nil]; }); }]; 

Using this queue of solutions, AVQueuePlayer can be populated with elements without any spaces or hangs.

+14
source

in Swift 2, working here:

 func load() { let player = AVQueuePlayer() for url in urls { makeItem(url) } } func makeItem(url: String) { let avAsset = AVURLAsset(URL: NSURL(string: url)!) avAsset.loadValuesAsynchronouslyForKeys(["playable", "tracks", "duration"], completionHandler: { dispatch_async(dispatch_get_main_queue(), { self.enqueue(avAsset: avAsset) }) }) } func enqueue(avAsset: AVURLAsset) { let item = AVPlayerItem(asset: avAsset) self.player.insertItem(item, afterItem: nil) } 
+1
source

Here is the solution.

 - (void)_makePlayer{ _player = [[AVQueuePlayer alloc] initWithPlayerItem:[AVPlayerItem playerItemWithAsset:[SSMoviePreviewItemMaker generateAVMovieItem]]]; } + (AVAsset *)generateAVMovieItem{ NSArray * array = [SSMovieFileManager getAllMovieResourceURL]; AVMutableComposition *composition = [[AVMutableComposition alloc] init]; for (int i = 0; i < array.count; i++) { AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:array[i] options:nil]; [composition insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofAsset:asset atTime:composition.duration error:nil]; } return composition; } 
-1
source

All Articles