http-video-streaming-headers

Par divinevideo · divine-mobile

Corrige les erreurs « Failed to load video » lorsque les requêtes réseau réussissent (statut 200/206). À utiliser quand : (1) l'élément vidéo affiche une erreur mais DevTools montre des requêtes réussies, (2) les vidéos se téléchargent correctement via curl mais échouent dans le navigateur, (3) les range requests fonctionnent mais la vidéo refuse de se lire, (4) vous construisez un CDN/serveur média pour le streaming vidéo. La cause racine est souvent l'absence du header `Accept-Ranges`, dont les navigateurs ont besoin pour la navigation temporelle et le streaming vidéo.

npx skills add https://github.com/divinevideo/divine-mobile --skill http-video-streaming-headers

Exigences des En-têtes HTTP pour la Diffusion Vidéo

Problème

Les éléments vidéo HTML5 ne parviennent pas à lire avec une erreur « Impossible de charger la vidéo » même si les requêtes réseau affichent des réponses 200/206 réussies. Le fichier vidéo se télécharge correctement quand testé avec curl, mais les navigateurs refusent de le lire.

Contexte / Conditions de Déclenchement

  • L'élément vidéo déclenche l'événement onerror malgré le succès réseau
  • L'onglet Network de DevTools affiche le statut 200 ou 206 pour les requêtes vidéo
  • curl -O <video-url> télécharge un fichier MP4 valide
  • La vidéo se lit localement une fois téléchargée
  • Le message d'erreur est générique : « Impossible de charger la vidéo » ou code d'erreur média 4

Solution

En-têtes Requis pour la Diffusion Vidéo

  1. Accept-Ranges: bytes (CRITIQUE)

    • Indique au navigateur que les requêtes en plage sont supportées
    • Sans cela, les navigateurs peuvent ne pas tenter les requêtes en plage pour la navigation
    • Ajouter à TOUTES les réponses vidéo, même les réponses complètes (200)
  2. Content-Type: video/mp4 (ou type MIME approprié)

    • Doit correspondre au format vidéo réel
    • Le navigateur l'utilise pour sélectionner le décodeur
  3. Content-Length (pour les réponses complètes)

    • Requis pour que le navigateur connaisse la taille du fichier
    • Active les indicateurs de progression et les calculs de navigation
    • Note : Pour les réponses 206, ce doit être la taille du contenu partiel
  4. Pour les Requêtes en Plage (206 Contenu Partiel):

    • Content-Range: bytes DÉBUT-FIN/TOTAL
    • Le code de statut DOIT être 206, pas 200

Implémentation Serveur

// Exemple Fastly Compute@Edge
resp.set_header("Accept-Ranges", "bytes");
resp.set_header("Content-Type", "video/mp4");

// Pour les réponses complètes uniquement (pas 206):
if resp.get_status() != StatusCode::PARTIAL_CONTENT {
    resp.set_header("Content-Length", file_size.to_string());
}

Considérations CDN

  • Les caches edge peuvent retirer ou modifier les en-têtes
  • Vérifier que les en-têtes atteignent le client, pas seulement l'origine
  • Fastly/CloudFront peuvent servir les requêtes en plage à partir du contenu complet en cache
  • Tester avec curl -I -H "Range: bytes=0-1023" pour vérifier la réponse 206

Vérification

# Vérifier l'en-tête Accept-Ranges
curl -I https://cdn.example.com/video.mp4 | grep -i accept-ranges
# Attendu : accept-ranges: bytes

# Tester le support des requêtes en plage
curl -I -H "Range: bytes=0-1023" https://cdn.example.com/video.mp4
# Attendu : HTTP/2 206 avec en-tête Content-Range

# Vérifier que le téléchargement partiel fonctionne
curl -H "Range: bytes=0-100" https://cdn.example.com/video.mp4 | wc -c
# Attendu : 101 (octets 0-100 inclus)

Exemple

Avant (cassé):

HTTP/2 200
content-type: video/mp4
x-custom-header: value

La vidéo ne se charge pas dans le navigateur.

Après (fonctionnant):

HTTP/2 200
content-type: video/mp4
content-length: 1443199
accept-ranges: bytes

La vidéo se lit correctement avec support de navigation.

Notes

  • Même si votre CDN gère automatiquement les requêtes en plage, vous devriez toujours inclure Accept-Ranges: bytes dans les en-têtes de réponse
  • Certains navigateurs sont plus tolérants que d'autres ; Safari exige souvent un support correct des plages tandis que Chrome peut fonctionner sans
  • Les réponses HTTP/2 peuvent avoir les en-têtes en minuscules (c'est normal)
  • Pour la diffusion HLS/DASH, le manifeste et les segments ont tous besoin des en-têtes appropriés
  • Les navigateurs mobiles sont particulièrement stricts concernant les en-têtes vidéo

Références

Skills similaires