视频标签仅在移动设备上调用一个字节的数据(Node.js)
video tag makes call for one byte of data only on mobile (Node.js)
>我创建了一个节点服务器,它使用 gridfs 从 Mongo 数据库流式传输 mp4 视频。将视频流式传输到桌面浏览器时我没有问题,但是当我尝试流式传输到任何移动设备时,我只能看到视频播放器,但它无法播放。当我检查我的服务器日志时,我看到桌面版本调用视频的总字节数为 0,但在移动设备上,它只调用字节 0-1 然后停止,没有给出任何错误。
这是两个服务器端函数,在流式传输到 PC 浏览器时效果很好。
function StreamGridFile(req, res, GridFile) {
console.log("Request: " + req);
if (req.headers['range']) {
// Range request, partialle stream the file
console.log('Range Request');
var parts = req.headers['range'].replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : GridFile.length - 1;
var chunksize = (end - start) + 1;
console.log('Range ', start, '-', end);
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + GridFile.length,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': GridFile.contentType
});
// Set filepointer
GridFile.seek(start, function() {
// get GridFile stream
var stream = GridFile.stream();
// write to response
stream.on('data', function(buff) {
// count data to abort streaming if range-end is reached
// perhaps theres a better way?
start += buff.length;
if (start >= end) {
// enough data send, abort
GridFile.close();
res.end();
} else {
res.write(buff);
}
});
stream.on("end", function() {
// Record the end was called
GridFile.close()
db.close(function() {
counter--;
console.log("closed db, counter: " + counter);
});
});
});
} else {
// stream back whole file
console.log('No Range Request');
var stream = GridFile.stream();
stream.pipe(res);
stream.on("end", function() {
// Record the end was called
gridfile.close();
db.close(function() {
counter--;
//console.log("closed db, counter: " + counter);
});
});
}
}
这是第二个
exports.streamVideo = function(req, res, id) {
console.log("entered the stream video function");
if (counter == 0) {
console.log("counter = 0");
db.open(function(err, db) {
console.log("db open for video stream");
counter++;
console.log(counter);
if (!err) {
var gs = GridStore(db, ObjectID(id));
gs.open(function(err, GridFile) {
console.log("gridstore open");
if (err) {
res.writeHead(404, {
'Content-Type': 'text/javascript'
});
res.end("Video not found");
gs.close();
db.close();
return;
}
console.log("no error, entering StreamGridFile function");
StreamGridFile(req, res, GridFile);
});
} else {
res.writeHead(404, {
'Content-Type': 'text/javascript'
});
res.end("database error");
gs.close();
db.close();
}
})
}
}
我很确定错误属于此代码,因为我最初从静态文件流式传输视频,但后来转换为使用 mongo,那是它停止工作的时候。
试一试:
function StreamGridFile (req, res, GridFile) {
console.log("Request: " + req);
if (req.headers['range']) {
// Range request, partialle stream the file
console.log('Range Request');
var parts = req.headers['range'].replace(/bytes=/, "").split("-");
var maxIdx = GridFile.length - 1;
var start = parseInt(parts[0], 10);
var end = parseInt(parts[1], 10);
if (isInvalidRange(start, end, maxIdx)) {
return res.writeHead(416, {
'Accept-Ranges': 'bytes',
'Content-Type': GridFile.contentType,
'Content-Range': 'bytes */' + GridFile.length,
}).end();
}
if (end > maxIdx || end !== end) {
end = maxIdx
}
var bytesToSend = end - start + 1;
res.writeHead(206, {
'Accept-Ranges': 'bytes',
'Content-Type': GridFile.contentType,
'Content-Range': 'bytes ' + start + '-' + end + '/' + GridFile.length,
'Content-Length': bytesToSend
});
// Set filepointer
GridFile.seek(start, function() {
// get GridFile stream
var stream = GridFile.stream(true);
// write to response
stream.on('data', function(buff) {
if (buff.length > bytesToSend) {
buff = buff.slice(0, bytesToSend)
}
res.write(buff);
bytesToSend -= buff.length;
if (bytesToSend <= 0) {
// enough data send, abort
GridFile.close();
db.close(function() {
counter--;
console.log("closed db, counter: " + counter);
});
res.end();
}
});
});
} else {
// stream back whole file
console.log('No Range Request');
res.header('Accept-Range', 'bytes');
res.header('Content-Type', GridFile.contentType);
var stream = GridFile.stream(true);
stream.pipe(res);
stream.on('end', function(){
GridFile.close();
db.close(function() {
counter--;
console.log("closed db, counter: " + counter);
});
});
}
}
function isInvalidRange (start, end, maxIdx) {
return start !== start // NaN
|| start < 0
|| end < start
|| start > maxIdx
}
这显然无法处理多字节范围请求(其中Range
标头看起来像bytes=2048-4095,4096-6143
),但它应该能够处理正常的字节范围请求。
相关文章:
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 视频标签仅在移动设备上调用一个字节的数据(Node.js)
- 如何在 Javascript 中声明一个字节数组
- 创建一个字节数组并获得相同的 Java 和 JavaScript 输出
- 在 .NET 和 JavaScript 中存储一个字符需要多少字节
- Knockoutjs 将一个 observableArray 绑定到字节
- 如何在Javascript中从字节数组中获得一个BigInteger
- 如何在javascript中转换一个对象为字节数组
- 将JSON发送到WebAPI - JSON对象包含一个图像(字节)-得到错误:表达式太长或太复杂而无法编译
- 我怎么能'依恋'一个ASP.. NET字节数组到'文件'在表单上键入输入字段
- 路径必须是一个没有空字节的字符串'当管道流要求时
- JavaScript:一个字节应该是8位
- uint8clampearray替代或使Uint8Array产生一个字节值的固定字符串
- 如何得到一个字节的最后2位
- 用Javascript获取一个字节的值
- 如何读取一个ArrayBuffer与二进制数据在“4字节”单/浮点/IEEE 754编码数据
- 拉斐尔.2.1.0.min.js有一个无效的UTF-8字节序列
- 是否有一个函数来查找当前使用xmlhttprequest从文件加载的字节数
- 将一个字节(数)按除法的小数部分移位
- js如何将0和1的字符串转换为一个字节