stiller_leser
stiller_leser

Reputation: 1572

Sending blob as Uint8Array to NodeJS and saving it to file

I am trying to send a blob coming from the new MediaRecorder API in Firefox to NodeJS to store it in a file. The blob contains the recording as converted webm-file. I am chunking this blob into a certain size before sending to be able to send it over the bandwidth provided by the webrtc datachannel. This look like this:

var blobToBuffer = function(blob, cb) {
  var reader = new FileReader();
  reader.onload = function() {
    cb(reader.result);
  };
  reader.readAsArrayBuffer(blob);
};

blobToBuffer(blob, function(buffer){
  var sendInterval = setInterval(function(){
    var currentEnd = dataSend + dis._dataChunkSize;
    if(currentEnd > buffer.byteLength){
      currentEnd = buffer.byteLength;
    } 
    var part = Array.apply([], new Uint8Array(buffer.slice(dataSend, currentEnd)));
    dis.dataChannel.send(
      JSON.stringify({
        payload: part
      })
    );
    dataSend = currentEnd;
    if(dataSend + 1 >= buffer.byteLength){
      dis.dataChannel.send(JSON.stringify({action: 'dataEnd'}));
      clearInterval(sendInterval);
    }
  }, 1000);
});

On the nodeJS side I am trying to convert the data back into a webm file like so:

fs.appendFile('my/path/file.webm', new Buffer(new Uint8Array(message.payload)), function(error){
    if(error){
        console.log(error);
    } else {
        console.log('Chunk successfully written');
    }
});

It tells me, that the chunk was written, however the file is empty. I tried the same with a base64 encoded string derived from the blob, which worked, but seemed like a bad idea because of possible data corruption.

What am I missing? Or is there a better way to transfer a blob from JavaScript to NodeJS?

EDIT

The uint8array-constructor does not seem to accept the data coming in as a string:

'0': 39, '1': 209, '2': 79, '3': 0, '4': 230, '5': 133,
'6': 190, '7': 138, '8': 188, '9': 103, '10': 131,

After the new Uint8Array(message.payload) part, the array length is still 0. So how should it be done instead?

EDIT II

After adding .toString() when using JSON.stringify() I managed to receive the UInt8Array as wished. However as the code is shown above now, it only writes [object uint8array] into the file.

EDIT III - Solution

Using the code above works fine.

Upvotes: 4

Views: 6658

Answers (1)

Blindman67
Blindman67

Reputation: 54026

[object uint8array] is what you should get when you use toString on a uint8array. Just convert the buffer to a string and send the string. If you want you could try base64 encoding but I don't think you should need it.

var str = ""; // string version of the part
for{var i = 0; i < part.length; i++){
    str += String.fromCharCode( part[i] );
}
dis.dataChannel.send(
  JSON.stringify({
    payload: str
  })
);

If Nodejs does not like the string as is then use btoa to convert it to base64 encoding. Dont worry you don't get corruption, that is the reason for base64 to stop some transport protocols from misinterpreting a raw binary string.

dis.dataChannel.send(
  JSON.stringify({
    payload: btoa(str)   // encode string as base64;
  })
);

Also ensure that the mime types are correct.

Upvotes: 2

Related Questions