问题
I use AVQueuePlayer
to play a sequence of movies which are loaded from URLs.
I tried to initialize player instance with array of all AVPlayerItems
that I need to play.
player = [[AVQueuePlayer queuePlayerWithItems:playerItemsArray]
But in this case AVQueuePlayer
loads some initial part of each AVPlayerItem
before starting playback. It causes frustrating freeze and application doesn't respond for some seconds.
There is possibility to add only first AVPLayerItem
to player's queue, observe its state and add second item in queue only when first will reach end, but in this case there will be a gap between playback of two items caused by initializing and buffering of second AVPlayerItem
.
Is there any way to organize gapless playback of several videos without a freeze?
Should I use some other player for this purposes?
Thanks in advance.
回答1:
The solution is found.
When adding new AVPlayerItem
in queue of AVQueuePlayer
player will synchronously wait till initial part of player item will be buffered.
So in this case player item should be buffered asynchronously and after that it can be added in the queue.
It can be done using [AVURLAsset loadValuesAsynchronouslyForKeys: completionHandler:]
For example:
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 solution queue of AVQueuePlayer can be populated with items without any gaps and freezes.
回答2:
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)
}
回答3:
Here is 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;
}
来源:https://stackoverflow.com/questions/14941461/avqueueplayer-playback-without-gap-and-freeze