-1

I’m building a web application that captures microphone audio using MediaRecorder and sends it to the backend for processing. Everything works fine on most devices (desktop and mobile), but on some devices, the MediaRecorder.ondataavailable callback is called with an empty Blob (event.data.size === 0), making it impossible to capture usable audio.

Here’s the relevant code:

const recorder = new MediaRecorder(stream, {
  mimeType: 'audio/webm;codecs=opus',
})

recorder.ondataavailable = (event) => {
  if (event.data.size > 0) {
    chunksRef.current.push(event.data)
    dataReadyRef.current = true
  } else {
    console.warn('Empty blob update:', event.data)
  }
}

I’m calling recorder.start(1000) to get audio chunks every second. Later I use recorder.stop() to finalize the blob.

On affected devices, I frequently get the warning:

Empty blob update: Blob {size: 0, type: 'audio/webm;codecs=opus'}

My questions:

  1. Why would ondataavailable be triggered with empty blobs?
  2. Are there any known limitations with MediaRecorder across devices/browsers?
  3. Is there a recommended fallback strategy to ensure we still get usable audio blobs?

Any help or advice would be appreciated.

1
  • 1
    I wouldn't worry. It can happen. (1) Do you have a Timer or other function doing some requestData() call? (2) Is the sound really unusable if you skip a zero-sized chunk? Commented Jun 6 at 17:34

1 Answer 1

1

This isn't really a problem. Append your blobs like any other, and if they are zero bytes in length, then so be it. All this means is that the encoder didn't have a chunk for you at that time.

Think about it this way... there are buffers along each stage:

  1. Audio Capture
  2. Presentation of audio through OS and its audio stack
  3. MediaStream/getUserMedia implementation
  4. MediaRecorder capture of MediaStream
  5. Codec (Opus)
  6. Muxer (WebM/Matroska)
  7. MediaRecorder blob-ifying the muxer output

In an ideal world, these would all run in lockstep but that's just not possible. Your audio capture buffers might be only like 256 samples, the OS and its audio stack might resample which may want bigger chunks, the browser side might also resample and will also chunk differently to reduce CPU load, the MediaRecorder can probably take whatever buffer size but might also need to adjust in case hardware accelerated codecs are used (not in audio land, but you get the idea). Finally you get to the codec, which is lossy here and will have a relatively large buffer, likely 10x more than what was captured. Then, the muxer has to repack it all and then blobs need to be made, and so on.

So, if you demand audio every 1 second, but it wants to deliver to you every 1.1 seconds, maybe you don't get a blob with data yet.

I will say... this seems to be a rare situation. I've never seen it happen when using .start() with a timeslice. MediaRecorder is smart enough to not give you a blob until its ready. But, there's no problem here. It doesn't hurt the usable output one bit.

Those blobs are not intended to standalone. This is a common misconception about MediaRecorder. So, if it's giving you trouble, you're likely just using the output incorrectly.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.