Search code examples
node.jsangularvideo-streamingnodejs-stream

Res many videos Nodejs


I'm working on an app who contains a page of videos. The front is in Angular and the back in Node.js

I choice to store my videos directly with API in the assets folder.

  files.forEach(file => {
    console.log(file);
  });
});

I can take my videos's path with fs.

At this moment i can only res one video with this code :

                const path = 'videos/Cycle de vie des déchets/test.mp4'
                const stat = fs.statSync(path)
                const fileSize = stat.size
                const range = req.headers.range
              
                if (range) {
                  const parts = range.replace(/bytes=/, "").split("-")
                  const start = parseInt(parts[0], 10)
                  const end = parts[1]
                    ? parseInt(parts[1], 10)
                    : fileSize-1
              
                  if(start >= fileSize) {
                    res.status(416).send('Requested range not satisfiable\n'+start+' >= '+fileSize);
                    return
                  }
                  
                  const chunksize = (end-start)+1
                  const file = fs.createReadStream(path, {start, end})
                  const head = {
                    'Content-Range': `bytes ${start}-${end}/${fileSize}`,
                    'Accept-Ranges': 'bytes',
                    'Content-Length': chunksize,
                    'Content-Type': 'video/mp4',
                  }
              
                  res.writeHead(206, head)
                  file.pipe(res)
                } else {
                  const head = {
                    'Content-Length': fileSize,
                    'Content-Type': 'video/mp4',
                  }
                  res.writeHead(200, head)
                  fs.createReadStream(path).pipe(res)
                }

And my template in angular is similar to this:

                            <video height="100%" width="100%" controls (click)="toggleVideo()" #videoPlayer>
                                <source src="http://localhost:4000/andromede/videos" type="video/mp4" />
                                Browser not supported
                            </video>

As you can see, the front request directly the API.

So, my question is : How i can res many videos with fs and my method to send videos to the client ?

Thank You


Solution

  • I will answer my own question. I managed to solve the problem.

    First of all, I create a query that retrieves the name of the video.

    Then another query that takes the file name as a parameter.

    Here is my html :

    src="http://localhost:4000/andromede/videos/getVideo?videoName={{files}}"
    

    Here is my 2nd controller for my 2nd request:

                const folder = req.query.folder
                const videoName = req.query.videoName
    
                const range = req.headers.range;
                if (!range){
                    res.status(400).send("Requires Range header");
                }
                const videoPath = "./videos/" + folder + "/" + videoName;
                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);
                const videoStream = fs.createReadStream(videoPath, { start, end });
                videoStream.pipe(res);