Вопрос по ios, delay, avplayer – Как уменьшить задержку запуска iOS AVPlayer

107

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

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

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

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

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

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

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

Update: idea 7, below, as-implemented yields switching times of around 500 ms. This is an improvement, but it it'd be nice to get this even faster.

Idea 1: Use N AVPlayers (won't work)

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

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

Idea 2: Use AVQueuePlayer (won't work)

Я не верю, что пуш 10AVPlayerItems вAVQueuePlayer будет предварительно загружать их все для плавного запуска.AVQueuePlayer это очередь, и я думаю, что она действительно только готовит следующее видео в очереди для немедленного воспроизведения. Я не знаю, какое из 10 видео мы хотим воспроизвести, пока не пришло время его запустить.ИОС-AVPlayer-видео-предзагрузка

Idea 3: Load, Play, and retain AVPlayerItems in background (not 100% sure yet -- but not looking good)

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

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

Idea 4: Use a different file format -- maybe one that is faster to load?

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

Idea 5: Combination of lossless video format + AVQueuePlayer

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

Idea 6: Use a non-standard AVPlayer / write my own / use someone else's

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

Idea 7: Combine everything into a single movie asset, and seekToTime

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

Какой подход, по вашему мнению, будет лучше? До сих пор я не достиг такого большого прогресса в плане уменьшения отставания.

Почти год спустя, что вы когда-нибудь узнали с этим? lnafziger
Что бы это ни стоило, я остановлюсь на идее 7. Она все еще медленная, но не настолько непредсказуемо медленная, как другие варианты. Следующий вопрос, который у меня возникает, - влияют ли параметры кодека, разрешение и частота ключевых кадров на время поиска? Bernt Habermeier
Я выбрал вариант 7 и попал в промежуток между 300 мс и 500 мс. Одна вещь, которую я обнаружил, заключается в том, что чем интереснее варианты кодеков mp4, тем медленнее поиск. Существует несколько параметров сжатия видео, которые позволяют улучшить сжатие и поддерживать качество видео, но убивают время декодирования. Bernt Habermeier
Позднее с игрой, но, возможно, стоит переключить видео как можно быстрее (т.е. сразу после того, как новый начнет играть) и профилировать приложение, чтобы увидеть, где оно проводит большую часть своего процессорного времени. tc.
Это разумный запрос, но для реализации варианта 7 в реализации слишком много аспектов, чтобы публиковать их. Рассмотрите: (a) Создайте цепочку инструментов для объединения видео активов, (b) убедитесь, что вы отслеживаете смещения сегментов видео, (c) смещения поиска, когда приходит запрос на воспроизведение определенного клипа, (d) используйте addPeriodicTimeObserverForInterval для проверки если вы запустили видеоклип и отреагировали соответствующим образом (используйте этот метод по сравнению с однократным addBoundaryTimeObserverForTimes, потому что я обнаружил, что последний иногда не запускается ... в целом, это не поддается вставке кода. Bernt Habermeier

Ваш Ответ

5   ответов
0

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

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

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

Лучший, Питер

О, теперь я понимаю вашу идею лучше. Благодарю. Было бы интересно исследовать, если вы получаете быстрый поиск коротких видеоклипов. Я еще не пробовал, но стоило бы подумать. Что касается использования основных носителей - я не нашел хорошего справочного материала по этому API. У вас есть хороший ресурс, на который вы можете указать мне? Bernt Habermeier
Я не нашел никакой выгоды от загрузки 10 ресурсов последовательно на одном AVPlayer. Кроме того, я не понимаю ваше предложение, поскольку вижу варианты (1) и (7) взаимоисключающими. Вариант 7 объединяет все видео активы в один актив - таким образом, есть только один актив для периода загрузки. Это то, что я делаю сегодня, и за то, что оно стоит, я получаю примерно 500 мс задержки с фактическим временем начала / воспроизведения. Стоит отметить, что SeekTo завершается быстрее, чем воспроизводится фактический первый кадр, поэтому для истинного времени начала я измеряю, когда первый кадр фактически воспроизводится с помощью обратного вызова по времени. Bernt Habermeier
Просто чтобы прояснить мою идею: моя идея состояла в том, чтобы разделить актив на две части: первые несколько секунд и остальные. Теперь вы сделали два актива из одного. 10 начал, к которым вы присоединяетесь и используете, пропускаете, а во время воспроизведения начала вы загружаете остальные. Это тогда включает предложение 8, которое добавляет к вашему списку.
Но, как я понимаю из вашего последнего комментария, вы тем временем продвинули исследования, что хорошо, и решение 7 также не работает. Похоже, что AV принципиально стоит на вашем пути, и единственный путь для вас, вероятно, состоит в том, чтобы использовать технологию, которая находится под ней, то есть Core Media, чтобы получить больше контроля над вашими активами. Питер.
Прошу прощения, но нет. Как я уже сказал, я не эксперт ни по AV, ни по Core Media. Просто прочитайте ваш Вопрос, и у меня были идеи, как я лично поступлю, и я хотел бы поделиться ими. Питер
0

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

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

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

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

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

1

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

Как насчет аудио части видео? Мне нужно видео и аудио для синхронизации. Bernt Habermeier
Нет, он работает с локальными файлами, потоковое сетевое видео - это совсем другое.
Есть ли возможность воспроизводить сетевое видео с помощью AVAnimator?
Да, аудио уже обрабатывается с очень жесткой синхронизацией между аудиодорожкой и видеоклипом. Смотрите пример проектов xcode. Это уже все реализовано, вам просто нужно скачать и попробовать.
-2

Вот несколько свойств и методов, предоставляемых классом 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;
1

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

Похожие вопросы