简体   繁体   中英

Player for live audio streaming in HTML 5

First of all, I know the <audio> tag, but I would like to write my own live audio player for further experiments.

Basically, I am trying to stream a simple MP3 file from a node.js server to a HTML5 client script that receives the stream using websockets, append the chunks, and finally play the file.

Since I am talking about streaming, I start playing the file before the end of the download process.

My main concern is: I can't hear anything. There is no error, everything seems to work fine, but actually nothing happen.

I supposed the tricky part was about the chunk sizes, but the decodeAudioData function does not seem to use the optional error callback.

The server side script is really simple:

var fs = require('fs');

var WebSocketServer = require('ws').Server;

var wss = new WebSocketServer({port: 9090,host:"192.168.0.253"});
var readStream = fs.createReadStream("test.mp3",
                                     {
                                        'flags': 'r',
                                        'mode': 0666,
                                        'bufferSize': 64 * 1024
                                     }
                                    );

wss.on('connection', function(ws) {
                                    readStream.on('data', function(data)
                                                                {
                                                                    ws.send(data,     {binary: true, mask: false});
                                                                }
                                                );
                                    }
        );

The client side script is:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=620">
<title>Test stream HTML5</title>

<script>
var numberOfChannels = 2;
function decode(node)
{
    try
    {
        audioCtx.decodeAudioData(
                                    node.buf,
                                    function(decoded)
                                    {
                                        for (var i=0; i<numberOfChannels; i++)
                                        {
                                            var channel = node.source.buffer.getChannelData(i);
                                            channel.set(decoded, node.cursor );
                                        }

                                        node.cursor += decoded.length;
                                        if (!node.started)
                                        {
                                            node.source.start();
                                            node.started = true;
                                        }
                                   }
                                );
    }
    catch(e)
    {
        console.log('decode exception',e.message);
    }
}

function onOpen(evt)
{
    console.log("CONNECTED");
}

function onClose(evt)
{
    console.log("DISCONNECTED");
}

function errorHandler(e)
{
  var msg = '';

  switch (e.code) {
    case FileError.QUOTA_EXCEEDED_ERR:
      msg = 'QUOTA_EXCEEDED_ERR';
      break;
    case FileError.NOT_FOUND_ERR:
      msg = 'NOT_FOUND_ERR';
      break;
    case FileError.SECURITY_ERR:
      msg = 'SECURITY_ERR';
      break;
    case FileError.INVALID_MODIFICATION_ERR:
      msg = 'INVALID_MODIFICATION_ERR';
      break;
    case FileError.INVALID_STATE_ERR:
      msg = 'INVALID_STATE_ERR';
      break;
    default:
      msg = 'Unknown Error';
      break;
  };

  console.log('Error: ' + msg);
}

var ws = new WebSocket("ws://192.168.0.253:9090");
ws.onopen = function(evt) {onOpen(evt)};
ws.onclose = function(evt) { onClose(evt) };
ws.onerror = function(evt) { errorHandler(evt) };
ws.binaryType = 'arraybuffer';

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

node={};
node.source  = audioCtx.createBufferSource();
node.source.connect(audioCtx.destination);
node.cursor = 0;
node.started=false;

// 9693654 is the size of the mp3 file: just a magic number used for the prototype :)
node.source.buffer = audioCtx.createBuffer( numberOfChannels, 9693654, 44100);

ws.onmessage = function (evt)
               {
                    node.buf=evt.data;
                    decode(node);
               };


</script>

</html>

By the way, I tried to play the file even at the end of the download part, and it still does not work.

Thanks for your advises!

I don't think you can split mp3 into multiple part and play / decode them partially. Haven't tried it myself and am not an expert on mp3 though.

You basically need to stream audio in PCM (raw audio) or use other mechanism in order to compress data.

Here's an example audio streaming code I've written while back: https://github.com/agektmr/AudioStreamer

I'm not sure if it still works but at least before Web Audio API change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM