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

14

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

我必须在服务器端记录音频输入,然后能够实时为许多客户端播放它。

我已经试过使用binary.js或socket.io流进行编码,但没有成功。

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

对此有什么建议,我没有找到任何有用的信息。

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


我也对实时音频流很感兴趣。但是,我越读有关它的内容,包括节点流、反压、缓冲和所有需要注意的事项,就越不知道如何解决它。这里有一篇不错的文章。我试图避免使用SHOUTcast/Icecast,但也许那是最简单的方法。 - maxdec
对我来说真正重要的是尽可能消除延迟。我不在乎质量。所有主要浏览器中,音频/视频HTML5元素本身都存在延迟问题,无论我尝试了什么。因此,AudioContext和UserMedia可能是解决方案。但对我来说仍然没有成功。 - ango
3个回答

16

您需要寻找适用于流的软件包,然后只需将您的流管道输出即可。使用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软件包也是围绕流构建的,因此它可能只是一个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); //发送给客户端的emit或send在哪里? }); - cmarrero01
还没有尝试过这个解决方案,但看起来很有趣。我会告诉你这个进展如何的。 - AllJs
有没有人能够指导我在Flask/Flask-SocketIO中实现这个的一些资源? - Josh Katofsky

5
在Web浏览器上,您有HTML5视频元素和音频元素。它们都有来源。每个Web浏览器本地支持不同的编解码器。因此,如果您正在尝试流式传输mp3,则需要注意。
您不需要socket.io,只需要HTTP。您的应用程序正在读取一个文件music.ogg,对于它读取的每个块,它将通过http服务器发送它。这将是一个保持打开状态直到文件传输完成的单个HTTP请求。
以下是您的HTML外观:
<audio src="http://example.com/music.ogg"></audio>

您的Node.js代码将类似于以下内容(尚未测试):
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);
})

我只在上述代码中使用了ReadableStream.pipe方法、inputStream和http、fs模块。如果你想转码音频文件(例如,从mp3到ogg),你需要找到一个能够做到这一点的模块,并将数据从文件传输到转码器,然后再传输到response
// using some magical transcoder
inputStream.pipe(transcoder).pipe(response);

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

5
非常感谢您的回答,但我真正想表达的是要将某些内容作为“实时流”同步到所有客户端,那么您认为有什么方式可以将音频源分成几部分(或使用已记录的 PCM 作为源),并向客户端提供这些部分?毕竟,WebRTC 的方式取得了非常好的效果,但对于连接更多客户端来说并不可持续。 - ango
2
你需要使用createReadStream而不是open来进行管道传输。 - wieczorek1990

1

您可以使用Node和RTC来实现此操作。已经有一些可用的工具,如SimpleWebRTCEasyRTC。根据我所测试的情况,视频仍然存在问题,但音频效果很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接