Как уменьшить задержку старта iOS AVPlayer

Обратите внимание на вопрос ниже: все ресурсы локальны на устройстве - потоковая передача по сети не выполняется. Видео содержат звуковые дорожки.

Я работаю над приложением iOS, которое требует воспроизведения видеофайлов с минимальной задержкой для запуска рассматриваемого видеоклипа. К сожалению, мы не знаем, какой именно видеоклип будет следующим, до тех пор, пока нам не понадобится его запустить. В частности: когда воспроизводится один видеоклип, мы будем знать, каков будет следующий набор (примерно) из 10 видеоклипов, но мы не знаем, какой именно, пока не наступит время «немедленно» воспроизвести следующий клип.

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

Из того, что я видел до сих пор, я обнаружил, что использование комбинации AVAsset загрузки, а затем создания AVPlayerItem из этого, когда он будет готов, а затем ожидания AVPlayerStatusReadyToPlay перед вызовом воспроизведения, как правило, занимает от 1 до 3 секунд. чтобы начать клип.

С тех пор я переключился на то, что, на мой взгляд, примерно равноценно: позвонил [AVPlayerItem playerItemWithURL:] и ждал, пока AVPlayerItemStatusReadyToPlay сыграет. Примерно такая же производительность.

Я наблюдаю, что первый элемент AVPlayer загружается медленнее, чем остальные. Кажется, одна из идей состоит в том, чтобы предварительно запустить AVPlayer с коротким / пустым активом, прежде чем пытаться воспроизвести первое видео, может быть хорошей общей практикой. [Медленный запуск AVAudioPlayer при первом запуске звук воспроизводится

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

Обновление: приведенная ниже идея 7 в том виде, в котором она реализована, дает время переключения около 500 мс. Это улучшение, но было бы неплохо сделать это еще быстрее.

Идея 1. Используйте N AV-плееров (не сработает)

Используя ~ 10 AVPPlayer объектов и запустите и приостановите все ~ 10 клипов, и как только мы узнаем, какой из них нам действительно нужен, переключитесь на правильный AVPlayer, снимите паузу и начните все заново для следующего цикла.

Я не думаю, что это работает, потому что я читал, что в iOS есть примерно 4 активных AVPlayer's. Кто-то спрашивал об этом здесь в StackOverflow и узнал о пределе 4 AVPlayer: быстро -переключение-видео-использование-avfoundation

Идея 2. Используйте AVQueuePlayer (не работает)

Я не верю, что добавление 10 AVPlayerItems в AVQueuePlayer приведет к их предварительной загрузке для беспрепятственного запуска. AVQueuePlayer - это очередь, и я думаю, что она действительно только делает следующее видео в очереди готовым к немедленному воспроизведению. Я не знаю, какое из ~ 10 видео мы хотим воспроизвести, пока не пришло время начать это. ios-avplayer-video-preloading

Идея 3. Загрузка, воспроизведение и сохранение AVPlayerItems в фоновом режиме (пока не уверен на 100%, но выглядит не очень хорошо)

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

Теоретически можно было бы предположить, что недавно воспроизведенные AVPlayer/AVPlayerItem могут все еще содержать некоторые подготовленные ресурсы, которые ускорят последующее воспроизведение. До сих пор я не видел пользы от этого, но, возможно, я неправильно настроил AVPlayerLayer фон. Я сомневаюсь, что это действительно улучшит ситуацию по сравнению с тем, что я видел.

Идея 4. Используйте другой формат файла - может быть, тот, который загружается быстрее?

В настоящее время я использую формат H.264 .m4v (видео-MPEG4). H.264 имеет множество различных вариантов кодеков, поэтому возможно, что некоторые параметры искать быстрее, чем другие. Я обнаружил, что использование более продвинутых настроек, уменьшающих размер файла, увеличивает время поиска, но не нашел никаких других вариантов.

Идея 5. Комбинация формата видео без потерь и AVQueuePlayer

Если есть видеоформат, который быстро загружается, но, возможно, имеет безумный размер файла, одна из идей может заключаться в том, чтобы предварительно подготовить первые 10 секунд каждого видеоклипа с версией, которая раздута, но быстрее загружается, но возвращается это с активом, закодированным в H.264. Используйте AVQueuePlayer и добавьте первые 10 секунд в несжатый формат файла, а затем добавьте в H.264, который занимает до 10 секунд времени подготовки / предварительной загрузки. Так что я бы получил «лучшее» из обоих миров: быстрое время запуска, но также преимущества более компактного формата.

Идея 6. Используйте нестандартный AVPlayer / напишите свой / используйте чужой

Учитывая мои потребности, возможно, я не могу использовать AVPlayer, но мне нужно прибегнуть к AVAssetReader и декодировать первые несколько секунд (возможно, записать необработанный файл на диск), а когда дело доходит до воспроизведения, использовать необработанный формат для его воспроизведения. назад быстро. Мне кажется, что это огромный проект, и если я подойду к нему наивно, то будет неясно / вряд ли получится даже лучше. Размер каждого декодированного и несжатого видеокадра составляет 2,25 МБ. Наивно говоря - если мы выберем для видео ~ 30 кадров в секунду, я получу требование на чтение с диска ~ 60 МБ / с, что, вероятно, невозможно. Очевидно, нам нужно было бы выполнить некоторый уровень сжатия изображений (возможно, собственные форматы сжатия openGL / es через PVRTC) ... но это безумие. Может быть, есть библиотека, которую я могу использовать?

Идея 7. Объедините все в один объект фильма и выполните seekToTime

Одна идея, которая может быть проще, чем некоторые из вышеперечисленных, - это объединить все в один фильм и использовать seekToTime. Дело в том, что мы бы прыгали повсюду. По сути произвольный доступ к фильму. Я думаю, что это действительно может сработать: avplayer-movie-playing-lag-in-ios5

Как вы думаете, какой подход будет лучшим? Пока что я не добился больших успехов в сокращении задержки.


person Bernie Habermeier    schedule 23.06.2012    source источник
comment
Как бы то ни было, я выберу Idea 7. Она все еще медленная, но не такая непредсказуемо медленная, как другие варианты. Следующий вопрос: влияют ли параметры кодека, разрешение и частота ключевых кадров на время поиска?   -  person Bernie Habermeier    schedule 04.07.2012
comment
Поздно к игре, но, возможно, стоит переключить видео как можно быстрее (то есть сразу после того, как новое начало воспроизводиться) и профилировать приложение, чтобы увидеть, где оно тратит большую часть своего процессорного времени.   -  person tc.    schedule 10.03.2013
comment
Что вы узнали об этом почти год спустя?   -  person lnafziger    schedule 11.06.2013
comment
Я выбрал вариант 7 и добрался до места между поисками от 300 мс до 500 мс. Я обнаружил, что чем красивее варианты кодека mp4, тем медленнее seekTo. Есть несколько параметров сжатия видео, которые позволяют улучшить сжатие и сохранить качество видео, но сокращают время декодирования.   -  person Bernie Habermeier    schedule 11.06.2013
comment
Отлично, спасибо за информацию. Если вы не возражаете, не могли бы вы добавить ответ, в котором подробно описывается ваше решение, и принять его как правильный ответ, чтобы дать будущим людям в этой ситуации какое-то руководство?   -  person lnafziger    schedule 14.06.2013
comment
Это разумно звучащий запрос, но на самом деле, чтобы реализовать вариант 7, в реализации слишком много аспектов для публикации. Подумайте: (a) Создайте цепочку инструментов для объединения видеоресурсов, (b) убедитесь, что вы отслеживаете смещения сегментов видео, (c) смещения поиска, когда поступает запрос на воспроизведение определенного клипа, (d) используйте addPeriodicTimeObserverForInterval для проверки если вы запустили видеоклип и отреагировали соответствующим образом (используйте этот метод вместо одноразового addBoundaryTimeObserverForTimes, потому что я обнаружил, что последний иногда не запускается ... в целом, это не поддается вставке кода.   -  person Bernie Habermeier    schedule 19.06.2013
comment
Привет, @BerntHabermeier, не могли бы вы помочь мне с проблемой на AVPlayer? Я уже несколько дней искал, как это решить. Проблема в том, что я использую свою внутреннюю систему для загрузки фрагментов файла mp4, каждые 200 КБ. Я использую протокол shouldWaitForLoadingOfRequestedResource для обработки запросов. Проблема в том, что когда я пытаюсь выполнить seekToTime для текущего элемента, он не запрашивает соответствующее смещение байта. Он просто запрашивает все видеоданные с самого начала. Плеер меняет состояние на readyToPlay, но ждет, пока не загрузятся все данные ... Вы когда-нибудь сталкивались с такой проблемой?   -  person kokoko    schedule 18.11.2015
comment
@kokoko Похоже, вы пытаетесь запустить потоковое видео. Кроме того, похоже, что вы используете протокол AVAssetResourceLoaderDelegate, из которого shouldWaitForLoadingOfRequestedResource является методом. Я не использовал этот протокол, поэтому не могу вам в этом помочь, но я думаю, что вопрос в том, что вы на самом деле пытаетесь сделать. Если вы пытаетесь запустить потоковое видео, вам следует посмотреть: developer.apple.com/streaming . Если вы просто пытаетесь загрузить большой файл небольшими порциями, вы можете сделать это полностью без AVAssetResourceLoaderDelegate.   -  person Bernie Habermeier    schedule 19.11.2015


Ответы (6)


Для iOS 10.x и выше, чтобы уменьшить задержку запуска AVPlayer, я установил: avplayer.automaticallyWaitsToMinimizeStalling = false;, и это, похоже, исправило это для меня. У этого могут быть и другие последствия, но я еще не столкнулся с ними.

Я получил идею от: https://stackoverflow.com/a/50598525/9620547

person grizzb    schedule 30.04.2019
comment
У меня получилось сокращение задержки на 6-7 секунд. Но у меня вопрос, повлияет ли это на производительность приложения? - person kalpa; 03.08.2020
comment
@kalpa Мы использовали этот код в рабочем приложении более года без каких-либо заметных негативных эффектов. В основном мы проигрываем 20-60-минутные аудиофайлы слушателям в США, где мобильная передача данных обычно является быстрой. Однако ваш вариант использования может быть другим. - person grizzb; 04.08.2020
comment
Спасибо за информацию. @grizzb - person kalpa; 05.08.2020
comment
Это сработало, больше ничего не работало. - person Niyog Ray; 25.03.2021

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

person nova    schedule 31.10.2012

Вы должны сначала попробовать вариант №7, просто чтобы посмотреть, сможете ли вы заставить его работать. Я подозреваю, что на самом деле это не сработает для ваших нужд, поскольку время поиска, скорее всего, будет недостаточно быстрым, чтобы обеспечить плавное переключение между клипами. Если вы попробуете это, и это не удастся, я бы посоветовал вам выбрать вариант 4/6 и взглянуть на мою библиотеку iOS, разработанную специально для этой цели, просто выполните быстрый поиск в Google на AVAnimator, чтобы узнать больше. Моя библиотека позволяет реализовывать бесшовные циклы и переключаться с одного клипа на другой, это очень быстро, потому что видео нужно предварительно декодировать в файл. В вашем случае все 10 видеоклипов будут декодированы в файлы до того, как вы начнете, но тогда переключение между ними будет быстрым.

person MoDJ    schedule 10.06.2013
comment
А как насчет звуковой части видео? Мне нужно синхронизировать видео и аудио. - person Bernie Habermeier; 06.07.2013
comment
Да, звук уже обрабатывается с очень плотной синхронизацией между звуковой дорожкой и видеоклипом. См. Примеры проектов xcode. Уже все реализовано, нужно просто скачать и опробовать. - person MoDJ; 06.07.2013
comment
Есть ли возможность проигрывать сетевое видео с помощью AVAnimator? - person Richard Topchii; 07.06.2016
comment
Нет, он работает с локальными файлами, потоковое сетевое видео - совсем другое дело. - person MoDJ; 07.06.2016

Не делая ничего подобного в прошлом, основываясь на ваших мыслях и опыте, я бы попробовал комбинацию 7 и 1: предварительно загрузите один AVPlayer с первыми парой секунд из 10 последующих видео. Тогда пропуск, скорее всего, будет быстрее и надежнее из-за меньшего количества данных. Пока вы играете выбранный фрагмент, у вас есть достаточно времени, чтобы подготовить AVPlayer для оставшейся части выбранного последующего видео в фоновом режиме. Когда начало закончено, вы переключаетесь на подготовленный AVPlayer. Таким образом, в любой момент у вас может быть загружено максимум 2 AV-плеера.

Конечно, я не знаю, можно ли переключение сделать так плавно, чтобы оно не мешало воспроизведению.

(Я бы добавил это как комментарий, если бы мог.)

Бест, Питер

person ilmiacs    schedule 07.09.2012
comment
Я не обнаружил никакой выгоды от последовательной загрузки 10 ресурсов на один AVPlayer. Кроме того, я не понимаю вашего предложения, так как считаю варианты (1) и (7) взаимоисключающими. Вариант 7 объединяет все видеоресурсы в один актив - таким образом, есть только один актив для загрузки. Это то, что я делаю сегодня, и чего бы это ни стоило, я получаю задержку примерно в 500 мс при фактическом времени запуска / воспроизведения. Стоит отметить, что SeekTo завершается быстрее, чем воспроизводится фактический первый кадр, поэтому для истинного времени начала я измеряю, когда первый кадр фактически воспроизводится, с помощью обратного вызова по времени. - person Bernie Habermeier; 08.09.2012
comment
Чтобы прояснить мою идею: моя идея заключалась в том, чтобы разделить актив на две части: первые несколько секунд и остальные. Теперь вы сделали два актива из одного. Вы бы присоединились к 10 начинаниям и использовали бы skip, а пока играете начало, вы загружаете все остальное. Затем это предложение 8, которое добавляется к вашему списку. - person ilmiacs; 08.09.2012
comment
Но, как я понимаю из вашего последнего комментария, тем временем вы продвинули исследования дальше, что хорошо, и решение 7 также не работает. Похоже, что AV по сути остается на вашем пути, и единственный выход, который вы можете сделать, - это использовать технологию, лежащую ниже, то есть Core Media, чтобы получить больший контроль над вашими активами. Питер. - person ilmiacs; 08.09.2012
comment
О, теперь я лучше понимаю твою идею. Спасибо. Было бы интересно исследовать, получаете ли вы быстрое время поиска для коротких видеоклипов. Я еще не пробовал это, но стоит подумать. Что касается использования основных носителей - я не нашел хороших справочных материалов по этому API. У вас есть хороший ресурс, на который можно мне указать? - person Bernie Habermeier; 10.09.2012
comment
Прошу прощения, но нет. Как я уже сказал, я не эксперт ни в AV, ни в Core Media. Просто прочитайте свой вопрос, у меня были идеи, как я лично буду действовать, и я хотел ими поделиться. Питер - person ilmiacs; 10.09.2012
comment
Вероятно, стоит иметь в виду, что загрузка больших медиафайлов или сразу многих файлов повлияет на вашу память, и вам придется следить за ней, так как это также может замедлить работу. - person cleverbit; 11.10.2012

Если я правильно понял вашу проблему, похоже, у вас есть одно непрерывное видео, для которого вам нужно загрузить звуковую дорожку в любой момент.

В этом случае я предлагаю изучить BASS. BASS - это аудио-библиотека, очень похожая на AVPlayer, которая дает вам (относительно) простой доступ к низкоуровневым API фреймворка AudioUnits в iOS. Что это значит для тебя? Это означает, что с помощью крошечных манипуляций с буфером (она может вам даже не понадобиться, зависит от того, насколько крошечной вы хотите задержку), вы можете мгновенно начать воспроизведение музыки.

Однако ограничения распространяются на видео, как я уже сказал, это библиотека аудио, поэтому любые манипуляции с видео все равно придется выполнять с помощью AVPlayer. Однако с помощью-seekToTime:toleranfeBefore:toleranceAfter: вы сможете добиться быстрого поиска по видео, если предварительно прокрутите все необходимые параметры.

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

PS: Поначалу BASS может показаться устрашающим из-за своего C-подобного формата, но его действительно очень легко использовать в том виде, в каком он есть.

person donkey    schedule 20.06.2017

Вот несколько свойств и методов, предоставляемых классом AVAsset, которые могут помочь:

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;
person James Bush    schedule 06.08.2016