Streaming audio from a Node.js server to HTML5 <audio> tag
Here's a (slightly outdated) summary of the current status of HTML5 Audio and Icecast streams.
As you can see, a MP3 source only seems to work in Safari (and possibly IE9). You might need to experiment with some server-side transcoding (with ffmpeg or mencoder) to OGG Vorbis. I'm pretty sure I was able to get Chrome to behave properly when I was sending Vorbis data.
Firefox was still being a brat though, maybe it doesn't like the chunked encoding (all SHOUTcast servers respond with a HTTP/1.0
version response, which hadn't defined Transfer-Encoding: chunked
yet). Try sending a Transfer-Encoding: identity
response header with the OGG stream to disable chunked
, and Firefox MIGHT work. I haven't tested this.
Let me know how it goes! Cheers!
Scott Wilson
Updated on July 09, 2022Comments
-
Scott Wilson almost 2 years
I've been experimenting with binary streams in Node.js, and much to my amazement do actually have a working demo of taking a Shoutcast stream using node-radio-stream and pushing it into a HTML5 element using chunked encoding. But it only works in Safari!
Here is my server code:
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');
My client code is simply:
<audio controls src="http://localhost:8000/"></audio>
This works fine in Safari 5 on the Mac, but doesn't seem to do anything in Chrome or Firefox. Any ideas?
Possible candidates including encoding issues, or just partially-implemented HTML5 features...