Le HLS fonctionne sur le téléphone, mais pas sur le téléviseur : diagnostic de la diffusion
Diagnostiquez un HLS lisible en local mais défaillant sur le téléviseur en séparant émetteur, récepteur, CORS, requêtes Range, codecs, autorisation et fenêtre live.
Un flux HLS peut fonctionner parfaitement sur un téléphone ou un ordinateur, se connecter à un téléviseur, puis s'arrêter après quelques secondes. Ce résultat ne prouve ni que le Wi-Fi du téléviseur est faible, ni que la playlist est universellement compatible. Dans de nombreux systèmes de diffusion, le récepteur distant charge lui-même le média. Les requêtes réussies et le décodeur de l'émetteur ne représentent alors plus l'ensemble du parcours de lecture.
Ce guide examine séparément le contrôle par l'émetteur, le réseau du récepteur, la compatibilité du média, l'autorisation et la sortie. N'utilisez que des flux que vous possédez ou que vous êtes autorisé à inspecter. Avant de partager des journaux, retirez les paramètres de requête signés, cookies, identifiants d'appareil, adresses IP et données de compte.
Méthode de vérification — 21 septembre 2026 : nous avons exécuté, avec Node.js 24.12.0, un service HTTP limité à l'interface locale et deux origines de requête fictives. Le serveur autorisait https://sender.example.test, mais omettait Access-Control-Allow-Origin pour https://receiver.example.test. Les deux origines ont reçu les octets de la playlist ainsi qu'une réponse 206 à une requête Range de quatre octets ; seule l'origine de l'émetteur a reçu un en-tête CORS correspondant. Ce test vérifie uniquement la différence entre les en-têtes HTTP du service de test et sa réponse Range. Le fetch de Node n'applique pas la politique CORS du navigateur. Nous n'avons testé ni Chromecast, Apple TV, récepteur AirPlay, téléviseur connecté, système DRM ou véritable décodeur multimédia. Les indications propres aux appareils ci-dessous reposent sur la documentation. Le test se trouve dans scripts/test-cast-hls-origin-headers.cjs.
Déterminer où la lecture a été transférée
Le mot « diffusion » peut désigner plusieurs architectures. Un onglet de navigateur peut être recopié à l'écran, le système peut transmettre une URL multimédia au récepteur, ou une application peut communiquer avec son propre programme récepteur. Le téléviseur peut donc afficher des pixels calculés par l'émetteur ou exécuter un lecteur indépendant qui émet ses propres requêtes HLS.
| Observation | Ce qu'elle suggère | Ce qu'elle ne prouve pas |
|---|---|---|
| L'onglet recopié continue lorsque le téléviseur prend la main | L'émetteur assure peut-être encore le rendu | Le récepteur peut charger l'URL HLS de façon autonome |
| Le téléphone devient une télécommande | Le récepteur gère probablement la lecture | Le récepteur a reçu les mêmes cookies ou le même contexte d'autorisation |
| Le téléviseur affiche un titre ou une image, puis quitte | Le message de contrôle et certaines métadonnées sont arrivés | La playlist, les segments, le codec ou la licence ont fonctionné |
| La lecture locale continue après l'échec du téléviseur | Le parcours de l'émetteur est sain pour cette session | Le réseau, les en-têtes, le décodeur ou la position live du récepteur sont sains |
| Toutes les autres vidéos sont diffusées correctement | La découverte de l'appareil et la sortie de base fonctionnent | Cette présentation HLS est compatible |
Notez s'il s'agit d'une recopie d'écran, de Remote Playback dans le navigateur, de Google Cast, d'AirPlay, d'une application pour téléviseur ou d'une connexion HDMI. Ne regroupez pas les résultats de ces parcours sous une seule étiquette. MDN classe l'API web Remote Playback parmi les fonctions à disponibilité limitée : la présence d'un bouton Cast ou AirPlay ailleurs dans le système d'exploitation ne permet donc pas d'en déduire sa prise en charge dans une page web.
Recueillir séparément les preuves de l'émetteur et du récepteur
Les outils de développement du navigateur de l'émetteur montrent généralement les requêtes de sa propre page, pas nécessairement celles du récepteur. L'arrêt des téléchargements de segments sur l'émetteur juste après le transfert peut être normal. Sans trace côté récepteur, le panneau Network ne peut pas identifier la requête qui a échoué sur le téléviseur.
Pour une application que vous contrôlez, recueillez les journaux du récepteur ou les requêtes du CDN autour de l'heure du transfert. Corrélez-les au moyen d'un identifiant de session ou de requête respectueux de la vie privée, sans publier l'URL du média. Relevez :
- L'heure exacte du transfert et le fuseau horaire.
- L'appareil émetteur, la version du navigateur ou de l'application, le réseau et l'état de la lecture locale.
- Le modèle du récepteur, son micrologiciel ou sa version logicielle, son réseau et l'écran de sortie.
- L'URL finale de la playlist après redirections et la première requête du récepteur.
- Le statut, le type de contenu, l'en-tête Range, le résultat du cache et l'URL finale du premier échec.
- La variante choisie, les codecs, le groupe audio, la piste de sous-titres et la position dans le média.
- Le passage de l'état de contrôle à la lecture, à la mise en mémoire tampon, à l'inactivité ou à l'erreur.
Lorsque les journaux du récepteur sont inaccessibles, ceux du serveur ou du CDN constituent souvent le premier moyen fiable de confirmer que le téléviseur a demandé la playlist. Notre guide d'inspection des requêtes reste utile côté émetteur, mais ne remplace pas une trace du récepteur.
Vérifier CORS sur le parcours du récepteur
La documentation Google sur le Web Receiver indique que les protocoles de streaming utilisent des requêtes asynchrones soumises à CORS et que le serveur de contenu détermine où le média peut être inclus. Google précise également que les médias adaptatifs et les pistes doivent recevoir les en-têtes CORS appropriés. Autoriser uniquement le site qui contient le bouton Cast peut donc être insuffisant si l'application réceptrice possède une autre origine.
Notre test illustre ce piège de diagnostic : les deux origines fictives ont reçu un statut HTTP 200 pour le manifeste, mais l'origine du récepteur n'a obtenu aucun Access-Control-Allow-Origin correspondant. Un journal serveur qui contient un 200 ne prouve pas que le JavaScript du récepteur peut lire la réponse. La plateforme du récepteur décide si et comment elle applique CORS ; notre test Node n'a pas simulé ce contrôle.
Inspectez CORS sur toute la chaîne :
- Playlists multivariantes et playlists média.
- Segments d'initialisation et segments média.
- Playlists et segments des pistes audio et de sous-titres alternatives.
- Clés de chiffrement et points de terminaison de licence autorisés.
- Destinations des redirections, et pas seulement le nom d'hôte initial.
- Réponses aux requêtes Range et, lorsqu'elles existent, aux requêtes préliminaires.
N'installez pas de proxy public ouvert et n'affaiblissez pas les contrôles d'accès de production comme solution définitive. Configurez précisément les origines, identifiants, méthodes et en-têtes prévus sur l'infrastructure que vous contrôlez, puis retestez avec le véritable récepteur.
Comparer les autorisations sans copier de secrets
La lecture locale peut dépendre d'un cookie du navigateur, d'un en-tête Authorization, d'un référent ou d'une URL signée à courte durée de vie. Un récepteur distant n'hérite pas automatiquement de chaque élément de la session de l'émetteur. Une playlist principale peut se charger alors que ses playlists enfants, ses clés ou ses segments utilisent une autorisation expirée ou incomplète.
Suivez la première requête du récepteur sur toute la chaîne de playlists. Comparez les paramètres et en-têtes présents, la durée de validité de chaque signature et l'effet des redirections sur l'autorisation. Si le flux fonctionne brièvement avant de s'arrêter, comparez l'expiration du jeton à l'heure de l'échec, sans considérer cette proximité temporelle comme une preuve suffisante.
Ne publiez jamais une URL signée encore valide dans un rapport et ne l'intégrez pas en dur dans une page. Transmettez plutôt au responsable du service les chemins anonymisés, les statuts, les durées d'expiration et les identifiants de requête.
Vérifier les requêtes Range et les types de réponse
Un récepteur peut utiliser des plages d'octets même si la lecture locale demandait les objets en entier. Notre test a renvoyé 206 Partial Content, Content-Range et Accept-Ranges pour une requête de segment contrôlée. Il n'a validé ni conteneur multimédia ni comportement d'appareil.
Sur un média réel que vous êtes autorisé à tester, vérifiez la cohérence de la réponse à une requête Range : statut 206 lorsque le contexte le prévoit, Content-Range valide, taille totale exacte, octets demandés et type de contenu multimédia. Repérez les CDN ou couches d'autorisation qui ignorent, suppriment ou refusent Range. Un statut 200 peut être légitime pour certaines ressources et certains clients ; interprétez-le avec la requête observée et la documentation de la plateforme au lieu d'appliquer une règle universelle.
Vérifiez également que les adresses .m3u8 renvoient du texte HLS commençant par #EXTM3U, et non une page HTML de connexion ou de contrôle CDN. Notre guide général de dépannage HLS explique comment un statut réussi peut tout de même contenir un mauvais corps de réponse.
Adapter les codecs au récepteur, pas au téléphone
Le téléphone et le téléviseur peuvent différer par leurs décodeurs matériels, profils pris en charge, dispositions de canaux, résolutions maximales, fréquences d'images, capacités HDR et limites de conteneur. Un flux décodé par l'émetteur n'est pas automatiquement compatible avec le récepteur.
Google publie les formats acceptés selon les appareils Cast et fournit CastReceiverContext.canDisplayType() aux applications réceptrices compatibles. Sa documentation actuelle indique des limites de codec et de résolution différentes selon l'appareil et précise, par exemple, que HEVC n'est pas pris en charge dans un conteneur Transport Stream. Consultez le tableau du modèle cible au lieu de vous fier au mot « 4K » ou à un essai réussi sur téléphone.
Inspectez les attributs CODECS, RESOLUTION, FRAME-RATE, les canaux audio et le média réel de la playlist multivariante. Proposez une variante prudente en H.264/AAC si elle correspond aux appareils officiellement pris en charge, mais ne vous contentez pas de modifier l'étiquette d'un média incompatible. Pour les problèmes d'audio alternatif, consultez notre diagnostic des pistes audio HLS.
Traiter le transfert d'un direct comme un problème de fenêtre temporelle
Lorsqu'il rejoint un direct, le récepteur part de son propre instantané de playlist et choisit sa propre position. Une playlist conservée trop longtemps en cache, des segments annoncés avant leur disponibilité ou un démarrage au bord d'une fenêtre sur le point de disparaître peuvent faire échouer le récepteur alors que la lecture locale continue.
Conservez plusieurs réponses successives de la playlist média côté récepteur. Comparez #EXT-X-MEDIA-SEQUENCE, le segment le plus récent, les en-têtes de cache, l'heure de la requête et le premier segment choisi par le récepteur. Vérifiez que ce segment était encore disponible au moment du transfert. Ne déduisez pas la récupération du récepteur du simple fait que le téléphone continue : les deux clients peuvent occuper des positions différentes.
Notre guide sur les playlists périmées et les segments manquants aide à distinguer un instantané live qui ne change plus d'un objet nouvellement annoncé qui répond 404. Pour le HLS à faible latence, assurez-vous que le parcours du récepteur prend réellement en charge les fonctions utilisées par la présentation ; toutes les variantes de HLS ne sont pas équivalentes.
Tester la sortie et l'état du contrôle
Si les requêtes et le décodage semblent sains, vérifiez si la lecture est simplement muette, envoyée vers une autre sortie, en pause ou masquée par un problème HDMI, HDCP ou de mode d'affichage. Relevez le volume, l'état muet, la route audio, les capacités de l'écran et la progression du temps vidéo sur le récepteur.
Un bouton qui affiche « connecté » sur l'émetteur prouve l'existence d'une session de contrôle, pas la réussite de la lecture. De même, l'image affichée sur le téléviseur peut provenir de métadonnées reçues avant le décodage du moindre segment. Enregistrez les transitions de l'état média du récepteur et la première erreur significative au lieu d'assimiler connexion et lecture.
Le DRM ajoute une autre frontière. Un flux protégé exige un parcours DRM pris en charge par le récepteur, un échange de licence, des identifiants et une protection de sortie. Un récepteur générique ne peut ni inventer une licence ni contourner la protection. Testez uniquement dans le parcours officiel et autorisé de l'application.
Construire une matrice d'appareils reproductible
Testez chaque combinaison prise en charge sans modifier plusieurs variables à la fois :
| Dimension | Informations minimales utiles |
|---|---|
| Émetteur | Appareil, système, version du navigateur ou de l'application, résultat local |
| Récepteur | Modèle exact, version du micrologiciel ou du logiciel récepteur, réseau filaire ou sans fil |
| Présentation | VOD, direct ou faible latence, variante choisie, codecs, état DRM |
| Point de transfert | Avant la lecture, pendant une lecture stable, après une recherche, après le retour du réseau |
| Résultat | Délai avant la première image, première requête récepteur en échec, état média final |
| Contrôle | Flux autorisé et connu comme fonctionnel sur le même émetteur et le même récepteur |
Testez au moins une variante à faible et à haut débit, l'audio alternatif, les sous-titres, la recherche, la pause et la reprise, ainsi qu'un transfert après l'avancée de la fenêtre live. Réduire la largeur d'un navigateur de bureau ne constitue pas un test du récepteur. Marquez explicitement comme non testés les appareils indisponibles ou non pris en charge.
Rédiger le rapport autour du premier échec du récepteur
Un rapport exploitable peut indiquer : « La lecture locale a continué. À 18:42:11, le récepteur modèle X a demandé la playlist média et reçu 200, puis sa première requête de segment a reçu 403 après une redirection. L'identifiant anonymisé est Y. » Cette formulation désigne le bon domaine de responsabilité et la prochaine vérification.
Incluez l'architecture de diffusion, les versions de l'émetteur et du récepteur, le type et le statut de la première URL côté récepteur, les en-têtes CORS et Range, le codec ou la variante choisi, la durée de l'autorisation, la séquence live et la transition d'état média. Excluez les identifiants bruts et les URL privées.
Références primaires
- Google Cast : Web Receiver personnalisé et CORS
- Google Cast : médias pris en charge et limites des codecs par appareil
- Google Cast : protocoles de streaming du Web Receiver
- Google Cast : exigences CORS pour les pistes média
- MDN : API Remote Playback
- RFC 8216 : HTTP Live Streaming
Quand le HLS fonctionne en local mais échoue sur le téléviseur, commencez par établir quel appareil demande réellement le média. Suivez ensuite, dans l'ordre, CORS côté récepteur, l'autorisation, les requêtes Range, les codecs, le minutage live, le décodage et la sortie. Une requête réussie sur le téléphone ne valide pas un parcours de réception distinct.