Safari 9无法播放带二进制源的HTML5视频?

时间:2016-08-29 09:04:38

标签: node.js html5 mongodb video safari

我目前正在使用具有视频上传和播放器的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中运行正常,因此视频编码没有问题。知道如何让这个工作吗?

1 个答案:

答案 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;
})