Возможно ли кэшировать сегменты HLS с помощью AVPlayer?
Корневая проблема
Наше видео много буферизуется при поиске в iOS. Он буферизует немного больше, чем наш веб-плеер, который сохраняет копии уже просмотренных сегментов в хранилище temp.
Желаемое решение
Кэширование видео сегментов локально на диске устройства. Мы в порядке с кешированием одного качества и всегда воспроизводим его.
Blocker
Мы не можем найти способ выполнить кеширование в AVFoundation/AVPlayer.
Что мы пробовали
2 способа перехвата сетевых запросов с помощью AVPlayer.
- Соответствует AVAssetResourceLoaderDelegate и обрабатывает загрузку носителя вручную
Не работает с HLS. Вы можете загружать файлы m3u8, реализуя AVAssetResourceLoaderDelegate, который позволяет передавать аутентификацию или расшифровывать ответ, однако файлы .ts не могут быть загружены.
Вот код, который мы пробовали:
https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6
- Реализация NSURLProtocol для захвата запросов для файлов
.ts
.
AVURLAsset фактически избегает перехвата. Как-то сетевые запросы просто не захватываются. (Не знаю, почему)
Ответы
Ответ 1
Начнем с действительно хороших новостей - iOS 10 и выше - выдает это из коробки.
Вскоре не будет необходимости в хаке. Более подробную информацию можно найти в следующем сеансе WWDC16 о том, что нового в потоке HTTP Live:
https://developer.apple.com/videos/play/wwdc2016/504/
Теперь вернемся к текущему состоянию вещей - iOS 9 и ниже:
С AVPlayer нет. Но вы можете кэшировать сегменты HLS через локальный HTTP-сервер и воспроизводить локальный поток с помощью AVPlayer.
AVPlayer и AVAsset не содержат необходимой информации при работе с HLS-воспроизведением (он ведет себя иначе, чем статический файл MP4, например).
TL; DR - вам нужно использовать HTTP-запросы для получения сегментов и их обслуживания с помощью локального HTTP-сервера.
Несколько компаний, включая ту, для которой я работаю, используют эту стратегию.
Используйте соединение для загрузки сегментов по желаемому качеству, перестройте манифест и скомпенсируйте все это в один каталог и одно качество, а затем используйте локальный HTTP-сервер внутри приложения, чтобы обслуживать его в AVPlayer (AVPlayer может воспроизводить только HLS потоки, переданные через HTTP, а не из файловых ресурсов).
Существуют крайние случаи, например, буферизация, если вы хотите играть и загружать за один проход, правильно перестраивая манифест m3u8, и различные состояния AVPlayer с чтением диска.
Я нашел это из первых рук, имея такую систему в производстве в течение 5 лет и других видеопродуктах в App Store, которые используют одно и то же решение - в целом обслуживают многих пользователей.
Это также лучшее решение для Android.
Ответ 2
На самом деле мы можем заставить AVPlayer воспроизводить видео из сети, но если вы хотите кэшировать загруженные данные, чтобы воспроизводить их локально, AVPlayer теперь кажется невозможным.
К счастью, в AVURLAsset есть большой API-интерфейс - объект resourceLoader, который вы можете предоставить контролируемому доступу к удаленному аудиофайлу в AVPlayer. Это работает как локальный HTTP-прокси, но без всех неприятностей.
Вы можете найти более подробную информацию о https://gist.github.com/anonymous/83a93746d1ea52e9d23f
Ответ 3
О NSURLProtocol
:
Как я понял, он создает собственные запросы, поэтому ваши пользовательские теги/поля/метки будут удалены.
Я сделал это по-другому: перенаправляет запросы сегментов на какую-то настраиваемую схему URL-адресов и просто проверяет схему в протоколе canInitWithRequest
.
Таким образом, все работает отлично. (потратил неделю на то, чтобы вычислить всю обработку hls-обработки...)