Обратите внимание на вопрос ниже: все ресурсы локальны на устройстве - потоковая передача по сети не выполняется. Видео содержат звуковые дорожки.
Я работаю над приложением iOS, которое требует воспроизведения видеофайлов с минимальной задержкой для запуска рассматриваемого видеоклипа. К сожалению, мы не знаем, какой именно видеоклип будет следующим, до тех пор, пока нам действительно не понадобится его запустить. В частности: когда воспроизводится один видеоклип, мы будем знать, каков будет следующий набор (примерно) из 10 видеоклипов, но мы не знаем, какой именно, пока не наступит время «немедленно» воспроизвести следующий клип.
Что я сделал, чтобы посмотреть на фактические задержки запуска, так это вызвал addBoundaryTimeObserverForTimes
видеоплеер с периодом времени в одну миллисекунду, чтобы увидеть, когда видео действительно начало воспроизводиться, и я беру разницу этой отметки времени с первым местом в код, который указывает, какой актив начать воспроизведение.
Из того, что я видел до сих пор, я обнаружил, что использование комбинации AVAsset
загрузки, а затем создание AVPlayerItem
из нее, когда она будет готова, а затем ожидание, AVPlayerStatusReadyToPlay
прежде чем я вызову play, обычно занимает от 1 до 3 секунд, чтобы запустить клип.
С тех пор я переключился на то, что, по моему мнению, примерно равноценно: звонить [AVPlayerItem playerItemWithURL:]
и ждать начала AVPlayerItemStatusReadyToPlay
игры. Примерно такая же производительность.
Одна вещь, которую я наблюдаю, - это то, что загрузка первого элемента AVPlayer происходит медленнее, чем остальных. Кажется, одна из идей - предварительно запустить AVPlayer с коротким / пустым активом, прежде чем пытаться воспроизвести первое видео, может быть хорошей общей практикой. [ Медленный запуск AVAudioPlayer при первом воспроизведении звука
Я бы хотел максимально сократить время начала видео и иметь некоторые идеи, с которыми можно поэкспериментировать, но хотел бы получить рекомендации от любого, кто мог бы помочь.
Обновление: приведенная ниже идея 7 в том виде, в котором она реализована, дает время переключения около 500 мс. Это улучшение, но было бы неплохо сделать это еще быстрее.
Идея 1: использовать N AVPlayers (не сработает)
Используем ~ 10 AVPPlayer
объектов и запускаем и приостанавливаем все ~ 10 клипов, и как только мы знаем, какой из них нам действительно нужен, переключаемся на правильный AVPlayer
, снимаем паузу и начинаем все заново для следующего цикла.
Я не думаю, что это работает, потому что я читал, что AVPlayer's
в iOS есть примерно 4 активных . Кто-то спрашивал об этом здесь в StackOverflow и узнал об ограничении в 4 AVPlayer: быстрое переключение между видео-использованием-avfoundation
Идея 2: использовать AVQueuePlayer (не сработает)
Я не верю, что добавление 10 AVPlayerItems
в одну AVQueuePlayer
заранее загрузит их все для плавного старта. AVQueuePlayer
это очередь, и я думаю, что она действительно только делает следующее видео в очереди готовым для немедленного воспроизведения. Я не знаю, какое из ~ 10 видео мы хотим воспроизвести, пока не пришло время начать это. ИОС-AVPlayer-видео-поджимать
Идея 3: загрузка, воспроизведение и сохранение AVPlayerItems
в фоновом режиме (еще не уверен на 100%, но не очень хорошо)
Я смотрю, есть ли какие-либо преимущества для загрузки и воспроизведения первой секунды каждого видеоклипа в фоновом режиме (подавление вывода видео и звука) и сохранения ссылки на каждый из них AVPlayerItem
, и когда мы знаем, какой элемент необходимо воспроизвести для real, поменяйте местами этот и поменяйте местами фоновый 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
Как вы думаете, какой подход будет лучшим? Пока что я не добился больших успехов в сокращении задержки.
Ответы:
Для iOS 10.x и выше, чтобы уменьшить задержку запуска AVPlayer, я установил:
avplayer.automaticallyWaitsToMinimizeStalling = false;
и это, похоже, исправило это для меня. Это могло иметь другие последствия, но я еще не столкнулся с ними.Я получил идею от: https://stackoverflow.com/a/50598525/9620547
источник
Ресурс может быть не готов после того, как вы его создадите, он может производить вычисления, такие как продолжительность фильма, убедитесь, что в файле содержатся все метаданные фильма.
источник
Вы должны сначала попробовать вариант №7, просто чтобы увидеть, сможете ли вы заставить его работать. Я подозреваю, что на самом деле это не сработает для ваших нужд, поскольку время поиска, вероятно, будет недостаточно быстрым, чтобы обеспечить плавное переключение между клипами. Если вы попробуете это, и это не удастся, я бы посоветовал вам выбрать вариант 4/6 и взглянуть на мою библиотеку iOS, разработанную специально для этой цели, просто выполните быстрый поиск в Google на AVAnimator, чтобы узнать больше. Моя библиотека позволяет реализовать бесшовные циклы и переключаться с одного клипа на другой, это очень быстро, потому что видео нужно предварительно декодировать в файл. В вашем случае все 10 видеоклипов будут декодированы в файлы до того, как вы начнете, но тогда переключение между ними будет быстрым.
источник
Не делая ничего подобного в прошлом, основываясь на ваших мыслях и опыте, я бы попробовал комбинацию 7 и 1: Предварительно загрузите один AVPlayer с первыми парой секунд из 10 последующих видео. Тогда пропуск будет быстрее и надежнее из-за меньшего количества данных. Пока вы играете выбранный фрагмент, у вас есть достаточно времени, чтобы подготовить AVPlayer для оставшейся части выбранного последующего видео в фоновом режиме. Когда начало закончено, вы переключаетесь на подготовленный AVPlayer. Таким образом, в любой момент у вас может быть загружено не более 2 AV-плееров.
Конечно, я не знаю, можно ли переключить так плавно, чтобы не мешать воспроизведению.
(Я бы добавил это как комментарий, если бы мог.)
Бест, Питер
источник
Если я правильно понял вашу проблему, похоже, у вас есть одно непрерывное видео, для которого вам нужно загрузить звуковую дорожку в любой момент.
Если это так, я предлагаю изучить BASS . BASS - это аудио-библиотека, очень похожая на AVPlayer, которая дает (относительно) легкий доступ к низкоуровневым API фреймворка AudioUnits в iOS. Что это значит для тебя? Это означает, что с помощью крошечных манипуляций с буфером (она может вам даже не понадобиться, зависит от того, насколько крошечной вы хотите задержку), вы можете немедленно начать воспроизведение музыки.
Однако ограничения распространяются на видео, как я уже сказал, это аудиотека, поэтому любые манипуляции с видео все равно придется выполнять с помощью AVPlayer. Однако с помощью
-seekToTime:toleranfeBefore:toleranceAfter:
вы сможете добиться быстрого поиска по видео, если предварительно прокрутите все необходимые параметры.Если вы синхронизируете несколько устройств (что может предложить ваше приложение), просто оставьте комментарий, и я буду счастлив отредактировать свой ответ.
PS: Поначалу BASS может показаться устрашающим из-за своего C-подобного формата, но его действительно очень легко использовать в том виде, в каком он есть.
источник
Вот несколько свойств и методов, предоставляемых классом AVAsset, которые могут помочь:
источник