Realtime encoding `MediaRecorder` stream to `mp3`

241 Views Asked by At

I want to realtime encode MediaRecorder stream to mp3.

Currently I am saving stream from MediaRecorder as a blob variable. After the recording is done, I am converting the blob to wav and after that I am using lamejs to encode it to MP3. Because this process is on the main thread, encoding 5 minute long recording freezes the browser.

After searching online I found https://aws.nlited.org/mp3.htm, which is what I need. Unfortunately i throws a warning/error The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead. in the console.

I also tried

const dataArray = []

// globally load lamejs
const mp3Encoder = new lamejs.Mp3Encoder(
  1,
  44000,
  128
)

const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
const recorder = new MediaRecorder(stream, {
  audioBitsPerSecond: 9000,
})

recorder.ondataavailable = async ({ data }) => {
  const mp3Data = mp3Encoder.encodeBuffer(data) // I am not able to encode the data here, because the types/values does not match/do not work

  dataArray.push(mp3Data)
}

recorder.onstop = async () => {
  mediaStream.getAudioTracks().forEach(track => track.stop())

  const mp3Data = mp3Encoder.flush()
  dataArray.push(mp3Data)
}

// ----
// on play
// const blob = new Blob(dataArray, { type: 'audio/mp3' })
// download blob

I do not want to use webworker right now (or if you have drop-in replacement, feel free to help) or the ffmpeg library (too big for this use-case)

Maybe related - https://github.com/zhuker/lamejs/issues/68? But without an answer

Is there a way, how achieve the goal I want?

Thanks!

1

There are 1 best solutions below

0
On

After searching online I found https://aws.nlited.org/mp3.htm, which is what I need. Unfortunately i throws a warning/error The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead. in the console.

Yeah, well, you can ignore that error. It's been deprecated for years as a matter of best practice, but I don't really see anyone removing ScriptProcessorNode anytime soon.

In any case, most code that works in ScriptProcessorNode can be easily adapted to work with AudioWorklet, which is intended to replace ScriptProcessorNode and runs on a different thread.

I do not want to use webworker right now (or if you have drop-in replacement, feel free to help) or the ffmpeg library (too big for this use-case)

That's unfortunate, because that is the solution to your problem. You could build FFmpeg with Emscripten with just the modules you need for your use case and cut its size down considerably.