¿Es posible almacenar en caching segmentos de HLS con AVPlayer?

Problema de raíz

Nuestro video almacena mucho cuando se busca en iOS. Almacena un poco más de espacio que nuestro reproductor web, que guarda copys de los segmentos ya vistos en el almacenamiento temporal.

Solución deseada

Almacenamiento en caching de los segmentos de video localmente en el disco del dispositivo. Estamos bien con el almacenamiento en caching de una sola calidad y siempre volver a reproducirlo.

Bloqueador

No podemos encontrar la manera de realizar el almacenamiento en caching dentro de AVFoundation / AVPlayer.

Lo que hemos probado

2 forms de interceptar requestes de networking con AVPlayer.

  1. Conforme a AVAssetResourceLoaderDelegate y event handling la carga del medio manualmente

No funciona con HLS. Puede cargar los files m3u8 implementando AVAssetResourceLoaderDelegate, lo que le permite pasar la authentication o descifrar la respuesta, sin embargo, los files .ts no se pueden cargar. Aquí está el código que probamos: https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6

  1. Implementación de un NSURLProtocol para capturar requestes de files .ts .

AVURLAsset realmente evita ser interceptado. De alguna manera las requestes de networking simplemente no son capturadas. (Sin idea de por qué)

Comencemos con una buena noticia, iOS 10 y más, da esto de la caja. No más necesidad de hacks pronto. Se pueden encontrar más detalles en la siguiente session WWDC16 sobre qué hay de nuevo en HTTP Live Streaming: https://developer.apple.com/videos/play/wwdc2016/504/

Ahora vuelve al estado actual de las cosas: iOS 9 y versiones inferiores: con AVPlayer, no. Pero puede almacenar en caching segmentos de HLS a través de un server HTTP local y reproducir el flujo local con AVPlayer.

AVPlayer y AVAsset no contienen la información necesaria cuando se trata de reproducción HLS (se comporta de manera diferente que un file MP4 estático, por ejemplo).

TL; DR: necesita utilizar requestes HTTP para get los segmentos y servirlos utilizando un Servidor HTTP local.

Algunas compañías, incluida la que estoy trabajando, están utilizando esta estrategia.

Use una connection para download los segmentos con la calidad que desee, vuelva a generar el manifiesto y aplíquelo todo en un directory y una calidad y luego use un server http local dentro de la aplicación para enviarlo a AVPlayer (AVPlayer solo puede reproducir secuencias HLS servidas sobre HTTP – no de los activos de file).

Hay casos de borde, como el almacenamiento en búfer, si desea reproducir y download en una ejecución, rebuild correctamente el manifiesto m3u8 y diferentes estados de AVPlayer con la lectura del disco.

Lo he descubierto gracias al conocimiento de primera mano, que tienen un sistema de este tipo en producción durante 5 años y otros productos de video en la App Store que utilizan la misma solución, en total sirven a muchos usuarios.

Esta es también la mejor solución que hemos encontrado para Android.

En realidad, podemos hacer que AVPlayer reproduzca un video desde la networking, pero si desea almacenar en caching los datos descargados para reproducirlo localmente, con AVPlayer eso parece imposible ahora.

Afortunadamente, hay una gran API que es el object resourceLoader en AVURLAsset, que puede proporcionar acceso controlado a un file de audio remoto a AVPlayer. Esto funciona como un proxy HTTP local, pero sin todas las molestias.

Puede encontrar más detalles en https://gist.github.com/anonymous/83a93746d1ea52e9d23f

Acerca de NSURLProtocol : como lo entendí, realiza requestes propias, por lo que sus tags / campos / marcas personalizadas se eliminarán.

Lo he hecho de otra manera: networkingirigir las requestes de segmentos a un esquema personalizado de url y simplemente verificar el esquema en el método canInitWithRequest del protocolo.

De esta manera funciona bien. (pasó una semana para calcular todo lo que hls-processing out …)