Streaming audio from a Node.js server to HTML5 <audio> tag

40,549

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!

Share:
40,549
Scott Wilson
Author by

Scott Wilson

Updated on July 09, 2022

Comments

  • Scott Wilson
    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...