节点(套接字)实时音频流/广播

Posted

技术标签:

【中文标题】节点(套接字)实时音频流/广播【英文标题】:node (socket) live audio stream / broadcast 【发布时间】:2014-06-17 06:35:40 【问题描述】:

请问,是否有任何简单的方法可以通过 NODE.js 和可能的 SOCKET.IO 将媒体文件(ogg、mp3、spx..)从服务器流式传输(广播)到客户端(浏览器)?

我必须在服务器端录制音频输入,然后才能为许多客户端实时播放。 我一直在搞乱 binary.js 或 socket.io 流,但无法正确处理。

我尝试使用 speex、vorbis 或 lame 对音频输入进行编码,然后通过 FS 将其加载到客户端,但我没有成功。还是我必须捕获 PCM 然后在浏览器中解码?

对此的任何建议,我都没有找到任何帮助过我的建议。

非常感谢您提供的任何提示、链接和想法。

【问题讨论】:

我对实时音频流也很感兴趣。我读的越多,节点流、背压、缓冲和所有你需要照顾的东西,我就越不知道如何解决这个问题。有一个nice post。我试图避免使用 SHOUTcast/Icecast,但也许这是最简单的方法。 topic on MDN 对我来说真正重要的是尽可能地消除延迟。我不在乎质量。到目前为止,我尝试过的所有主要浏览器中的音频/视频 html5 元素本身都会延迟。所以audiocontext和usermedia可能是这样的。但对我来说仍然没有成功。 【参考方案1】:

您需要寻找适用于 Streams 的包,然后根据需要将流通过管道传输到输出。使用 Express 或仅使用内置 HTTP,您可以轻松完成此操作。这是一个围绕 osx-audio 构建的示例,它提供 PCM 流,lame 可以将流编码为 mp3,以及 Express:

var Webcast = function(options) 

  var lame = require('lame');
  var audio = require('osx-audio');
  var fs = require('fs');

  // create the Encoder instance
  var encoder = new lame.Encoder(
    // input
    channels: 2,        // 2 channels (left and right)
    bitDepth: 16,       // 16-bit samples
    sampleRate: 44100,  // 44,100 Hz sample rate

    // output
    bitRate: options.bitrate,
    outSampleRate: options.samplerate,
    mode: (options.mono ? lame.MONO : lame.STEREO) // STEREO (default), JOINTSTEREO, DUALCHANNEL or MONO
  );

  var input = new audio.Input();
  input.pipe(encoder);

  // set up an express app
  var express = require('express')
  var app = express()

  app.get('/stream.mp3', function (req, res) 
    res.set(
      'Content-Type': 'audio/mpeg3',
      'Transfer-Encoding': 'chunked'
    );
    encoder.pipe(res);
  );

  var server = app.listen(options.port);


module.exports = Webcast;

如何获取输入流可能是最有趣的部分,但这取决于您的实现。流行的 request 包也是围绕 Streams 构建的,所以它可能只是一个 HTTP 请求!

【讨论】:

你有和 socket.io 的例子吗?你在 http: app.get('/stream.mp3', function (req, res) res.set( ' Content-Type': 'audio/mpeg3', 'Transfer-Encoding': 'chunked' ); encoder.pipe(res); );和 socket.io ?像这样的东西? socket.on('audio',function(data) encoder.pipie(data); //发送或发送到客户端在哪里?); 还没有尝试过这个解决方案,但看起来很有趣。我会让你知道这是怎么回事。 谁能指出一些可以在 Flask/Flask-SocketIO 中实现这一目标的资源?【参考方案2】:

在网络浏览器上,您有the HTML5 video element and the audio element。两者都有来源。 Each web browser supports different codecs natively. 因此,如果您尝试流式传输 mp3,请注意这一点。

你不需要socket.io,你只需要HTTP。您的应用程序正在读取一个文件 music.ogg,并且对于它读取的每个块,它将通过 http 服务器发送它。在文件传输之前,它将是一个保持打开状态的 HTTP 请求。

这是您的 html 的外观:

<audio src="http://example.com/music.ogg"></audio>

你的 nodejs 代码将是这样的(还没有测试过):

var http = require('http');
var fs = require('fs');

http.on('request', function(request, response) 
    var inputStream = fs.open('/path/to/music_file.ogg');
    inputStream.pipe(response);
)

我只在inputStream 上使用ReadableStream.pipe 方法以及上述代码的http 和fs 模块。如果您想对音频文件进行转码(例如,从 mp3 转码为 ogg),您需要找到一个模块来执行此操作,然后将文件中的数据通过管道传输到转码器,然后传输到 response

// using some magical transcoder
inputStream.pipe(transcoder).pipe(response);

该方法将在完成写入时在流上调用end,以便在文件完成读取(和转码)后立即完成 HTTP 请求。

【讨论】:

非常感谢您的回答,但我真正的意思是让“实时流”同步到所有客户端,所以您认为有什么方法可以例如将音频源切到零件(或使用记录的 pcms 作为来源)并将这些零件提供给客户?毕竟,WebRTC 方式取得了非常好的结果,但对于连接的更多客户端来说是不可持续的。 您需要使用createReadStream 而不是open 来管道。【参考方案3】:

您可以使用节点和 RTC 做到这一点。有一些工具可供使用,例如SimpleWebRTC 或EasyRTC。对于我已经测试过的内容,视频仍然很麻烦,但音频效果很好。

【讨论】:

以上是关于节点(套接字)实时音频流/广播的主要内容,如果未能解决你的问题,请参考以下文章

实时音频流套接字卡在浏览器中

收听实时音频流

通过 TCP 套接字将音频写入服务器

WebRTC 实时音频流/广播 [关闭]

如何创建实时音频流队列?

Qt 通过 TCP 套接字实时流式传输音频