web-dev-qa-db-fra.com

HTML5 - Comment diffuser de gros fichiers .mp4?

J'essaie de configurer une page HTML très basique qui charge une vidéo au format .mp4 de 20 Mo. Il semble que le navigateur ait besoin de tout télécharger plutôt que de simplement lire la première partie de la vidéo et de la diffuser en continu.

Ce post est la chose la plus proche que j'ai trouvée lors de la recherche ... J'ai essayé à la fois Hand Brake et Data Go Round par aucun des deux ne semblait faire une différence:

Des idées sur la façon de faire ceci ou si c'est possible?

Voici le code que j'utilise:

<video controls="controls">
    <source src="/video.mp4" type="video/mp4" />
    Your browser does not support the video tag.
</video>
73
longda
  1. Assurez-vous que moov (métadonnées) est avant le mdat (données audio/vidéo)) . Ceci est également appelé "démarrage rapide" ou "optimisé pour le Web". Par exemple, Handbrake a une case à cocher "Web optimisée" , et ffmpeg et avconv ont l'option de sortie -movflags faststart.
  2. Assurez-vous que votre serveur Web signale le type de contenu correct (video/mp4).
  3. Assurez-vous que votre serveur Web est configuré pour répondre aux demandes de plage d'octets .
  4. Assurez-vous que votre serveur Web n’applique pas gzip ou n’affaiblissez pas la compression au-dessus de la compression du fichier mp4.

Vous pouvez vérifier les en-têtes envoyés par votre serveur Web en utilisant curl -I http://yoursite/video.mp4 ou en utilisant les outils de développement de votre navigateur ( Chrome , Firefox ) (rechargez la page si elle est mise en cache). L'en-tête de réponse HTTP doit inclure Content-Type: video/mp4 et Accept-Ranges: bytes et no Codage de contenu: .

135
mark4o

Voici la solution que j'ai utilisée pour créer un contrôleur API Web en C # (MVC) qui servira les fichiers vidéo avec des plages d'octets (demandes partielles). Les demandes partielles permettent à un navigateur de ne télécharger que la quantité de vidéo dont il a besoin pour lire plutôt que de télécharger la vidéo entière. Cela le rend beaucoup plus efficace.

Notez que cela ne fonctionne que dans les versions récentes.

var stream = new FileStream(videoFilename, FileMode.Open, FileAccess.Read , FileShare.Read);

var mediaType = MediaTypeHeaderValue.Parse($"video/{videoFormat}");

if (Request.Headers.Range != null)
{
    try
    {
        var partialResponse = Request.CreateResponse(HttpStatusCode.PartialContent);
        partialResponse.Content = new ByteRangeStreamContent(stream, Request.Headers.Range, mediaType);

        return partialResponse;
    }
    catch (InvalidByteRangeException invalidByteRangeException)
    {
        return Request.CreateErrorResponse(invalidByteRangeException);
    }
}
else
{
    // If it is not a range request we just send the whole thing as normal
    var fullResponse = Request.CreateResponse(HttpStatusCode.OK);

    fullResponse.Content = new StreamContent(stream);
    fullResponse.Content.Headers.ContentType = mediaType;

    return fullResponse;
}
4
Chris