AVPlayerLayer не появляется несколько секунд, но звук работает отлично

Я работаю над приложением, в котором в фиде есть зацикленные видео (внутри ячеек представления таблицы). Одновременно может присутствовать несколько видео, но может воспроизводиться только одно из них. Я создаю AVPlayer в фоновом режиме и помещаю их playerLayer в слой моего представления в качестве подпредставления и воспроизводю видео с наибольшей областью на экране, когда пользователь перестает прокручивать ленту.

Однако недавно я заметил, что видео не отображается в ленте, когда пользователь прекращает прокрутку. Звук начинается сразу, но видео не отображается. Я проверил границы слоя игрока, все в порядке. Я видел AVPlayerLayer показывает черный экран, но звук работает но этот вопрос относится только к более старой версии iOS. Я также видел видео AVPlayer пустое, но слышу звук, но этот вопрос решен поскольку ОП понял, что границы слоя были нулевыми прямоугольниками. Я добавил таймер для повторной печати границ моего видеоплеера, и границы верны, даже если видео не отображается.

После нескольких секунд воспроизведения только со звуком видео начинает воспроизводиться идеально. Я дважды проверил, что «включение» не совпадает с возвратом видео к 0:00. Он просто включается в случайной части видео. Я также перебирал все суперслои, пока не достиг слоя UIWindow. Иерархия слоев правильно достигает слоя окна, и ни один из промежуточных слоев не имеет нулевого прямоугольника. Кроме того, когда видео запускается случайным образом, никакие из вышеперечисленных данных (суперслои, их прямоугольники) вообще не меняются. Просто чтобы быть уверенным, я добавил следующий код, и я не получаю никаких ошибок утверждения (у меня уже были NSLogs в нем, так что да, он называется):

timer = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
    NSAssert(_playerLayer.bounds.size.width, @"bounds");
    NSAssert(_playerLayer.bounds.size.height, @"bounds");
    NSAssert(!_playerLayer.hidden, @"hidden");
    BOOL inWindow = NO;
    CALayer *layer = _playerLayer.superlayer;
    while(layer){
        layer = layer.superlayer;
        NSAssert(layer.bounds.size.width, @"bounds");
        NSAssert(layer.bounds.size.height, @"bounds");
        NSAssert(!layer.hidden, @"hidden");
        if(layer == [UIApplication sharedApplication].keyWindow.layer){
            inWindow = YES;
            break;
        }
    }
     NSAssert(inWindow, @"not in window");
}]; 

Некоторые наблюдения и резюме:

  • Видео всегда воспроизводится правильно с первой попытки. Проблема начинается, когда я играю другое видео, а затем возвращаюсь.
  • Ни один из слоев/представлений не имеет нулевого прямоугольника, и он доходит до слоя окна. Я проверяю это в цикле с таймером 10 раз в секунду, и все выглядит идеально.
  • Звук начинается сразу, без задержки, даже при последующих «проблемных» воспроизведениях. Вкратце: со звуком проблем нет вообще.
  • Видео передаются через Интернет (из нашей собственной корзины S3), но уже загружены, так как их можно воспроизвести до конца и зациклить до того, как начнется проблема, так как проблема все равно не возникает при первом воспроизведении.
  • Я использую комбинацию AVPlayer/AVPlayerLayer и не снова создаю новые проигрыватели или слои для одного и того же видео, у меня есть словарь сопоставления URL-адреса с проигрывателем/слоем, и я использую их снова.
  • У меня iOS 11.2.5 и iPhone X, хотя я также пробовал симулятор, и проблема присутствует, поэтому я не думаю, что это связано с устройством.

В чем может быть проблема?


person Can Poyrazoğlu    schedule 24.02.2018    source источник


Ответы (1)


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

person Can Poyrazoğlu    schedule 25.02.2018