我目前正在使用具有视频上传和播放器的NodeJS开展网络项目。上传的视频将以二进制形式存储在mongodb中,当通过API localhost / api / media /:id:
进行后续处理时/*getting media from db in binary format*/
res.setHeader('Accept-Ranges', 'bytes');
res.setHeader('Content-Range', 'bytes=0-1/' + media.length);
res.setHeader('Content-Type', 'video/mp4');
res.setHeader('Cache-Control', 'public,max-age=0');
res.send(media);
这项工作在Chrome和Firefox上运行良好,使用此API会给我一个带有视频标记的html5页面,如下所示:
<video controls="" autoplay="" name="media">
<source src="localhost/api/media/abcde" type="video/mp4">
</video>
即使在像7这样的旧版Safari上运行也很好。但是在Safari 9上,它特别不起作用,只会向媒体控制器显示文本&#34; loading&#34;并且永远不能播放视频。我尝试将相同的视频文件放在localhost中并通过localhost / test.mp4访问它,这在Safari 9中运行正常,因此视频编码没有问题。知道如何让这个工作吗?
答案 0 :(得分:0)
使用GridFS,您可以使用字节范围支持正确地将文件流式传输到客户端:
var db
var app = require('express')()
var parseRange = require('range-parser')
var mongo = require('mongodb')
var MongoClient = mongo.MongoClient
var GridStore = mongo.GridStore
var ObjectID = mongo.ObjectID
function StreamGridFile(req, res, next, GridFile) {
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Disposition', 'filename="' + req.params.file + '"')
res.setHeader('Content-Type', GridFile.contentType)
var ranges = parseRange(GridFile.length, req.headers.range || '', { combine: true })
if (Array.isArray(ranges) && ranges.length === 1 && ranges.type = 'bytes') {
var type = ranges.type
var start = ranges[0].start
var end = ranges[0].end
var total = end - start + 1
res.statusCode = 206
res.setHeader('Content-Range', 'bytes ' + start + '-' + end + '/' + GridFile.length)
res.setHeader('Content-Length', total)
return GridFile.seek(start, function() {
var finished = false
GridFile.stream(true).on('data', function (buff) {
if (finished) return;
var remaining = total
total -= buff.length
if (total <= 0) {
res.end(buff.slice(0, remaining))
GridFile.close()
finished = true
} else {
res.write(buff)
}
}).on('end', function () {
if (finished) return;
finished = true
res.end()
}).on('error', next)
})
} else if (ranges === -1) {
res.statusCode = 416
res.setHeader('Content-Range', 'bytes */' + GridFile.length)
return res.end()
} else {
res.statusCode = 200
res.setHeader('Content-Length', GridFile.length)
return GridFile.stream(true).pipe(res)
}
}
app.get('/files/get/:file', function (req, res, next) {
new GridStore(db, new ObjectID(req.params.file), null, 'r').open(function(err, GridFile) {
return GridFile ? StreamGridFile(req, res, next, GridFile) : res.send(404, 'Not Found')
})
})
MongoClient.connect("mongodb://localhost/test", function(err, database) {
if (err) throw err;
db = database;
})