fatlog
fatlog

Reputation: 1192

Streaming Binary with Node.js and WebSockets

I've been googling this and looking around stackoverflow for a while but haven't found a solution - hence the post.

I am playing around with Node.js and WebSockets out of curiosity. I am trying to stream some binary data (an mp3) to the client. My code so far is below but is obviously not working as intended.

I suspect that my problem is that I am not actually sending binary data from the server and would like some clarification/help.

Heres my server...

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

var wss = new WebSocketServer({port: 8080,host:"127.0.0.1"});
wss.on('connection', function(ws) {    
    var readStream = 
    fs.createReadStream("test.mp3", 
     {'flags': 'r',
      'encoding': 'binary', 
      'mode': 0666, 
      'bufferSize': 64 * 1024});

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

And my client...

context = new webkitAudioContext();
var ws = new WebSocket("ws://localhost:8080");
ws.binaryType = 'arraybuffer';

ws.onmessage = function (evt) {
    context.decodeAudioData(
    evt.data,
        function(buffer) {
            console.log("Success");
        }, 
        function(error) {
            console.log("Error");
        });
};

The call to decode always end up in the error callback. I am assuming this is because it is receiving bad data.

So my question is how to I correctly stream the file as binary?

Thanks

Upvotes: 11

Views: 13841

Answers (2)

fatlog
fatlog

Reputation: 1192

Problem solved.

I fixed this issue with a combination of removing the "'encoding': 'binary'" parameter from the options passed to "createReadStream()" and the solution at...

decodeAudioData returning a null error

As per some of my comments, when I updated the createReadStream options, the first chunk was playing but all other chunks were executing the onError callback from decodeAudioData(). The solution in the link above fixed this for me. It seems that decodeAudioData() is a bit picky as to how the chunks it receives should be formatted. They should be valid chunks apparently...

Define 'valid mp3 chunk' for decodeAudioData (WebAudio API)

Upvotes: 0

user568109
user568109

Reputation: 48003

What your server is doing is that it is sending messages consisting of binary audio data in 64 KB chunks to your client. Your client should rebuild the audio file before calling decodeAudioData.

You are calling decodeAudioDataevery time your client is getting message on websocket. You have to create a separate buffer to add all the chunks to it. Then on completion of transfer, the buffer should be given input to decodeAudioData.

You have two options now:

  1. You load entire file (fs.read) without using stream events and send the whole file with ws.send (easy to do)
  2. You use stream events, modify your client to accept chunks of data and assemble them before calling decodeAudioData

Upvotes: 4

Related Questions