Reputation: 63
I am working on my streaming project for quite sometime. Everything works great, however I am getting 206 err partial content when streaming is done for large MP4 files. I do understand why is that I researched a ton and it appears to be a bug in NodeJS compression or something. I uploaded the entire project to git-hub.
https://github.com/oyosied/cat-flix-frontend
https://github.com/oyosied/cat-flix-backend
I do see from debugging that for large files , when stream starts in controllers/videoStream.js getVideoStream . Is that the start in the Range header is equal to the end. Which is weird and I can't figure out why. I'll be really glad if anyone is familiar with this issue and how it's possible to fix this, I tried changing ReactPlayers PlyR, VideoJS etc and it doesn't do the trick.
exports.getVideoStream = (req, res, next) => {
const DBConn = getDataBaseConnection("getVideoStream");
DBConn().conn.client.connect(function (error, client) {
if (error) {
res.status(500).json(error);
return;
}
// Check for range headers to find our start time
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}
const db = client.db("CatFlix");
// GridFS Collection
db.collection("VideoFiles.files").findOne(
{ _id: mongoose.Types.ObjectId(req.params.id) },
(err, video) => {
if (!video) {
res.status(404).send("Video is not found");
return;
}
console.log(video);
// Create response headers
const videoSize = video.length;
const start = Number(range.replace(/\D/g, ""));
const end = videoSize - 1;
let 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);
// Get the bucket and download stream from GridFS
const bucket = new mongodb.GridFSBucket(db, {
bucketName: "VideoFiles",
});
const downloadStream = bucket.openDownloadStream(video._id, {
start: start,
end: end,
});
// Finally pipe video to response
console.log(
streamCounter,
" start ",
start,
" end ",
end,
"content-length",
contentLength,
"video size",
videoSize
);
streamCounter++;
downloadStream.pipe(res);
}
);
});
};
Most likely and issue with the streaming function and the range header which passes start with max value and not 0. Example video length is 2:17 seconds start value is 0 and end is 164923. This mp4 is ~6mb. When I try to stream a video of ~45mb start value is 4178967 end value 4178967 right from the begining.
Upvotes: 0
Views: 798
Reputation: 63
I was missing plus one in
const downloadStream = bucket.openDownloadStream(video._id, {
start: start,
end:end +1 // was "end: end,"
});
Apparently this array's end is not -1 and since I subtracted -1 above for the range header it gave a partial content error.
Upvotes: 2