Partage
  • Partager sur Facebook
  • Partager sur Twitter

[nodejs] [stream] [Content-Ranges]

native video player not work

Sujet résolu
    19 mai 2022 à 23:12:29

    Bonjour, j'ai une route HTTP dans un projet Nodejs qui pipe un stream dans une réponse (un flux video mp4).

    La route fonctionne le fichier est lisible dans le navigateur, par contre au niveau du navigateur je ne peux pas naviguer dans la "duration" (timeline) de la video.

    Les clicks sur la "timeline" qui est encadré en rouge ne fonctionne pas le déplacement via "drag and drop" non plus,

    en faite la timeline change et revient quasi-immédiatement à l'endroit précédent.

    En cherchant un peut j'ai vue qu'il fallait définir un en-tête

    Accept-Range

    pour indiquer au navigateur que la ressource est "navigable"

    Est au niveau de la requête il faut envoyer un en-tête Content-Range et passé en valeur l'éventail de données qu'on veut récupéré puis parser les valeurs côté serveur ect, ect...

    Mais en faite ça ne permet pas au player "native" de fonctionner, ça me sert juste à faire des requêtes personnaliser pour "manuellement" avancer/reculer dans la "timeline" du fichier, non ?

    Le snippet de code qui génère le flux video:

          const createStream = (videoFormat?: videoFormat) => {
            response.header("Content-Disposition", "inline; filename=stream-yt.mp4");
            response.header('Accept-Ranges', 'bytes');
            response.header('Content-Length', videoFormat?.contentLength || "0");
            response.type('video/mp4');
            response.statusCode = StatusCodes.PARTIAL_CONTENT;
    
            const stream = ytdl(`http://www.youtube.com/watch?v=${key}`, {
              format: videoFormat,
              begin: (typeof startAt === 'string' ? startAt: "0m0s")
            })
    
            stream.pipe(response, {
              end: true
            })
          }

    J'ai un paramètre startAt qui peut être passé dans l'URL c'est un timecode de la vidéo qui permet de facilement changer la timeline,

    mais du coup j'ai le même problème le player native du navigateur, il y comprend rien à mon paramètre du coup il marche pas.

    J'imagine que je peux plus où moins le faire fonctionner d'une façon où d'une autre en bricolant un player en Javascript qui va écouter les changement dans la timeline est mettre à jour l'url du stream, met j'aimerais quand même que le player par défaut du navigateur puisse fonctionner.

    Si quelqu'un à déjà manipuler des flux dans un contexte HTTP(s) est a déjà eu ce problème (même si c'est dans un autre langages j'imagine que la logique du problème est transposable et doit se situer au niveau des Headers HTTP notamment) et qu'il pourrait me partager l'expérience de sont problème, cela pourrait surement m'aider, merci d'avance.

    • Partager sur Facebook
    • Partager sur Twitter

    suggestion de présentation.

      20 mai 2022 à 12:22:22

      Hello,

      Normalement la balise <video> est sensée faire des requêtes avec des Range lorsque c'est possible. Si le serveur répond avec un code 206 et un chunk correct, cela devrait fonctionner sans soucis.

      Voici un exemple avec Node qui envoie des chunks de 1Mo à chaque requête disposant d'une en-tête "Range" :

      app.get("/stream/video", function(req, res) {
        const range = req.headers.range;
        if (!range) {
          return res.status(400).send("Requires Range header");
        }
      
        const videoPath = path.join(__dirname, "videos", `video.mp4`);
        const videoSize = fs.statSync(videoPath).size;
      
        const CHUNK_SIZE = 10 ** 6; // 1MB
        const start = Number(range.replace(/\D/g, ""));
        const end = Math.min(start + CHUNK_SIZE, videoSize - 1);
        const contentLength = end - start + 1;
      
        const headers = {
          "Content-Range": `bytes ${start}-${end}/${videoSize}`,
          "Accept-Ranges": "bytes",
          "Content-Length": contentLength,
          "Content-Type": "video/mp4",
        };
        res.writeHead(206, headers);
      
        fs.createReadStream(videoPath, { start, end }).pipe(res);
      });
      

      Plus d'infos ici : https://blog.logrocket.com/build-video-streaming-server-node/

      -
      Edité par jmpp 20 mai 2022 à 12:23:38

      • Partager sur Facebook
      • Partager sur Twitter
      HTML5 & JavaScript enthusiast (webdev/gamedev/mobile/demoscene). [github, twitter@_jmpp]
        21 mai 2022 à 13:00:13

        Oui, en effet le Content-Range + Accept-Range avec un status 206 suffit à faire comprendre au navigateur comment naviguer dans la ressource,

        je me doutais que cela venais des en-têtes car ces les résultats qui revenait le plus dans les recherches que j'avais faites, mais j'avais pas bien compris comment les faire fonctionner correctement.

        L'article que tu as trouvé est assez explicite j'ai réussie à le faire fonctionner, merci.

        • Partager sur Facebook
        • Partager sur Twitter

        suggestion de présentation.

        [nodejs] [stream] [Content-Ranges]

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        • Editeur
        • Markdown