How to Code a Video Streaming Server using NodeJS
Tags: node, javascript, tutorial
Published: 2020-10-25 01:52:05

---
title: How to Code a Video Streaming Server using NodeJS
published: true
description: Give a stream to the browser and it handles the rest. I show you the first part.
tags: node, javascript, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/4isl5q4fxl1la31yf7ta.png
---

Do you want to stream video in your app without needing users to download the entire video? Here's how to do exactly that using NodeJS.

## Final Result
Here's the end result of what we're gonna make.
![Video player with buffering timeline](https://dev-to-uploads.s3.amazonaws.com/i/u40kym1av7643egw2bgv.png)

Notice that light grey bar on the video timeline? That's the HTML5 Video Element buffering the video from our NodeJS server!

If you want to git clone the code and play with it yourself, here's the link to my GitHub Repo! https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream

## Part 1: Setup npm project
You'll need to install NodeJS and run:
```
mkdir http-video-stream
cd http-video-stream
npm init
npm install --save express nodemon
```

## Part 2: index.html
We need to create a HTML5 Video element, and set the source as `"/video"`, which is where server's endpoint is.
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>HTTP Video Stream</title>
  </head>
  <body>
    <video id="videoPlayer" width="650" controls muted="muted" autoplay>
      <source src="/video" type="video/mp4" />
    </video>
  </body>
</html>

```
## Part 3: index.js
Now lets setup our node server so that on `"/"` endpoint it serves our index.html page.
```javascript
const express = require("express");
const app = express();

app.get("/", function (req, res) {
  res.sendFile(__dirname + "/index.html");
});

app.listen(8000, function () {
  console.log("Listening on port 8000!");
});

```
## Part 4: package.json -- Run our server
Add a `start` script to your `package.json` so that we can run our server using `npm start` command.
There's more in your `package.json` file but I just want you to copy this start script. It uses `nodemon` to run `index.js` and restarts the server every time you save the `index.js` file so you don't need to restart the server yourself!
```
{
  "scripts": {
    "start": "nodemon index.js"
  }
}
```
Now you should be able to run
```
npm start
```
and see our app running on port 8000. Open your browser and go to `http://localhost:8000` to see if it worked.
## Part 5: index.js (Again)
We're almost there!
For this final stage, you'll need to either find an mp4 video file, or download the one I've provided in my GitHub project link.
https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream
Here's the `"/video"` endpoint for our server.

```javascript
// in the imports above
const fs = require("fs");

app.get("/video", function (req, res) {
  // Ensure there is a range given for the video
  const range = req.headers.range;
  if (!range) {
    res.status(400).send("Requires Range header");
  }

  // get video stats (about 61MB)
  const videoPath = "bigbuck.mp4";
  const videoSize = fs.statSync("bigbuck.mp4").size;

  // Parse Range
  // Example: "bytes=32324-"
  const CHUNK_SIZE = 10 ** 6; // 1MB
  const start = Number(range.replace(/\D/g, ""));
  const end = Math.min(start + CHUNK_SIZE, videoSize - 1);

  // Create headers
  const contentLength = end - start + 1;
  const headers = {
    "Content-Range": `bytes ${start}-${end}/${videoSize}`,
    "Accept-Ranges": "bytes",
    "Content-Length": contentLength,
    "Content-Type": "video/mp4",
  };

  // HTTP Status 206 for Partial Content
  res.writeHead(206, headers);

  // create video read stream for this particular chunk
  const videoStream = fs.createReadStream(videoPath, { start, end });

  // Stream the video chunk to the client
  videoStream.pipe(res);
});
```

The HTML5 video element makes a request to the `/video` endpoint, and the server returns a file stream of the video, along with headers to tell which part of the video we're sending over.

For a chunk size, I've decided 1MB but you could change that to whatever you like! Another great benefit of this is that we don't need to code the stream to continuously deliver the video data, the browser handles that gracefully for us.


For an in-depth line by line playback on how this works, consider watching [my YouTube video on this topic.](https://youtu.be/ZjBLbXUuyWg)

Now, you've got a working video streaming server using NodeJS!

Happy Streaming! ✌