Recording videos in the browser using MediaRecorder

For a project which is currently in development, I’d liked to record a video from the webcam data that is available through getUserMedia. That’s how I got to know the MediaRecorder API.

Get the user media

First I discovered that navigator.getUserMedia is deprecated – you should use navigator.mediaDevices.getUserMedia now.

The new getUserMedia isn’t widely supported yet, but works very similar to the old implementation. Instead of passing in callbacks, it returns a Promise. Using the new implementation with a fallback to the old one is easy:

navigator.getUserMedia = navigator.getUserMedia ||
  navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
  navigator.msGetUserMedia;

var constraints = {
  video: true,
  audio: false
};

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  navigator.mediaDevices.getUserMedia(constraints)
    .then(handleStream)
    .catch(handleError);
} else if (navigator.getUserMedia) {
  navigator.getUserMedia(constraints, handleStream, handleError);
} else {
  console.error('getUserMedia is not supported.');
}

function handleStream(stream) {
  console.log(stream);
}

function handleError(error) {
  console.log(error);
}

So we hopefully get a video stream by now. But how to turn that in a video?

Using the MediaRecorder API

The MediaRecorder API is pretty new and currently only Firefox supports it in stable. In Chrome you need to enable the experimental flag and even then it supports only video recording but no audio recording. Re-check the browser support as that hopefully changes soon.

A implementation may look like the following (suppose we substitute the handleStream function from the example above):

function handleStream(stream) {
  var mediaRecorder = new window.MediaRecorder(stream);
  mediaRecorder.ondataavailable = function(event) {
    if (!event.data || event.data.size === 0) {
      return;
    }

    console.log(event.data); // Logs a Blob containing the video
  };

  mediaRecorder.start();
  setTimeout(function() {
    mediaRecorder.stop();
  }, 3000);
}

A new MediaRecorder can be created from the stream that we get from the getUserMedia APIs explained above. Calling .start() and .stop() on the created MediaRecorder will do as it says – start or stop the recording.

When there is data available, the ondataavailable handler is called. The data can then be retrieved from the passed event as a Blob. If .start() get’s called without a param, it will create one big chunk of data. It is also possible to pass parameter to .start(), defining a time slice. In that case, each time a slice got available, the ondataavailable handler will be called.

Further resources

To find out more, check the great Using the MediaRecorder API on MDN. This new API is a convenient way to create videos. Let’s hope the browser support get’s better soon!