将音频从nodejs流式传输到html5音频标签

时间:2016-07-02 03:11:31

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

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

非常感谢任何帮助。

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");
    });

  });
});

1 个答案:

答案 0 :(得分:1)

这里有相当多的代码,并且有相当多的缺失信息......但是还有一些值得指出的事情可能是你特定问题的根源。 / p>

你提到客户无法上场。他们是否以正确的方式使用您的流?他们是否获得了正确的标题和数据?如果没有,请先修复它。

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

您没有指出您正在使用哪个油门模块。 TooTallNate是偶然的吗?如果是这样,我过去在使用该模块时遇到了麻烦。它最近没有更新过,可能与现代Node.js&#34; streams3&#34;不太匹配。

在任何情况下,您进行限制的方式都不合适。虽然你的平均比特率可能是128k,但它不一定是128k。你不应该承担比特率。您可以编写自己的代码来读取MP3帧标题并进行相应的同步,但为什么在其他地方已经完成时会这样做呢?我会将FFmpeg作为子进程启动,让它实时运行。未经测试,但是这样的事情:

return

除了基于实际媒体的限制之外,这还有一个好处是可以删除所有随机ID3标签以及iTunes之类的软件喜欢嵌入MP3中的其他随机垃圾,为您提供一个非常干净的流,只需很少的开销。

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

许多浏览器(如Chrome)会发出范围请求,尝试像对待任何其他MP3文件一样处理您的流。如果你只是忽略那些像你一样的范围请求,那么一切都会好起来的。您可以考虑根据您正在做的事情的具体情况来处理它们。

在一天结束时,你可以使用它,但是涉及很多,并且进行了很多小的调整以使流适用于所有的听众。可能我建议离开流服务已经完成的事情,比如Icecast?您仍然可以在Node.js中获取流,从而允许您在流的源周围绑定您想要的任何应用程序逻辑。一点自我推销......我有一些Node.js代码,我可以授权你连接到Icecast。我还有一个CDN,您可以直接从Node.js应用程序流式传输。您可以在https://audiopump.co查看,或发送电子邮件至brad@audiopump.co。即使您决定自己完成所有操作,也请考虑从Node.js应用程序中获取流并从其他地方提供服务。