Skip to content
Advertisement

How to save MediaRecorder Web API output to disk using a stream

I am experimenting with the MediaStream Recording API within Electron (therefore Node.js) and wish to handle the output as a stream. Handling as a stream would allow me to process the MediaRecorder output before saving to disk – I could encrypt it, for example. For my specific use case I am just concerned with audio, so I do not have any video elements recording.

My most basic use case is to simply save the output to disk using a stream, but I cannot seem to achieve this fundamental task, so I will focus this question on achieving this.

Question: How to save MediaRecorder Web API output to disk using a stream.

I can save a file to disk using a download “hack”, provided and described as such by Google here, and successfully use node.js fs to open, transform (encrypt), save a new encrypted file, and delete the unencrypted file. This means that I ultimately have to save unencrypted data to disk. Even if for a short amount of time, this feels like a security compromise that I thought would be easy to avoid by encrypting before saving.

There is a risk I am getting quite a few wires crossed between different stream objects, but I am surprised I have not found a solution online yet – therefore I am popping my StackOverflow question cherry.

A project highlighting all I have tried is below. The key code in is record.js, in the save() function.

Ultimately, I am trying to create a suitable readStream to plug into the writeStream created with const writeStream = fs.createWriteStream(fPath); using readStream.pipe(writeStream).

In summary, I have tried the following:

1. Blob to readStream

I cannot convert Blob into readStream, only ReadableStream , ReadableStreamDefaultReader or Uint8Array

2. Blob to file (in memory) and then use fs.createReadStream()

I cannot seem to use an ObjectURL in fs.createReadStream(url), it insists on appending a local Path. The answer to this question suggests this is a limitation of fs.createReadStream() and using http.get() or request() is not suitable in my case because I am not trying to access a remote resource.

3. Blob to buffer and then use fs.createReadStream()

I cannot convert Blob to a buffer that can be used in fs.createReadStream(buffer), only an arrayBuffer or one with null bytes

Any help is greatly appreciated!


Project:

Node 12.13.0, Chrome 80.0.3987.158, and Electron 8.2.0.

Set-up:

  • the four files: main.js, package.json, index.html, record.js are all single level in the project folder.

Contents of each file:

package.json:

JavaScript

main.js:

JavaScript

index.html:

JavaScript

record.js:

JavaScript

Run the following:

JavaScript

Advertisement

Answer

OK, I cracked it… Ultimately, the crux of the challenge was:

how to convert blob into readablestream in node.js.

Anyway, in summary the steps I found to work are: blob > arrayBuffer > array > buffer > readStream

I needed the following function to convert a buffer to a stream. Reference and Node.js docs:

JavaScript

The rest of the conversion steps are one-liners and the full save function is here:

JavaScript

And I can finally pipe and can continue using other stream functions between the data and the save, for example, encryption. 🙂

Hope this helps someone else too.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement