【问题标题】:stream audio from nodejs to html5 audio tag将音频从 nodejs 流式传输到 html5 音频标签
【发布时间】:2016-07-02 03:11:31
【问题描述】:

我在尝试将音频从 nodejs 服务器实时流式传输到多个 html 客户端时遇到多个问题(以后可能还会连接)。我在下面的代码中所做的是在 bufferArray 中加载 2 个 mp3 文件,然后当客户端连接后,我继续从 bufferArray 中出列,然后以 16384 字节/秒 ~ 128kbits/秒的速度将其写入客户端。但我觉得 缓冲区很快被清空。我的方法是否正确。基本上我应该确保所有客户都应该播放歌曲的同一部分。首先,我的客户都无法播放歌曲,这是另一个问题。

任何帮助将不胜感激。

var http = require('http');
var fs = require("fs");
var url = require('url');
var stream = require('stream');
var Throttle = require('throttle');
var bufferArray = [];
var clients = [];
var entry = true;
setInterval(function () {
  if(bufferArray.length > 0 && clients.length > 0){
    entry = false;
    var buffer = bufferArray.shift();
    var bufferStream = new stream.PassThrough();
    var throttledStream = new stream.PassThrough();
    var throttle = new Throttle(16384);
    bufferStream.end(new Buffer(buffer));
    bufferStream.pipe(throttle).pipe(throttledStream);
    throttledStream.on('data',function(data){
      console.log("Going to write to all the clients "+clients.length);
      for(var i = 0; i < clients.length; i++){
          clients[i].write(data);
      }
    });
    throttledStream.on('end',function(){
      console.log("finished the buffer. Still have to write tot "+bufferArray.length+" buffers");
      entry = true;
    });
  }
},1);
function readMp3FilesInBuffer(songName,callback){
    var fd = fs.createReadStream("./songs/"+songName);
    fd.on('data',function(chunk){
      bufferArray.push(chunk);
    });
    fd.on('end',callback);
}

readMp3FilesInBuffer("FeelOfLove.mp3",function(){
  readMp3FilesInBuffer("ILoveAfrica.mp3",function () {
    console.log("successfully read the songs..");
    http.createServer(function (request, response) {
      var parsedUrl = url.parse(request.url,true);
      var requestType = parsedUrl.query.requestType;
      if(requestType == "renderHtml"){
        console.log("got a request to render html");
        response.writeHead(200, {
           'Content-Type': 'text/html'
       });
        var htmlStream = fs.createReadStream("./views/audioStreaming.html");
        htmlStream.pipe(response);
      }
      else if (requestType === "stream") {
        response.writeHead(200,{
            "Content-Type": "audio/mpeg",
            'Transfer-Encoding': 'chunked'
        });
        clients.push(response);
        console.log("got a request to stream. Tot clients available : "+clients.length);
      }
      else{
        response.end();
      }
    }).listen(8081,function () {
      console.log("listening");
    });

  });
});

【问题讨论】:

    标签: javascript node.js html audio audio-streaming


    【解决方案1】:

    这里有很多代码,也有很多缺失的信息......但也有很多值得指出的事情可能是您的特定问题的根源。

    你提到客户端不能玩。他们最终是否以正确的方式使用您的信息流?他们是否获得了正确的标题和数据?如果没有,请先修复它。

    只有大约三分之一的流媒体音频播放器能够正确处理分块编码。如果您在浏览器中(实际上是在网页上),您通常会没事,但除此之外,分块编码是行不通的。您需要强制 Node.js 完全跳过分块编码。

    您没有指明您使用的是哪个油门模块。 TooTallNate 是偶然的吗?如果是这样,我过去在使用该模块时遇到过麻烦。它最近没有更新,可能与现代 Node.js“streams3”不兼容。

    无论如何,您进行节流的方式都不合适。虽然您的平均比特率可能是 128k,但不一定是 128k。你不应该假设比特率。您可以编写自己的代码来读取 MP3 帧标头并进行相应的同步,但是为什么在其他地方已经完成时还要这样做呢?我会将 FFmpeg 作为子进程启动,并让它实时运行。未经测试,但类似这样:

    ffmpeg -re -i yourfile.mp3 -map_metadata -1 -acodec copy -f mp3 -
    

    除了根据实际媒体进行节流之外,这还具有删除所有随机 ID3 标签和其他像 iTunes 等软件喜欢嵌入 MP3 的随机垃圾的好处,从而为您提供干净的流,而且开销很小。

    您将遇到的下一个问题是您的客户端将需要很长时间来缓冲和开始播放。有一个相当大的缓冲区准备好在它们连接后立即刷新它们可以解决这个问题。

    许多浏览器(如 Chrome)会发出范围请求,试图像对待任何其他 MP3 文件一样对待您的流。如果您只是像您所做的那样忽略这些范围请求,那么一切都会正常工作。不过,您可能会考虑处理它们,具体取决于您正在做什么。

    在一天结束时,您可以完成这项工作,但其中涉及很多内容,并且需要进行很多小调整以使流对您的所有听众都有效。我是否可以建议让流服务于已经这样做的东西,比如 Icecast?您仍然可以在 Node.js 中获取流,允许您在流的源周围绑定您想要的任何应用程序逻辑。自我推销……我有一些 Node.js 代码可以授权给你,用于连接到 Icecast。我还有一个 CDN,您可以直接从您的 Node.js 应用程序流式传输到该 CDN。您可以通过https://audiopump.co 查看或发送电子邮件至 brad@audiopump.co。即使您决定自己做这一切,也请考虑从您的 Node.js 应用程序获取流并从其他东西提供服务。

    【讨论】:

    • 嘿tnx 回复。我能够使用 npm 模块 github.com/fluent-ffmpeg/node-fluent-ffmpeg 将输出 mp3 文件的比特率设置为 128kbps,它使用 ffmpeg,正如你所建议的那样。但我的第二个问题是,我正在尝试做一个直播应用程序。作为初步步骤,我只想尝试两个 mp3 文件。我还想确保在不同时间点连接到服务器的两个客户端(通常是浏览器)应该以这样的方式同步,即两个客户端都播放歌曲的相同部分。我将如何处理这种情况。任何输入都会很棒。
    • 带ADTS的MP3和AAC可以任意分割。这意味着您可以同时将数据发送到浏览器,它们将自动同步。这对您来说非常方便,因为您的服务器不必知道或关心流经的数据。只需将其缓冲并按原样发送给客户端。但理想情况下,使用现有服务器并将您的应用程序用作该服务器的源。您可以为流源编写任何您想要的代码,而无需花费大量时间重新发明已经可用的部分。
    猜你喜欢
    • 2019-10-29
    • 2021-04-15
    • 2011-04-18
    • 2011-04-26
    • 2012-06-11
    • 2014-11-10
    • 2016-01-26
    • 1970-01-01
    • 2019-08-09
    相关资源
    最近更新 更多