In just a few years, technology has advanced to the point where streaming video and audio has become increasingly common. Services like Netflix, Spotify, and Hulu, for example, provided live movies, television, and music. On-demand movies and audio are now feasible thanks to the availability to stream media.
Streaming service providers aim to ensure that their service is as quick and dependable as possible, which necessitates the development of specific systems to handle the traffic. For that to be possible we need a robust server to stream media, and for that, we use Express which is a lightweight HTTP server based on Node.js run time.
In this article, we are going to learn to stream media through nodejs by creating a simple Express-based API endpoint, that streams mp3 and video files back to the client.
Getting started
Create a new node project
$ md stream-media && cd stream-media
$ npm init -y
$ npm i express
$ code .
Now, that we have created the project, and installed Express, now comes the actual coding part.
Code to stream media
First, create a index.js
file.
## Creating main application file and also an html file
$ touch index.js
$ touch index.html
Now, before getting started with the code, add an mp4 file in the same directory of the node project.
index.js
//* index.js
const express = require("express");
const app = express();
const fs = require("fs");
const PORT = process.env.PORT || 3000;
app.get("/video", (req, res) => {
const range = req.headers.range || "0";
const videoPath = "./video.mp4";
const videoSize = fs.statSync(videoPath).size;
const chunkSize = 1 * 1e6; // 1MB
const start = Number(range.replace(/\D/g, ""));
const end = Math.min(start + chunkSize, 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",in Node.Js
};
res.writeHead(206, headers);
const stream = fs.createReadStream(videoPath, { start, end });
stream.pipe(res);
});
app.listen(PORT, console.log("Started on port 3000"));
In the above code, the range
is provided by the client it is the point where the video is playing at. The fs.statSync()
gives us the statistics of the file, like file size, creation time, etc. The chunkSize
given above is 1MB. We will send 1MB of data from the given range. Meaning for each response back to the client we send back 1MB of data. start
and end
are the beginning and end of the chunk of data. contentLength
is the size of the data that is being sent back to the client.
The header contains information about Content-Range that gives the start point end point and size of the file to the user. Accept-Ranges
tells the client what kind of data type the provided response is. Content-Length
tells the length of content provided. Content-Type
tells the type of file that is being sent, it may be text, audio, video, application, multipart, VND, etc. The status code is 206
because we are sending back partial content to the user by telling the client not to close the connection, as the data is still being sent.
Now the actual part that helps us stream media is stream
, which is created from fs.createReadStream()
, It takes in the videoPath
, start
and end
. Which lets it pull the actual part of the content. So, it gets the data from the defined start point to the endpoint. The stream.pipe()
sends data back to the client in the form of a stream of data.
index.html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<video src="http://localhost:3000/video" controls></video>
</body>
</html>
The above page is to stream media back to the client. It takes the stream of data from the backend and wraps it in a video
tag. making it possible for it to show the media back to the client. Now let’s see it in action.
We can see from the example that the data is sent back to the client in chunks, that’s the reason why there are multiple video
in the network tab. The served video files are still network heavy, for reducing the strain on the network you can compress the files before sending them to the client this is done through npm package called compression.
Conclusion
In the above example, we learned how to stream media through nodejs. Also, we implemented it.