Подтвердить что ты не робот

AVPlayerItem replaceCurrentItemWithPlayerItem Blocking

Сначала немного контекста о приложении...
 - Там много тяжелой работы пользовательского интерфейса с участием видеоплееров (в основном прокрутки)
 - Видеоролики динамичны и меняются в зависимости от нашей текущей страницы.
 - поэтому видео должно быть динамичным и постоянно меняться, а пользовательский интерфейс должен быть отзывчивым

Сначала я использовал MPMoviePlayerController, но затем из-за определенных требований мне пришлось вернуться на AVPlayer
Я сделал свою собственную упаковку для AVPlayer.
Чтобы изменить содержимое в видеоплеере, это выглядит так, как в классе AVPlayer-wrapper

/**We need to change the whole playerItem each time we wish to change a video url */
-(void)initializePlayerWithUrl:(NSURL *)url
{
    AVPlayerItem *tempItem = [AVPlayerItem playerItemWithURL:url];

    [tempItem addObserver:self forKeyPath:@"status"
                  options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                  context:nil];
    [tempItem addObserver:self forKeyPath:@"playbackBufferEmpty"
                  options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                  context:nil];

    //Not sure if this should be stopped or paused under the ideal circumstances
    //These will be changed to custom enums later
    [self setPlaybackState:MPMoviePlaybackStateStopped];
    [self setLoadState:MPMovieLoadStateUnknown];
    [self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem];

    //This is required only if we wish to pause the video immediately as we change the url
    //[self.videoPlayer pause];
}

Теперь, конечно, все работает нормально...... кроме.

[self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem];

Кажется, что блокировка пользовательского интерфейса на долю секунды и во время прокрутки делает пользовательский интерфейс действительно невосприимчивым и уродливым, и эта операция не может выполняться в фоновом режиме

Есть ли какое-либо исправление или обходное решение для этого.?

4b9b3361

Ответ 1

Решение, которое я нашел, состояло в том, чтобы гарантировать, что базовый AVAsset готов вернуть основную информацию, такую ​​как ее продолжительность, перед подачей ее в AVPlayer. AVAsset имеет метод loadValuesAsynchronouslyForKeys:, который удобен для этого:

AVAsset *asset = [AVAsset assetWithURL:self.mediaURL];
[asset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{
    AVPlayerItem *newItem = [[AVPlayerItem alloc] initWithAsset:asset];
    [self.avPlayer replaceCurrentItemWithPlayerItem:newItem];
}];

В моем случае URL-адрес является сетевым ресурсом, а replaceCurrentItemWithPlayerItem: будет фактически блокироваться в течение нескольких секунд, ожидая, когда эта информация будет загружена в противном случае.

Ответ 2

У нас была такая же проблема при создании Ultravisual. Я не могу точно помнить, как мы это решили, но в рамках IIRC он выполнял как можно больше настроек элемента в фоновом потоке и ожидал, пока новый элемент не сообщит, что он "готов играть" перед вызовом replaceCurrentItemWithPlayerItem.

К сожалению, это связано с танцем вуду с несколько непоследовательным асинхронным KVO, что не является забавой.