通过fs模块在nodejs中进行视频流传输

时间:2020-01-15 12:43:27

标签: javascript node.js

我想通过fs模块在node.js中流式传输视频,并且尝试了以下代码。

app.get('/video', function(req, res) {
  const path = 'assets/sample.mp4'
  const stat = fs.statSync(path)
  const fileSize = stat.size
  const range = req.headers.range
  if (range) {
    const parts = range.replace(/bytes=/, "").split("-")
    const start = parseInt(parts[0],10);
    const end = parts[1] ? parseInt(parts[1],10) : fileSize-1
    const chunksize = (end-start)+1
    const file = fs.createReadStream(path, {start, end})
    const head = {
      'Content-Range': `bytes ${start}-${end}/${fileSize}`,
      'Accept-Ranges': 'bytes',
      'Content-Length': chunksize,
      'Content-Type': 'video/mp4',
    }
    res.writeHead(206, head)
    file.pipe(res)
  } else {
       const head = {
         'Content-Length': fileSize,
         'Content-Type': 'video/mp4',
       }
       res.writeHead(200, head)
       fs.createReadStream(path).pipe(res)
  }
})

我的视频“ sample.mp4”大小为:1055736字节,为1 MB。但是当我运行代码时,我发现在启动start变量为0时,end变量为1055735&chunksize为1055736。如果您查看 Content-Range 标头,它等于开始时的以下值。

内容范围:'字节0-1055735 / 1055736'

我想逐个流式传输我的视频,而不是等待整个视频加载。但是我认为上面的代码不会做到这一点。

任何人都可以告诉我,此代码对视频流是否正确?

谢谢!

1 个答案:

答案 0 :(得分:0)

您的代码没问题,除了以下几点:通常,浏览器会在视频请求中向您发送Range: bytes=0-。在此标头中输入您的代码

const start = parseInt(parts[0],10);
const end = parts[1] ? parseInt(parts[1],10) : fileSize-1

为您提供start === 0end === fileSize-1以及chunksize的文件大小。因为parts[1]总是虚假的。因此,决定是发送文件的是一个很大的块,而不是浏览器。浏览器已准备好接收206 Partial Content,但是您没有发送它。试试

const preferred_chunksize = 100000
let end = parts[1] ? parseInt(parts[1],10) : start + preferred_chunksize
if( end > fileSize-1 ) end = fileSize-1
const chunksize = end-start+1

preferred_chunksize的范围可以是1到fileSize,具体取决于您的网络状况。我尝试了preferred_chunksize = 1000-很慢。我没有尝试preferred_chunksize = 1-因为它会极其缓慢,并且会导致数百万个请求。 preferred_chunksize介于10万和10000万之间是可以接受的。

但是,实际上,如果您在大文件上尝试使用代码,则不会发现过多的内存使用情况,并且浏览器将立即开始播放视频文件,而无需等待

要加载整个视频

即使您一起跳过end部分(在您的代码版本中已经完成),也可以使用以下方法简化代码:

const end = fileSize-1
const chunksize = end-start+1

会的。
而且,正如我从问题的原始版本中所知道的那样,您正在编写教程,因此出于您的目的,就可以了。

PS。当然,在生产代码中,您最好检查Range标头是否格式错误

相关问题