Обратите внимание, что приведенный ниже вопрос: все активы локальны на устройстве - потоковая передача сети не происходит. Видео содержат звуковые дорожки.
Я работаю над приложением iOS, которое требует воспроизведения видеофайлов с минимальной задержкой для запуска рассматриваемого видеоролика. К сожалению, мы не знаем, какой именно видеоролик будет дальше, пока нам не понадобится его запускать. В частности: когда один видеоролик воспроизводится, мы узнаем, что представляет собой следующий набор (примерно) 10 видеороликов, но мы не знаем, какой именно, пока не придет время "немедленно" воспроизвести следующий клип.
То, что я сделал, чтобы посмотреть фактические задержки запуска, - это вызвать addBoundaryTimeObserverForTimes
на видеоплеере с периодом времени в миллисекунду, чтобы увидеть, когда видео действительно начало играть, и я беру разницу того времени отметьте первое место в коде, которое указывает, какой актив начать играть.
Из того, что я видел до сих пор, я обнаружил, что используя комбинацию загрузки AVAsset
, а затем создавая AVPlayerItem
от того, что он готов, а затем ждет AVPlayerStatusReadyToPlay
, прежде чем я вызову игру, для начала клипа требуется от 1 до 3 секунд.
С тех пор я переключился на то, что, по моему мнению, примерно эквивалентен: звоните [AVPlayerItem playerItemWithURL:]
и ждем AVPlayerItemStatusReadyToPlay
для воспроизведения. Примерно такая же производительность.
Одна вещь, которую я наблюдаю, заключается в том, что первая загрузка элемента AVPlayer медленнее остальных. Кажется, одна идея заключается в предполетном AVPlayer с коротким/пустым активом, прежде чем пытаться воспроизвести первое видео может быть хорошей общей практикой. [Медленный запуск для AVAudioPlayer при первом воспроизведении звука
Мне бы хотелось, чтобы время начала видеороликов было как можно меньше, и у вас есть идеи о том, что нужно экспериментировать, но хотелось бы, чтобы некоторые рекомендации были доступны любому, кто мог бы помочь.
Обновление: идея 7 ниже, как реализовано, дает время переключения около 500 мс. Это улучшение, но было бы неплохо сделать это еще быстрее.
Идея 1: используйте N AVPlayers (не будет работать)
Использование объектов ~ 10 AVPPlayer
и запуск и приостановка всех ~ 10 клипов, и как только мы узнаем, какой из них нам действительно нужен, переключитесь на правильную AVPlayer
и отмените паузу и начните сначала заново следующий цикл.
Я не думаю, что это работает, потому что я читал, что в iOS имеется примерно 4 активных AVPlayer's
. Кто-то спрашивал об этом в StackOverflow здесь и узнал о четырех ограничениях AVPlayer: fast-switching-between-videos-using-avfoundation
Идея 2: Использовать AVQueuePlayer (не работает)
Я не верю, что перетащить 10 AVPlayerItems
в AVQueuePlayer
будет предварительно загружать их все для бесшовного запуска. AVQueuePlayer
- это очередь, и я думаю, что это действительно только делает следующее видео в очереди готовым к немедленному воспроизведению. Я не знаю, какой из 10 видеороликов мы хотим воспроизвести, пока не приступит к началу этого. ios-avplayer-video-preloading
Идея 3: загрузить, воспроизвести и сохранить AVPlayerItems
в фоновом режиме (не на 100% еще, но не выглядящий хорошо)
Я смотрю, есть ли какая-либо польза для загрузки и воспроизведения первой секунды каждого видеоклипа в фоновом режиме (подавление вывода видео и аудио) и сохраняйте ссылку на каждый AVPlayerItem
, и когда мы знаем, какие элемент должен быть воспроизведен для реального, поменяйте его и замените фоновый AVPlayer активным. Промыть и повторить.
Теория заключалась бы в том, что недавно воспроизведенный AVPlayer/AVPlayerItem
может все еще содержать некоторые подготовленные ресурсы, которые ускорили бы последующее воспроизведение. До сих пор я не видел преимуществ от этого, но у меня может не быть настройки AVPlayerLayer
правильно для фона. Я сомневаюсь, что это действительно улучшит все, что я видел.
Идея 4: Используйте другой формат файла - возможно, тот, который быстрее загружается?
В настоящее время я использую формат .m4v (video-MPEG4) H.264. В H.264 есть много различных вариантов кодеков, поэтому возможно, что некоторые параметры быстрее искать, чем другие. Я обнаружил, что использование более продвинутых параметров, которые делают размер файла меньше, увеличивают время поиска, но не нашли никаких параметров, которые идут другим путем.
Идея 5: Сочетание формата видео без потерь + AVQueuePlayer
Если есть видеоформат, который быстро загружается, но, возможно, там, где размер файла сумасшедший, одной из идей может быть предварительная подготовка первых 10 секунд каждого видеоклипа с раздутой версией, но более быстрой для загрузки, но обратно с актива, который закодирован в H.264. Используйте AVQueuePlayer и добавьте первые 10 секунд в формат несжатого файла и следуйте этому примеру, который находится в H.264, который получает до 10 секунд времени подготовки/предварительной загрузки. Таким образом, я получил бы "лучшее" из обоих миров: быстрое начало работы, но также выигрывает от более компактного формата.
Идея 6: используйте нестандартный AVPlayer/напишите мой собственный/используйте чужой
Учитывая мои потребности, возможно, я не могу использовать AVPlayer, но мне приходится прибегать к AVAssetReader и декодировать первые несколько секунд (возможно, писать сырые файлы на диск), а когда дело доходит до воспроизведения, используйте необработанный формат чтобы быстро воспроизвести его. Кажется, это огромный проект для меня, и если я буду заниматься наивным образом, это неясно/вряд ли даже лучше работает. Каждый декодированный и несжатый видеокадр составляет 2,25 МБ. Наивно говоря - если мы пойдем с ~ 30 кадров в секунду для видео, я бы закончил с требованием ~ 60 МБ/с для чтения с диска, что, вероятно, невозможно/подтолкнуло. Очевидно, нам нужно было бы сделать некоторый уровень сжатия изображения (возможно, родные форматы сжатия OpenGL/es через PVRTC)... но такого рода сумасшедшие. Может быть, есть библиотека, которую я могу использовать?
Идея 7: объединить все в один ресурс фильма и искатьToTime
Одна из идей, которая может быть проще, чем некоторые из вышеперечисленных, состоит в том, чтобы объединить все в один фильм и использовать seekToTime. Дело в том, что мы будем прыгать по всему месту. По сути, произвольный доступ к фильму. Я думаю, что это может на самом деле работать нормально: avplayer-movie-playing-lag-in-ios5
Какой подход, по вашему мнению, будет лучше? До сих пор я не добился такого большого прогресса в плане сокращения отставания.