Video Streaming Application
A super easy way to stream large video files using NodeJs and ExpressJs and we'll package it as a standalone executable.
Tags
TLDR ๐ฅฑ!!!
Of course thereโs no TLDR, itโs just simple fu*kiโn code you gotta write.
The entire magic lies with packaging it as a standalone executable, and Iโve already written a post on that here .
So, what Iโm saying is ๐คท๐ปโโ๏ธ :-
Why would you need this? ๐คจ
Well, It doesnโt matter if you โฆ no no, not gonna โThe Rockโ you peeps ๐ถ
- It doesnโt just stream large videos files, it can stream/send any file be it large or small ๐.
- On frontend side, all you gotta do is use simple
fetch
api ๐คท๐ปโโ๏ธ, no fancy sh*t required. - I personally pair it with my Tauri apps as a sidecar to stream videos, because support for doing that within Tauri itself is horrendous ๐.
Important Note ๐
Just FYI, dis note might be completely irrelevant in the future, but at the time of writing this post :-
- NodeJs version 21+ has the ability to create single executables, but currently itโs an experimental feature.
- So you kinda have to write your code in CommonJs module system, because thatโs the only thing thatโs supported at the moment. Read more here
Why dis note might be irrelevant in the future? Because they might make it better and support a whole bunch of module systems, who tf knows ๐คท๐ปโโ๏ธ.
Packages Youโll Need ๐ฆ
Check out my package.json
:-
"dependencies": { "cors": "^2.8.5", "express": "^4.19.2" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "rollup": "^4.17.2" }
FAQ
- Why rollup you ask? Read the damm post over here ๐ค.
Code ๐
Basic Folder/File structure is kinda important and will look kinda like this :-
node_modules src/ - index.js routers/ - file.js // all the routers you'll need go here package.json
const express = require("express"); const fs = require("fs"); const path = require("path"); const fileRouter = express.Router(); fileRouter.get("/", (req, res) => { const { filepath = "" } = req.query; if (filepath === "") { return res .status(400) .send( "Please provide a filepath. Example: /file?filepath=folder1/folder2/file.txt. Visit / for more info." ); } const finalFilepath = filepath.split(",").join(path.sep); // check if the file exists fs.stat(finalFilepath, (_, stat) => { if (stat && stat.isFile()) { res.status(200).sendFile(finalFilepath); } else { res.status(404).send(`File not found at ${finalFilepath}`); } }); }); module.exports = fileRouter;
and just one more
const cors = require("cors"); const express = require("express"); const getFileRouter = require("./routers/getFile"); /* More about these 2 ๐๐ป in Bonus section const getFileFromCurrentDirectoryRouter = require("./routers/getFileFromCurrentDirectory"); const getCurrentDirectoryPathRouter = require("./routers/getCurrentDirectoryPath"); */ const app = express(); app.use(cors()); app.use("/file", getFileRouter); /* More about these 2 ๐๐ป in Bonus section app.use("/cwd", getCurrentDirectoryPathRouter); app.use("/file-cwd", getFileFromCurrentDirectoryRouter); */ app.get("/", (_, res) => { const response = { endpointsGET: { getFile: "/file?filepath=folder1/folder2/file.txt", /* More about these 2 ๐๐ป in Bonus section getCurrentDirectoryPath: "/cwd?mode=development(or production)", getFileFromCurrentDirectory: "/file-cwd?mode=development(or production)&filepath=folder1/folder2/file.txt", */ }, message: "Welcome to the file server. Please visit the endpoints to get the desired output. Change the mode to production or development to see the difference in the output.", }; res.status(200).send(response); }); app.listen(11111, () => { console.log("Server is running on http://localhost:11111"); });
To Package It ๐ฆ
Just follow the steps in the NodeJs Single Executable post and youโre good to go ๐.
Hereโs some scripts you can use in your package.json
to make your life easier ๐ฎโ๐จ.
"scripts": { "build": "rollup -c", "start": "node dist/index.js" }
Bonus ๐
So if you noticed these lines in the src/index.js
file up there :-
// More about these 2 ๐๐ป in Bonus section
and wondering what tf is that all bout ๐คจ :-
- If you package your app as a standalone executable, and want to stream files from the current directory where the executable is; Why ๐คจ? :-
- Becasue your app isnโt installable but is actually portable, then consider using these 2 routers ๐๐ป (because I use them in my projects all the time)
const express = require("express"); const path = require("path"); const getCurrentDirectoryPathRouter = express.Router(); getCurrentDirectoryPathRouter.get("/", (req, res) => { const { mode = "development" } = req.query; const currentDirPath = mode === "development" ? path.join(__dirname, "..", "..", "..") : path.join(__dirname); res.send(`Current directory path: ${currentDirPath}. Current mode: ${mode}. Change mode by adding ?mode=production or ?mode=development to the URL.`); }); module.exports = getCurrentDirectoryPathRouter;
and,
const express = require("express"); const fs = require("fs"); const path = require("path"); const getFileFromCurrentDirectoryRouter = express.Router(); getFileFromCurrentDirectoryRouter.get("/", (req, res) => { const { mode = "development", filepath = "" } = req.query; if (filepath === "") { return res .status(400) .send( "Please provide a filepath. Example: /file-from-current-directory?filepath=folder1/folder2/file.txt. Visit / for more info." ); } const filepathCorrected = filepath.split(",").join(path.sep); const finalFilepath = mode === "development" ? path.join(__dirname, "..", "..", "..", filepathCorrected) : path.join(__dirname, filepathCorrected); // check if the file exists fs.stat(finalFilepath, (_, stat) => { if (stat && stat.isFile()) { res.status(200).sendFile(finalFilepath); } else { res .status(404) .send( `File not found at ${finalFilepath}. Current mode: ${mode}. Change mode by adding ?mode=production or ?mode=development to the URL.` ); } }); }); module.exports = getFileFromCurrentDirectoryRouter;
And thatโs it bit*hes ๐. Have fun ๐๐
Thanks ๐ค for reading all the way till down here. Please consider subscribing(click) (tap) and check out some other stuff I wrote below ๐๐ป