Learn more about Israeli war crimes in Gaza, funded by the USA, Germany, the UK and others.

MediaRecorder hello world

The MediaStream Recording API lets you convert a MediaStream to a Blob containing compressed video and audio. Here’s a hello world. Click the button, and this page will record a 5-second clip from your camera and microphone, then present it back for you to replay.

You first need a MediaStream, which you can get from many places, but here’s one method:

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

Next, you instantiate a MediaRecorder with the stream:

const recorder = new MediaRecorder(stream);

There are various options for how to encode the video, but we’ll leave it at the defaults.

The MediaRecorder provides data in a dataavailable event which contains a Blob. This event can happen many times. Each event contains a chunk of the recording since the previous event. The frequency of the dataavailable event depends on on how we configure the MediaRecorder. We can configure it to only provide a chunk once, but in general there are many chunks, so let’s assume that, and keep an array of all the chunks:

const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);

Once all the chunks have been provided, we get a stop event. Here, we concatenate our chunks into one video Blob, then set it as the source of a <video> element:

recorder.onstop = e => {
  const totalBlob = new Blob(chunks, { type: chunks[0].type });
  const url = URL.createObjectURL(totalBlob);
  const playbackVideoEl = document.createElement("video");
  playbackVideoEl.controls = true;
  playbackVideoEl.src = url;
  recordingsWrapperEl.appendChild(playbackVideoEl);
};

Nothing will happen yet! We need to start the recorder:

recorder.start(1000);

Still nothing will happen! We’re accumulating chunks, but at some point we need to tell the MediaRecorder stop, at which point it will generate any remaining chunks, and finally the stop event. Here I stop the recording after 5 seconds:

setTimeout(() => recorder.stop(), 5000);

One “interesting” issue I found was that the audio and video are sometimes not synced. I don’t know if this is a bug in Chrome. I was able to avoid this behavior by introducing a 1-second delay between getting the stream and starting the MediaRecorder. Something to investigate.

Tagged #programming, #web.

Similar posts

More by Jim

Want to build a fantastic product using LLMs? I work at Granola where we're building the future IDE for knowledge work. Come and work with us! Read more or get in touch!

This page copyright James Fisher 2020. Content is not associated with my employer. Found an error? Edit this page.