Stream Videos with Low Server Resource and Gzip compression using NodeJS ~ Hybrid Mobile Apps Development, React Native, Flutter, JavaScript, Darts, iOS, Android, NodeJS
Coding Savvy FB Twitter Google
» »

Stream Videos with Low Server Resource and Gzip compression using NodeJS

Video streaming is more popular than it was a decade ago, More videos are played on Youtube, Netflix, and other online video streaming media. Netflix is the best example who leveraged the benefit of Node.js by implementing it for production and they achieved the tremendous result economically and in performance. Delivering almost 7 billion hours of videos to nearly 50 million customers in 60 countries per quarter. This tutorial will highlight how to efficiently stream video from a NodeJS server with less server resource and a compressed output to make it easier for browsers to download the content.
Stream Videos with Low Server Resource and Gzip compression using NodeJS
This tutorial assumes you have the basic knowledge on how to use NodeJS. If you are new to NodeJS, this article is a good way to start learning. We are going to harness the power of inbuilt NodeJS files-system library that is written in C++ to make content manipulation seamless, fast and easy. In Node fs module, all methods have asynchronous and synchronous forms; I/O tasks can take time and it might fail due to various reasons.
It's recommended to use the asynchronous methods, The asynchronous form always takes a completion callback as its last argument. The module can perform many I/O functions like rename, delete, move, create, watch, read, write and many more on files or folder.
In this example usage, we are using the ExpressJS framework as our server-side handle. ExpressJS gives the request and the response object as a parameter for each route (req, res). Using response object to feed the client with the stream data, we can use the Node fs module. Another useful library that we are going to be using is the Node zlib module. Zlib provides compression functionality implemented using Gzip and Deflate/Inflate. It makes it possible for the fs module to feed the response stream with a compressed content. It is recommended to first check if the client environment supports compression before serving it with a compressed content. Compression-support checks can be done with the request object header. Every client that accept compressed data will send an 'accept-encoding' header.
Handling video streaming on a server is different from how a regular request is handled; video streaming needs to be on demand to save both client and server resource and avoid blocking other useful processes.
NodeJS non-blocking I/O paradigm and JavaScript makes a good streaming service. Companies like Netflix, LinkedIn and Paypal use NodeJS in production for some aspect of their services to enable a seamless experience for users.
Why Netflix Implemented the Node.js by Yunong Xiao, Principle Engineer, Netflix.
The example in this tutorial demonstrate a simple and straightforward way of streaming video content from the server. In a large user-base environment, a lot of refactoring and more coding will need to be done to make sure it scales perfectly for the use case. Below code sample shows how to handle video streaming from an ExpressJS route.
router.get('/stream', function (req, res) {
    const videoURI = path.join(__dirname, "videos", "myvideo.mp4");
    var acceptEncoding = req.headers['accept-encoding'];
    const stat = fs.statSync(videoURI);
    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
      const chunkSize = (end-start)+1
      const stream = fs.createReadStream(path, {start, end})

       const head = {
        'Content-Range': `bytes ${start}-${end}/${fileSize}`,
        'Accept-Ranges': 'bytes',
        'Content-Length': chunkSize,
        'Content-Type': 'video/mp4',
      }
      if (/\bdeflate\b/.test(acceptEncoding)) {
        head['Content-Encoding']= 'deflate';
    }  else if (/\bgzip\b/.test(acceptEncoding)) {
   head['Content-Encoding']= 'gzip';
    }
      res.writeHead(206, head);

      if (/\bdeflate\b/.test(acceptEncoding)) {
        stream.pipe(zlib.createDeflate()).pipe(res);
     } else if (/\bgzip\b/.test(acceptEncoding)) {
       stream.pipe(zlib.createGzip()).pipe(res);
       } else {
           stream.pipe(res);
       }

    } else {

      const head = {
        'Content-Length': fileSize,
        'Content-Type': 'video/mp4',
      }
      if (/\bdeflate\b/.test(acceptEncoding)) {
        head['Content-Encoding']= 'deflate';
    }  else if (/\bgzip\b/.test(acceptEncoding)) {
   head['Content-Encoding']= 'gzip';
    }
      res.writeHead(200, head)
      var stream = fs.createReadStream(path);

      if (/\bdeflate\b/.test(acceptEncoding)) {
        stream.pipe(zlib.createDeflate()).pipe(res);
     } else if (/\bgzip\b/.test(acceptEncoding)) {
       stream.pipe(zlib.createGzip()).pipe(res);
       } else {
           stream.pipe(res);
       }
    }
});
The code snippet above simply checks if the browser supports compression as we recommended and stream the content of myvideo.mp4 to the client side. Required modules for this code includes fs, path, zlib and express.
Was this article helpful?
Thanks! Your feedback helps us improve tutorials.

You May Also Like...

No comments:

Post a Comment