Разочарования AVQueuePlayer (обработка переполнения буфера)
У меня чертовски много времени с AVQueuePlayer. Очень просто, я делаю это на массиве AVPlayerItems, построенных с помощью playerItemWithURL: и указывающих на видеоактивы на сервере в Сети.
Если я попытаюсь запустить эту штуку в стимуляторе (sic), она играет через первый актив, начинает играть во второй и просто умирает. Иногда он даже не проходит через первый актив.Теперь я понимаю, что sim-карта ведет себя иначе, чем устройство, поэтому я попробовал ее на устройство тоже, с той же проблемой.
Когда я регистрирую различные изменения статуса элемента, я вижу, что буфер заканчивается, и игрок просто умирает. Это кажется мне немного глупым для конструкции, которая играет в очередь элементов... конечно, буфер может быть переполнен, но почему он просто умрет?
Я делаю что-то не так, или так и должно быть?Я обошел эту проблему, наблюдая свойство loadedTimeRanges и когда оно изменяет отправку Играйте для игрока. Но это приводит к заиканию воспроизведения, что тоже отстой.
Вот мой код. Может кто-нибудь, пожалуйста, сказать мне, как это сделать, чтобы воспроизведение не было полным дерьмом?
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePlayerItemReachedEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.queuePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePlayerStalled:) name:AVPlayerItemPlaybackStalledNotification object:self.queuePlayer];
NSString *baseURL = @"http://www.aDomain.com/assets/";
NSMutableArray *vidItemArray = [[NSMutableArray alloc] initWithCapacity:5];
for (int i = 1; i <= 5; i++) {
AVPlayerItem *vid = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[baseURL stringByAppendingFormat:@"%d.mov", i]]];
[vid addObserver:self forKeyPath:@"status" options:0 context:nil];
[vid addObserver:self forKeyPath:@"playbackBufferEmpty" options:0 context:nil];
[vid addObserver:self forKeyPath:@"loadedTimeRanges" options:0 context:nil];
[vidItemArray addObject:vid];
}
self.queuePlayer = [AVQueuePlayer queuePlayerWithItems:vidItemArray];
[self.mPlaybackView setPlayer:self.queuePlayer];
}
- (void)handlePlayerItemReachedEnd:(NSNotification *)notification {
NSLog(@"Clip #%d finished playing", [self.queuePlayer.items indexOfObject:self.queuePlayer.currentItem]);
}
- (void)handlePlayerStalled:(NSNotification *)notification {
NSLog(@"CLIP STALLED...");
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([object isKindOfClass:[AVPlayerItem class]]) {
AVPlayerItem *item = (AVPlayerItem *)object;
if ([keyPath isEqualToString:@"status"]) {
switch (item.status) {
case AVPlayerItemStatusFailed:
NSLog(@"player item status failed");
break;
case AVPlayerItemStatusReadyToPlay:
NSLog(@"player item status is ready to play");
[self.queuePlayer play];
break;
case AVPlayerItemStatusUnknown:
NSLog(@"player item status is unknown");
break;
}
}
else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
if (item.playbackBufferEmpty) {
NSLog(@"player item playback buffer is empty");
}
}
else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSLog(@"Loaded time range = %@", item.loadedTimeRanges);
self.queuePlayer play];
}
}
}
1 ответ:
Вы не должны добавлять много
AVPlayerItem
кAVQueuePlayer
изначально, потому что они начнут буферизацию одновременно, по усмотрению фреймворка.Попробуйте загрузить один файл, а затем на KVO
currentItem
изменить очередь на следующий, это может решить вашу проблему. Я использую это, чтобы добиться бесплотного воспроизведения.