web-dev-qa-db-fra.com

Est-il possible de mettre en cache des segments HLS avec AVPlayer?

Problème racine

Notre vidéo tamponne beaucoup lors de la recherche dans iOS. Il tamponne un peu plus que notre lecteur Web, qui enregistre des copies des segments déjà visités dans la mémoire temporaire.

Solution souhaitée

Mettre en cache les segments vidéo localement sur le disque de l'appareil. Nous acceptons de mettre en cache une qualité unique et de la rejouer en permanence.

Bloqueur

Nous ne pouvons pas trouver un moyen d'effectuer la mise en cache dans AVFoundation/AVPlayer.

Ce que nous avons essayé

2 façons d'intercepter les requêtes réseau avec AVPlayer.

  1. Conformité à AVAssetResourceLoaderDelegate et gestion manuelle du chargement du support

Ne fonctionne pas avec HLS. Vous pouvez charger les fichiers m3u8 en implémentant AVAssetResourceLoaderDelegate, ce qui vous permet de transmettre une authentification ou de déchiffrer la réponse. Toutefois, les fichiers .ts ne peuvent pas être chargés. Voici le code que nous avons essayé: https://Gist.github.com/nathanhillyer/84e46152d7c4c88183b6

  1. Implémentation d'un protocole NSURL pour capturer les demandes de fichiers .ts.

AVURLAsset évite en fait d’être intercepté. D'une manière ou d'une autre, les requêtes réseau ne sont tout simplement pas capturées. (Aucune idée pourquoi)

26
Nathan Hillyer

Commençons par de très bonnes nouvelles - iOS 10 et les versions ultérieures - le sort de la boîte. Plus besoin de piratage bientôt. Vous trouverez plus de détails dans la session WWDC16 suivante sur les nouveautés de la diffusion HTTP en direct: https://developer.Apple.com/videos/play/wwdc2016/504/

Revenons maintenant à l'état actuel des choses - iOS 9 et inférieur: Avec AVPlayer, non. Mais vous pouvez mettre en cache les segments HLS via un serveur HTTP local et lire le flux local avec AVPlayer.

AVPlayer et AVAsset ne contiennent pas les informations nécessaires lors de la lecture HLS (par exemple, il se comporte différemment d’un fichier statique MP4).

TL; DR - Vous devez utiliser des requêtes HTTP pour obtenir les segments et les servir via un serveur HTTP local.

Quelques entreprises, y compris celle pour laquelle je travaille, utilisent cette stratégie.

Utilisez une connexion pour télécharger les segments avec la qualité souhaitée, reconstruisez le manifeste et mettez-le dans un répertoire et une qualité, puis utilisez un serveur http local dans l'application pour le servir à AVPlayer (AVPlayer ne peut lire que les flux HLS diffusés HTTP - pas à partir des fichiers).

Il existe des cas Edge, tels que la mise en mémoire tampon si vous voulez lire et télécharger en une fois, la reconstruction du manifeste m3u8 correctement et différents états de AVPlayer avec lecture de disque.

Je l'ai découvert grâce à des connaissances de première main, à la fois avec un tel système en production depuis 5 ans et d'autres produits vidéo sur l'App Store qui utilisent la même solution - servant au total de nombreux utilisateurs.

C'est aussi la meilleure solution que nous avons trouvée pour Android.

9
Liviu R

En fait, nous pouvons obliger AVPlayer à lire une vidéo du réseau, mais si vous souhaitez mettre en cache les données téléchargées pour les lire localement, avec AVPlayer, cela semble impossible maintenant. 

Heureusement, il existe une excellente API: l'objet resourceLoader dans AVURLAsset, pour lequel vous pouvez fournir un accès contrôlé à un fichier audio distant pour AVPlayer. Cela fonctionne comme un proxy HTTP local mais sans les tracas.

Vous trouverez plus de détails sur https://Gist.github.com/anonymous/83a93746d1ea52e9d23f

2
HDT

À propos de NSURLProtocol: Si j'ai bien compris, cela crée ses propres requêtes, ainsi vos balises/champs/marques personnalisés seront supprimés.

Je l'ai fait autrement: redirigez les requêtes de segments vers un schéma d'URL personnalisé et vérifiez simplement le schéma dans la méthode canInitWithRequest du protocole.

De cette façon cela fonctionne très bien. (passé une semaine à comprendre tout le traitement hls ...)

0
norlin