如何在nodejs中流式传输一组mp3文件?

s2j5cfk0  于 2023-08-04  发布在  Node.js
关注(0)|答案(1)|浏览(233)

我在一个目录中有几个mp3文件,我想一个接一个地流式传输,这样浏览器就会(a)立即开始播放音频,并继续播放所有的mp3,直到我关闭响应流。(Intent是一个端点,其功能类似于播放列表mp3流。)
下面是我的代码:

import express from 'express';

const app = express();

function startServer() {
  const port = process.env.PORT || 3000;
  app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
  });
}

app.get('/stream', (req, res) => {
  const mp3Files = fs.readdirSync('.').filter(file => file.endsWith('.mp3'));
  let i = 0;

  res.setHeader('Content-Type', 'audio/mpeg');
  res.set('Transfer-Encoding', 'chunked');

  function sendFile() {
    const mp3File = mp3Files[i];
    console.log(`processing ${mp3File}`);
    const fileStream = fs.createReadStream(mp3File);
    fileStream.on('data', (chunk) => {
      res.write(chunk);
    }).on('end', () => {
      i++;
      if (i < mp3Files.length) {
        sendFile();
      } else {
        res.end();
      }
    });
  }
  sendFile();
});

startServer();

字符串
我可以确认所有的mp3文件都已处理,但浏览器只播放第一个文件的音频。需要说明的是,我并没有在客户端做任何事情--我只是将Chrome指向express API端点。
我希望得到相同的结果,如果我看到Chrome指向任何其他(工作)流音频URL,如https://audio1.maxi80.com
有没有想过我做错了什么?

7eumitmz

7eumitmz1#

我让你的代码工作,因为是,它是成功地过渡到下一首歌的整个目录的mp3文件(50 mb的总)。这12个文件都是以同样的方式从CD上撕下来的。但有几件事让我印象深刻。
最重要的。您可能需要一个Content-Length头,它是发送的文件大小的总和。我黑进了这个

const mp3Files = fs.readdirSync('.').filter(file => file.endsWith('.mp3'));
  let i = 0;
  let contentLenght = 0;

  mp3Files.forEach(file => {
    contentLength += fs.statSync(file).size;
  });

  res.setHeader('Content-Type', 'audio/mpeg');
  res.setHeader('Content-Length', contentLength);
  res.set('Transfer-Encoding', 'chunked');

字符串
这使得浏览器的简单音频播放器能够更好地估计总的流时间。进度条在一个合理的位置,而不是只保持在最后。
x1c 0d1x的数据
我注意到的第二件事是,当回调调用res.write时,没有对读取流进行节流。当客户端连接时,50 MB的数据几乎立即被推入写入流。您可以在console.log语句中破解,在每个data回调中打印出chunk.length,以了解我的意思。
我想浏览器很快就把它拉下来了,因为我在本地主机上。但是,如果客户端的缓冲区有限,并且与音乐同步,那么这不会给节点进程带来很大的字节背压吗?考虑将drain事件挂接到响应对象上,并以所需的速度写入响应流。我可能错了,但是如果客户端本身没有做太多的缓冲,缓冲就没有免费的午餐。
最后一件事我不知道你正在处理的文件,但是如果任何ID 3头包含某种长度提示,那可能会让浏览器客户端的播放器感到困惑。因此,上面插入的Content-Length头应该可以解决这个问题。(免责声明:我不认为ID 3头实际上包含长度提示。我可能是错的)。

相关问题