将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签

Posted

技术标签:

【中文标题】将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签【英文标题】:Streaming audio from a Node.js server to HTML5 <audio> tag 【发布时间】:2011-04-26 16:30:33 【问题描述】:

我一直在用 Node.js 中的二进制流进行试验,令我惊讶的是,实际上有一个使用 node-radio-stream 获取 Shoutcast 流并使用分块编码将其推送到 html5 元素中的工作演示。但它只适用于 Safari!

这是我的服务器代码:

var radio = require("radio-stream");
var http = require('http');
var url = "http://67.205.85.183:7714";
var stream = radio.createReadStream(url);

var clients = [];

stream.on("connect", function() 
  console.error("Radio Stream connected!");
  console.error(stream.headers);
);


// When a chunk of data is received on the stream, push it to all connected clients
stream.on("data", function (chunk) 
    if (clients.length > 0)
        for (client in clients)
            clients[client].write(chunk);
        ;
    
);

// When a 'metadata' event happens, usually a new song is starting.
stream.on("metadata", function(title) 
  console.error(title);
);

// Listen on a web port and respond with a chunked response header. 
var server = http.createServer(function(req, res) 
    res.writeHead(200,
        "Content-Type": "audio/mpeg",
        'Transfer-Encoding': 'chunked'
    );
    // Add the response to the clients array to receive streaming
    clients.push(res);
    console.log('Client connected; streaming'); 
);
server.listen("8000", "127.0.0.1");

console.log('Server running at http://127.0.0.1:8000'); 

我的客户端代码很简单:

<audio controls src="http://localhost:8000/"></audio>

这在 Mac 上的 Safari 5 中运行良好,但在 Chrome 或 Firefox 中似乎没有任何作用。有任何想法吗?

可能的候选者,包括编码问题,或者只是部分实现的 HTML5 功能...

【问题讨论】:

你有没有启动并运行过这个? 是的,请查看下面 Nate 的答案以获取更多信息。 我不确定这是否是一个愚蠢的问题,但客户阵列在哪里发挥作用?我正在尝试复制这一点,但似乎很挣扎。 【参考方案1】:

Here's a (slightly outdated) summary of the current status of HTML5 Audio and Icecast streams.

如您所见,MP3 源似乎只能在 Safari(可能还有 IE9)中工作。您可能需要尝试一些服务器端转码(使用 ffmpegmencoder)到 OGG Vorbis。我很确定在发送 Vorbis 数据时能够让 Chrome 正常运行。

尽管如此,Firefox 仍然是个小子,也许它不喜欢分块编码(所有 SHOUTcast 服务器都以 HTTP/1.0 版本响应响应,尚未定义 Transfer-Encoding: chunked)。尝试使用 OGG 流发送 Transfer-Encoding: identity 响应标头以禁用 chunked,Firefox 可能会工作。我还没有测试过。

告诉我进展如何!干杯!

【讨论】:

谢谢!我现在正在检查 FFMpeg 来试一试。 昨晚我搞砸了这个,实际上能够让 Chrome 播放转码的 OGG Vorbis 数据! ffmpeg 似乎无法从 MP3 流中制作正确的 OGG 文件,但 Chrome 仍然能够播放它。我也在尝试手动调用lameoggenc,结果看起来很有希望(一个很好的兼容OGG 文件)。我怀疑 Firefox 也可以使用这种流。我会尽快在node-radio-stream repo 中创建一个更新的示例! 对于将来偶然发现这些帖子的任何人,我的 node-radio-stream 模块已重命名为 node-icecast-stack: github.com/TooTallNate/node-icecast-stack 再一次,现在node-icecast-stack 已更名为node-icecast:github.com/TooTallNate/node-icecast @TooTallNate 现在只是node-icy,嗯?【参考方案2】:

有一些仅适用于 H5 音频的解决方案直播

HLS 或 LLHLS:最佳兼容性,适用于 Safari、androidios。现在有了MSE,Chrome 也可以通过hls.js 播放 HLS。请注意,纯音频流的延迟约为 10 秒或更长。 HTTP-MP3:也是被广泛支持的解决方案,但是由于mp3编解码器使用越来越少,现在aac和opus在H5中很流行。因此,建议使用 HTTP-MP3。 HTTP-AAC:H5浏览器支持,CDN一般不支持,所以自己搭建服务器也可以,如果需要CDN不可以。 HTTP-FLV 或 HTTP-TS:使用 flv.js 或 mpegts.js by MSE。延迟比 HLS 低,并且可以使用 AAC 编解码器,因此也是一个很好的解决方案。 WebRTC:是的,也可以通过 WebRTC 播放纯音频流。

注意:Opus 也可通过 HTTP-OGG 获得,但 ogg 并非所有浏览器都支持,CDN 也不支持,因此推荐。

让我们看看你的流源,但是你没有提到它:

如果使用 H5 发布流,现在只有 WebRTC 可用。 如果使用 IP 摄像头,则必须先拉取 RTSP 流,然后通过 FFmpeg 转换为 RTMP。 如果使用 OBS,RTMP 或 SRT 都可以。

所以最好的解决方案可能是使用服务器(SRS)为播放器转换您的流:

publisher(WebRTC, OBS, FFmpeg) 
    --RTMP/WebRTC--> Server(SRS) 
        --HLS/HTTP-FLV/WebRTC--> player(H5 audio)

【讨论】:

"但是没有像 HTTP-AAC 或 HTTP-OPUS 这样的流" 这是错误的。 AAC 很好地封装在 ADTS 中,所有常见的浏览器都支持它十年左右。而且,Opus 与 Ogg 或 WebM 配合得很好。 @Brad 感谢您的更正。浏览器、HLS、HTTP-FLV、HTTP-TS和HTTP-AAC都支持AAC/ADTS。 Ogg 或 WebM 并非所有 H5 播放器都支持,所以我认为这可能不是一个好的解决方案。 @Brad 对于 HTTP-AAC,我认为 H5 支持,但一般 AAC/ADTS 是通过 HLS/HTTP-FLV/HTTP-TS 流来承载的,特别是使用 CDN 来传递。所以我认为 HTTP-AAC 不是一个好的解决方案。 成千上万的互联网广播电台通过 HTTP 使用 ADTS 流式传输 AAC,您可能会不同意。我向你保证,它工作正常。 :-) 然后,使用 HLS 等分段方法没有开销。没有不必要的额外延迟。唯一的好处是您可以使用基于文件/blob 的 CDN。而现在,我们使用“低延迟”HLS 绕了一圈,无论如何我们只是将数据包直接推送到客户端。但是,最后一点是另一天的咆哮...... @Brad 谢谢 ^_^ 你能告诉我一个使用 HTTP-AAC 的网站吗?只是为了确认如何使用基于文件/块的 CDN 来交付它,用于直播。

以上是关于将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签的主要内容,如果未能解决你的问题,请参考以下文章

使用 discord bot 可以将音频从我的 DAW 流式传输到 Discord 吗?

将 mp3 从服务器流式传输到 html5 音频时传递持续时间

Node.js如何流式传输音频文件

如何使用 Node.js 通过 ffmpeg 流式传输 MP4 文件?

如何流式传输 blob

使用 node js 实时流式传输 MP3 文件