Ответ 1
Активы могут не быть готовы после его создания, он может выполнять вычисления, такие как продолжительность фильма, обязательно содержать все метаданные фильма в файле.
Обратите внимание, что приведенный ниже вопрос: все активы локальны на устройстве - потоковая передача сети не происходит. Видео содержат звуковые дорожки.
Я работаю над приложением 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
Какой подход, по вашему мнению, будет лучше? До сих пор я не добился такого большого прогресса в плане сокращения отставания.
Активы могут не быть готовы после его создания, он может выполнять вычисления, такие как продолжительность фильма, обязательно содержать все метаданные фильма в файле.
Сначала попробуйте вариант № 7, чтобы убедиться, что вы можете это сделать. Я подозреваю, что это не будет работать для ваших нужд, так как время поиска, вероятно, не будет достаточно быстрым, чтобы обеспечить плавное переключение между клипами. Если вы попробуете это и не получится, то я бы посоветовал вам сделать вариант 4/6 и взглянуть на мою iOS-библиотеку, разработанную специально для этой цели, просто выполните быстрый поиск Google на AVAnimator, чтобы узнать больше. Моя библиотека позволяет реализовать бесшовные циклы и переключиться с одного клипа на другой, это очень быстро, потому что видео необходимо предварительно декодировать в файл. В вашем случае все 10 видеоклипов будут дешифрованы в файлы до начала, но переход между ними будет быстрым.
Не делая ничего подобного в прошлом, основываясь на ваших мыслях и опытах, я бы попытался использовать комбинацию 7 и 1: предварительно загрузите один AVPlayer с помощью первых нескольких секунд из 10 последующих видеороликов. Тогда пропуски, скорее всего, будут быстрее и надежнее из-за меньшего количества данных. Пока вы играете выбранную пьесу, у вас есть достаточно времени, чтобы подготовить AVPlayer для остальной части выбранного последующего видео в фоновом режиме. Когда начало закончено, вы переключаетесь на подготовленный AVPlayer. Таким образом, вы в любой момент времени загружаете максимум 2 AVPlayers.
Конечно, я не знаю, можно ли сделать это так плавно, что это не мешает воспроизведению.
(Добавил бы это как комментарий, если бы мог.)
Лучший, Питер
Если я правильно понял вашу проблему, кажется, у вас есть одно непрерывное видео, на которое вам нужно загрузить звуковую дорожку на мгновение.
Если это так, я предлагаю изучить BASS. BASS - это аудио-библиотека, подобная AVPlayer, которая дает вам (относительно) легкий доступ к низкоуровневому API-интерфейсу среды AudioUnits в iOS. Что для вас значит? Это означает, что с небольшим количеством манипуляций с буфером (вам может и не понадобиться, зависит от того, насколько малы вы хотите задержку), вы можете сразу начать воспроизведение музыки.
Ограничения, тем не менее, распространяются на видео, как я уже сказал, это библиотека аудио, поэтому всевозможные манипуляции с видео будут выполняться с помощью AVPlayer. Однако, используя -seekToTime:toleranfeBefore:toleranceAfter:
, вы должны иметь возможность быстро искать в видео, пока вы пререкаете все необходимые параметры.
Если вы синхронизируете несколько устройств (что может предложить ваше приложение), просто оставьте комментарий, и я с удовольствием отредактировал бы мой ответ.
PS: BASS сначала может выглядеть пугающе из-за его C-подобного формата, но он действительно очень прост в использовании для чего.
Для iOS 10.x и выше, чтобы уменьшить задержку запуска AVPlayer, я установил: avplayer.automaticallyWaitsToMinimizeStalling = false;
и это, казалось, исправило это для меня. Это может иметь и другие последствия, но я еще не поразил их.
Я получил эту идею от: fooobar.com/questions/14633411/...
Вот несколько свойств и методов, предоставляемых классом 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;