Skip to content

Instantly share code, notes, and snippets.

@creotiv
Created June 20, 2024 13:09
Show Gist options
  • Save creotiv/b5e2663caedde2dac9e6ee1eacdcc85e to your computer and use it in GitHub Desktop.
Save creotiv/b5e2663caedde2dac9e6ee1eacdcc85e to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Video Stream</title>
</head>
<body>
<video controls>
<source src="/video" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
</html>
const express = require('express');
const fs = require('fs');
const { pipeline } = require('stream');
const path = require('path');
const app = express();
const port = 3000;
const MAX_CHUNK_SIZE = 512*1024; // Maximum chunk size of 512Kb
// ffmpeg -i video.mp4 -vcodec h264 -acodec aac -strict -2 converted_video.mp4
const videoPath = 'converted_video.mp4'; // Update this path to your video file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.get('/video', (req, res) => {
const stat = fs.statSync(videoPath);
const fileSize = stat.size;
const range = req.headers.range;
if (range) {
const parts = range.replace(/bytes=/, "").split("-");
const start = parseInt(parts[0], 10);
let end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
end = Math.min(start + MAX_CHUNK_SIZE - 1, end, fileSize - 1);
const chunkSize = (end - start) + 1;
const file = fs.createReadStream(videoPath, { start, end });
const head = {
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunkSize,
'Content-Type': 'video/mp4',
};
res.writeHead(206, head);
pipeline(file, res, (err) => {
if (err) {
console.log('Pipeline failed.', err);
}
});
} else {
res.status(416).send('Range Not Satisfiable');
}
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment