141

I am working with node.js and I streamed my Audio to my node.js server. Now I noticed during the process of building the audio blob:

var audioBlob = new Blob([dataview], { type: 'audio/wav' });

That I get a ReferenceError at new Blob. It seems that Blob is not supported. How can I create a blob which I would like to save with node.js fs module?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
zer02
  • 3,963
  • 4
  • 31
  • 66
  • 5
    What is Blob? Where does it come from? – Pete Feb 01 '13 at 19:11
  • http://en.wikipedia.org/wiki/Binary_large_object – zer02 Feb 01 '13 at 19:11
  • All common browser support it https://developer.mozilla.org/de/docs/DOM/Blob – zer02 Feb 01 '13 at 19:12
  • 2
    Yeah, but a blob isn't a native Node.js type.. You know, Number, String, Boolean, Object, Array, etc. Why don't you create an object prototype or a module for NPM? Did you check NPM for anything like what you need? – sent1nel Feb 01 '13 at 19:15
  • I found a Blobbuilder module but it is outdated and not working.Thats why I am asking if there is a way to create a Blob inside node.js. I haven´t built a wav file object prototype yet. – zer02 Feb 01 '13 at 19:21
  • Try [`Buffer`](http://nodejs.org/api/buffer.html). `Blob` isn't available because it's defined by a [DOM API](http://www.w3.org/TR/FileAPI/#dfn-Blob) and Node is not a DOM implementation. – Jonathan Lonowski Feb 01 '13 at 20:33
  • 9
    To me it seems that those who downvoted didn´t get that there is apparently no solution to this question, that´s why I am asking. – zer02 Feb 01 '13 at 20:34
  • 1
    @Jonathan I will have a look on this, but is it possible to define the MIME type? – zer02 Feb 01 '13 at 20:35
  • 1
    @zer02 Yes and no. You can always add a `mime` property to the `Buffer` since it's still dynamic. But, MIME types are for communicating binary data; not so much for saving to disk. – Jonathan Lonowski Feb 01 '13 at 20:37
  • 1
    `var bufferL = mergeBuffers(recBuffersL, recLength); var bufferR = mergeBuffers(recBuffersR, recLength); var interleaved = interleave(bufferL, bufferR); var dataview = encodeWAV(interleaved); //var audioBlob = new Blob([dataview], { type: 'audio/wav' });` Here is the example. Your suggestion is to create a buffer and then use `fs.writeFile('test.wav', , function(err){ if (err) console.log(err); });` ? – zer02 Feb 01 '13 at 20:53

5 Answers5

44

The Solution to this problem is to create a function which can convert between Array Buffers and Node Buffers. :)

Convert a binary NodeJS Buffer to JavaScript ArrayBuffer

In recent node versions it's just:

let buffer = Buffer.from(arraybuffer);
let arraybuffer = Uint8Array.from(buffer).buffer;
Community
  • 1
  • 1
zer02
  • 3,963
  • 4
  • 31
  • 66
  • Did you managed to get it working? I can record the audio to a file but I can't listen to it although it has the right time. – Gabriel Apr 25 '14 at 20:37
  • can you help me? did you do something like this on the gist?https://gist.github.com/anonymous/11302966 – Gabriel Apr 25 '14 at 20:54
  • Yes, something like that. I can´t find the source code of my old project. – zer02 Apr 25 '14 at 21:15
  • 20
    Hi, I need the same like you, but I don't understand your solution. I have this var audioBlob = new Blob([dataview], { type: 'audio/mp3' }); but you use "arrayBuffer" variable in your example – oihi08 Feb 01 '18 at 10:38
  • 17
    is `let arraybuffer` in your example equal to `new Blob`? – mesqueeb Feb 09 '20 at 01:40
  • 1
    `ArrayBufferLike` appears to be missing certain properties from `Blob`: ```ts Argument of type 'ArrayBufferLike' is not assignable to parameter of type 'File | Blob'. Type 'ArrayBuffer' is not assignable to type 'File | Blob'. Type 'ArrayBuffer' is missing the following properties from type 'Blob': size, type, arrayBuffer, stream, text ``` – Mateja Petrovic Oct 14 '20 at 18:52
  • 6
    This answer answer stops at creating array buffer. Then what? – AndyUK Jan 06 '21 at 09:00
  • 3
    Isn't better for you to use the same variable names as used in the question so that we know exactly how to convert the code? – Xavier Mukodi Mar 01 '21 at 07:40
  • 6
    This is one of the more confusing answers I've seen on stack overflow. – light24bulbs Oct 19 '21 at 19:55
  • This solution helped me to figure out my problem with electron-react communication. For instance, this example code gets the arrayBuffer and easily converts that to a client File ```new File([remoteFile.arrayBuffer], remoteFile.name)]```. – Muhamad Zolfaghari Dec 21 '22 at 04:56
39

Since Node.js 16, Blob can be imported:

import {Blob} from 'node:buffer';

new Blob([]);
//=> Blob {size: 0, type: ''}

Otherwise, just use cross-blob:

import Blob from 'cross-blob';
 
new Blob([]);
//=> Blob {size: 0, type: ''}
 
// Global patch (to support external modules like is-blob).
globalThis.Blob = Blob;
Richie Bendall
  • 7,738
  • 4
  • 38
  • 58
13
Note: This answer only applies if you want to follow the Richie Bendall's answer.

Short answer:

Avoid importing Blob from 'node:buffer'.

Instead, prefer importing it like this (as explained in the NodeJS docs. (implementation example here)):

import { Blob } from 'buffer';

Long answer:

The Richie Bendall's answer helped me a lot. But it seems that importing Blob from node:buffer breaks the Jest unit tests, throwing this error:

 FAIL  dist/tests/unit/users/getOneById.spec.js
  ● Test suite failed to run

    ENOENT: no such file or directory, open 'node:buffer'

      2 | import config from '../config/config';
      3 | import { getFileExt, getFileName, removeFile } from './file';
    > 4 | import { Blob } from 'node:buffer';
        | ^
      5 |
      6 | class PdfHelpers {
      7 |

      at Runtime.readFile (node_modules/jest-runtime/build/index.js:2118:21)
      at Object.<anonymous> (src/helpers/pdf.ts:4:1)

Instead of trying to mock the node:buffer import with some weird/tricky code, I took a look at the NodeJS documentation examples. So it demonstrates that Blob can be imported from 'buffer'

import { Blob } from 'buffer';

// ...

// Only the import is changing, don't change your existing implementation
const blob = new Blob([buf], { type: 'application/pdf' });

And all Jest errors have been gone away!

Maxime Lafarie
  • 2,172
  • 1
  • 22
  • 41
  • Importing with the `node:` protocol appears to have been fixed in Jest 27.1.0 which was released only 3 days before this answer was posted. https://github.com/facebook/jest/releases/tag/v27.1.0 – Richie Bendall Jan 15 '22 at 07:26
  • Can you help fix module '"buffer"' has no exported member 'Blob'.ts(2305) – YTG Jul 06 '22 at 09:29
  • @YTG I would say it's due to the Node version you're using, but you have a topic on this issue here: https://stackoverflow.com/a/70868796/2724204 which suggests to set your package.json dependency for `@types/node` to `"@types/node": "^16.0.0"`. – Maxime Lafarie Jul 07 '22 at 09:00
-1

You can try use Readable.from(value.buffer) from "stream" node api.

It solved to me on FormData append file to send.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
-2

Another solution to consider is to use a Base64 String to transfer data from the Server to the client.

I am working on a Node.js project where I receive audio data in the form of an ArrayBuffer, and I want to send and play that data in the browser. Most of my struggles came from trying to send the ArrayBuffer to the client or trying to convert the ArrayBuffer and send a Buffer.

What ended up being a simple solution for me was to

  1. Convert the ArrayBuffer to a Base64 encoded String on the Server
  2. Return/Send the Base64 String to the client from the server
  3. Create an Audio element/object on the client side and play the sound

I used base64-arraybuffer to perform the ArrayBuffer > Base64 String conversion (though, it may be simple to do this without a package).

I used tips from here to create the audio element on the client side.

*I haven't done much in the way of testing limits - so I don't know how this might handle large audio files.

Rooster
  • 13
  • 2