Почему воспроизведение звука через AV Foundation блокирует пользовательский интерфейс при медленном соединении?

#cocoa-touch #ios #networking #nstimer #avfoundation

#cocoa-touch #iOS #сеть #nstimer #avfoundation

Вопрос:

Я использую AV Foundation для воспроизведения MP3-файла, загруженного по сети, с кодом, который почти идентичен приведенному здесь примеру воспроизведения: Собираем все это вместе: воспроизведение видеофайла с использованием AVPlayerLayer, за исключением того, что без прикрепления слоя для воспроизведения видео. Я пытался заставить свое приложение реагировать на то, что буфер воспроизведения становится пустым при медленном сетевом соединении. Для этого я планировал использовать наблюдение за значением ключа в свойстве playbackBufferEmpty AVPlayerItem, но в документации не указано, возможно ли это. Я подумал, что это может быть возможно, потому что свойство status можно наблюдать (и это пример выше), хотя в документации этого не сказано.

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

Даже без режима ожидания на сервере я заметил, что при загрузке потоков с использованием AVPlayerItem пользовательский интерфейс не обновляется в течение короткого времени загрузки потока. Я не понимаю, почему медленная загрузка файла должна когда-либо блокировать отзывчивость пользовательского интерфейса. Есть идеи, почему это происходит или что я могу с этим поделать?

Ответ №1:

Хорошо, проблема решена. Похоже, что передача AVURLAssetPreferPreciseDurationAndTimingKey в параметрах URLAssetWithURL:options: вызывает замедление. Это также происходит только тогда, когда свойство duration AVURLAsset или какое-либо другое свойство, относящееся к синхронизации потока, доступно из селектора, запускаемого NSTimer. Итак, если вы можете избежать опроса информации о времени, эта проблема может не повлиять на вас, но для меня это не вариант. Если точное время не запрашивается, задержка по-прежнему составляет от 0,75 секунды до 1 секунды, но это все.

Оглядываясь назад, документация предупреждает, что точное время может привести к снижению производительности, но я никогда не представлял себе задержки более чем на 10 секунд. Почему задержка должна увеличиваться со временем загрузки носителя, мне непонятно; кажется, что она должна увеличиваться только с размером файла. Возможно, iOS выполняет какой-то интенсивный опрос новых данных и / или обрабатывает одни и те же байты снова и снова.

Итак, теперь, без «точного времени и продолжительности», длительность ресурса постоянно равна 0.0, даже когда он полностью загружен. Я также могу ответить на свою первоначальную цель — выполнить KVO в AVPlayerItem.isPlaybackBufferEmpty. Кажется, что KVO в любом случае было бы бесполезно, поскольку свойство начинается со значения NO, меняется на YES, как только я начинаю воспроизведение, и продолжает быть YES, даже когда носитель воспроизводится в течение нескольких минут за раз. В документации говорится об этом свойстве:

Указывает, был ли использован весь буферизованный носитель и что воспроизведение остановится или завершится.

Так что, я думаю, это неточно, и, по крайней мере, в этом конкретном случае, свойство не очень полезно.

Комментарии:

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

2. Выполнено. Я отправил два сообщения об ошибках, одно из-за задержки при загрузке мультимедиа, а другое из-за неточного значения playbackBufferEmpty. Я редактирую ответ выше, чтобы отразить некоторые дополнительные выводы.

3. По иронии судьбы, сайт отчетов об ошибках Apple неоднократно не отправлял сообщения при использовании Safari, но отлично работал с Chrome (хотя однажды срок действия моих учетных данных истек, и мне пришлось повторно вводить второй отчет).