我可以播放 1GB 和 500MB 等大型视频,但对于 60MB 或更小的视频大小,浏览器在收到内容时不会加载它们。
视频 html-
<video src="${url}" style="width:100% !important; height: inherit; background: black;" controls autoplay muted preload="metadata"></video>
我尝试操纵响应内容范围、状态,但没有任何效果。
我的服务器代码用于响应范围请求-
route.get('/video/:id', async (req, res) => {
const { id } = req.params;`your text`
const range = req.headers.range;`your text`
console.log(range);
if (!range || range === undefined) {
res.writeHead(416,{
"Content-Range":`bytes */*`
}).send("Requires Range header");
return;
}
try {
const cursor = await bucket.find({ "_id": id });
let size, type;
await cursor.forEach(document => {
size = document.length;
type = document.metadata.mimeType;
});
let CHUNK_SIZE = 1024 *1024 ; // 1MB
let start = Number(range.replace(/\D/g, ""));
const end = Math.min(start + CHUNK_SIZE, size-1);
if(start>=size || start===end){
res.writeHead(416,{
"Content-Range":`bytes */${size}`
})
return res.end();
}
try {
const downloadStream = await bucket.openDownloadStream(id, {
start: start,
end: end
});
const contentLength = end - start;
const headers = {
"Content-Range": `bytes ${start}-${end}/${size}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
res.writeHead(206, headers);
downloadStream.pipe(res);
} catch (err) {
console.log('Error: ' + err);
res.status(416).send();
}
} catch (err) {
console.log('Error: ' + err);
res.status(416).send();
}
});
问题解决了!!!
当范围请求接近文件末尾或此代码最小条件达到大小 -1 时,就会出现问题
const end = Math.min(start + CHUNK_SIZE, **size-1**);
这里的问题是流大小:
const downloadStream = await bucket.openDownloadStream(id, {
start: start,
**end: end**
});
流永远不会到达终点
因此,如果我们将端点配置为实际端点,就可以解决问题
最终代码 -
route.get('/video/:id', async (req, res) => {
const { id } = req.params;
const range = req.headers.range;
try {
const cursor = await bucket.find({ "_id": id }).toArray();
const document = cursor[0];
const size = document.length;
const type = document.metadata.mimeType;
if (range) {
let CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
var parts = range.replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : Math.min(start + CHUNK_SIZE, size - 1);
if (start >= size) {
res.writeHead(416, {
"Content-Range": `bytes */${size}`
})
return res.end();
}
try {
const downloadStream = await bucket.openDownloadStream(id, {
start: start,
end: end == size - 1 ? size : end
});
const contentLength = end - start + 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${size}`,
"Accept-Ranges": "bytes",
"Content-Length": `${contentLength}`,
"Content-Type": type,
};
res.writeHead(206, headers);
console.info('Satisfied Range: ' + `${start}-${end}/${size}`);
downloadStream.pipe(res);
} catch (err) {
console.log('Error: ' + err);
res.status(416).send();
}
} else {
const downloadStream = await bucket.openDownloadStream(id);
res.setHeader('Cache-Control', 'private, max-age=0, must-revalidate');
res.setHeader('Content-Length', size.toString());
res.setHeader('Content-Type', type);
res.writeHead(200);
res.end(downloadStream);
}
} catch (err) {
console.log('Error: ' + err);
res.status(416).send();
}
});