> ## Content Index
> Fetch the complete content index at: https://blog.addpipe.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# HTML5’s Media Recorder API in Action on Chrome and Firefox
- URL: https://blog.addpipe.com/mediarecorder-api/
- Published: 2015-12-10T10:32:57.000Z
- Updated: 2026-05-21T08:31:12.000Z
- Author: Remus
- Tags: MediaStream Recording API, getUserMedia, Technology, #Import 2026-05-22 13:18

**April 2016 update: added info about Chrome 49**

**October 2016 update: added H.264 support for Chrome 52**

For many years recording webcam video on the web meant using Adobe’s Flash plugin. This is still true at the moment, but the new JavaScript Media Recorder API (previously known as the MediaStream Recording API) is slowly crawling its way in today’s modern browsers – and it will allow video recording using just HTML 5 and JavaScript.

In this article we will dig deeper into what the [Media Recorder API](https://addpipe.com/media-recorder-api-demo/) is, it’s current state, browser support and what it could mean for the future of the web.

### What is the Media Recorder API?

Until recently it was just a [proposal](https://w3c.github.io/mediacapture-record/MediaRecorder.html) by the [Media Capture Task Force](http://www.w3.org/2009/dap/#mediacapture) (a joint task force between the [WebRTC ](http://www.w3.org/2011/04/webrtc/)and [Device APIs](http://www.w3.org/2009/dap/) working groups) that attempts to make basic audio and video recording in the browser very simple.

But recent versions of Chrome and Firefox have started implementing this proposed API.

The API defines the **new MediaRecorder JS object**, its functions:

- `start()`
- `stop()`
- `pause()`
- `resume()`

events:

- `onstart`
- `onstop`
- `ondataavailable`
- `onpause`
- `onresume`
- `on error`

and properties:

- `state`
- `stream`
- `mimeType`

The new MediaRecorder object relies on the (existing) `getUserMedia` JavaScript function to access to the webcam and microphone but, as we’ll see next, that’s where the touch points with WebRTC end.

### HTML5’s Media Recorder API in Action

So how does video recording work using this new API ? The [document draft](https://w3c.github.io/mediacapture-record/MediaRecorder.html) contains all the details, but the gist of it is:

1. Webcam input (audio and video) is accessed by `getUserMedia`.
2. A new `MediaRecorder` JS object is created and starts the recording process
3. `MediaRecorder`‘s `ondataavailable` event gets triggered with new audio and video data that’s pushed in an array
4. When the `MediaRecorder`‘s `stop` method is called, the `onstop` event is triggered. This is where all the data can be saved as a video file (webm) or played back immediately in a `<video>` tag.

### HTML5 Video Recorder – Quick Implementation

I’ve created a cross browser demo (Chrome + Firefox) that implements the API. Check it out [here](https://addpipe.com/media-recorder-api-demo/) or [download it from GitHub](https://github.com/nusofthq/Media-Recorder-API-Demo).

#### Now let’s go over the JavaScript code a bit.

In the demo code the 1st thing I’m doing is I’m detecting whether the code is run on Chrome or Firefox. This information is important because:

1. The way the audio and video constraints need to be defined differs in Chrome and Firefox.
2. At the time of writing, **audio recording is not supported in Chrome** when using the [Media Recorder API](https://addpipe.com/media-recorder-api-demo/).

This is also where I’m specifying the desired video resolution for the recording.

```javascript
if (getBrowser() == "Chrome") {
    var constraints = {
        "audio": false,
        "video": {
            "mandatory": {
                "minWidth": 320,
                "maxWidth": 320,
                "minHeight": 240,
                "maxHeight": 240
            },
            "optional": []
        }
    };
} else if (getBrowser() == "Firefox") {
    var constraints = {
        audio: true,
        video: {
            width: {
                min: 320,
                ideal: 320,
                max: 1280
            },
            height: {
                min: 240,
                ideal: 240,
                max: 720
            }
        }
    };
}

```

With that out of the way, clicking the Record button triggers the `startRecording` function:

```javascript
function onBtnRecordClicked() {
    if (typeof MediaRecorder === 'undefined' || !navigator.getUserMedia) {
        alert('Sorry! This demo requires Firefox 30 and up or Chrome 47 and up.');
    } else {
        navigator.getUserMedia(constraints, startRecording, errorCallback);
    }
}

```

`startRecording` is where all the juicy stuff happens:

```javascript
function startRecording(stream) {
    console.log('Starting...');
    mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.start();
    var url = window.URL || window.webkitURL;
    videoElement.src = url ? url.createObjectURL(stream) : stream;
    videoElement.play();
    mediaRecorder.ondataavailable = function(e) {
        chunks.push(e.data);
    };
    mediaRecorder.onerror = function(e) {
        log('Error: ' + e);
        console.log('Error: ', e);
    };
    mediaRecorder.onstart = function() {
        log('Started, state = ' + mediaRecorder.state);
    };
    mediaRecorder.onstop = function() {
        log('Stopped, state = ' + mediaRecorder.state);
        var blob = new Blob(chunks, {
            type: "video/webm"
        });
        chunks = [];
        var videoURL = window.URL.createObjectURL(blob);
        downloadLink.href = videoURL;
        videoElement.src = videoURL;
        downloadLink.innerHTML = 'Download video file';
        var rand = Math.floor((Math.random() * 10000000));
        var name = "video_" + rand + ".webm";
        downloadLink.setAttribute("download", name);
        downloadLink.setAttribute("name", name);
    };
    mediaRecorder.onwarning = function(e) {
        log('Warning: ' + e);
    };
}

```

The function takes as parameter the `stream` object from `getUserMedia`. The stream data is made available when `ondataavailable` gets triggered and that’s where it gets pushed into the aptly named `chunks` array.

When we press the Stop button `onstop`is triggered. A new `video/webm` Blob object is created with the data from the `chunks` array.

A source for the video tag gets created directly from the Blob data with `createObjectURL`. The same Blob is also saved as a video when the download is made.

### File Formats and Audio Video Codecs

According to the [draft](http://w3c.github.io/mediacapture-record/MediaRecorder.html):

> The contents of the recording will be made available in the platform’s default encoding via the dataavailable event. Functions are available to query the platform’s available set of encodings, and to select the desired ones if the author wishes.

The **video container** used by both Chrome and Firefox is:

- .webm

The **video codecs** available are:

- VP8 on Firefox and Chrome 47+
- VP8/VP9 on Chrome 49+
- VP8/VP9/H.264 on Chrome 52+

The **audio codec** used is:

- Vorbis @ 44100 Hz on Firefox 30+
- Opus Audio @ 48000 Hz on Chrome 49+

|             | Chrome 49+   | Chrome 52+    | Firefox 30 and up |
| ----------- | ------------ | ------------- | ----------------- |
| Container   | webm         | webm          | webm              |
| Video codec | VP8/VP9      | VP8/VP9/H.264 | VP8               |
| Audio codec | Opus @ 48kHz | Opus @ 48kHz  | Vorbis @ 44.1 kHz |

Not quite the standard .MP4 file with H.264 video and AAC audio.

### Browser Support and Limitations

Currently the [Media Recorder API](https://addpipe.com/media-recorder-api-demo/) is supported on the following browsers:

On Desktop:

- Firefox 30 and up
- Chrome 47 & 48 ( no sound is being recorded and it only works with *experimental Web Platform features* turned on from **chrome://flags/#enable-experimental-web-platform-features**
- Chrome 49 [supports audio & video recording](https://developers.google.com/web/updates/2016/01/mediarecorder?hl=en) without the flag

On Mobile:

- Chrome for Android.

Downloaded .webm recordings also work in a video player like VLC regardless if they originate on Firefox or Chrome.

### Final Conclusions

Although a simple and promising start, the **Media Recording API** still has some way to go before it can be used in a production environment:

- there’s a lack of implementation and even initiative on major browsers like Safari and IE/Edge
- there are no container or audio/video codec options
- ~~no sound in the Chrome implementation~~ (audio recording works in Chrome 49)
- there’s no bitrate or picture quality control
- there’s no sample rate or audio quality control
- no support for .mp4, ~~H.264 video~~ and/or AAC audio
- .webm files (with Vorbis/Opus audio and VP8/VP9 video) will have to be converted before they playback on virtually anything else other than the browsers they were recorded in
- all the recorded data is stored *locally* in the RAM, which limits the amount of video you can record to short video clips – as opposed to video recording solutions that rely on streaming the data
- the standard’s `pause()` and `resume()` functions are not implemented yet

As for being a direct competitor for Flash when it comes to video recording, it can and most surely will happen, but at the current stage of the API, a Flash client connected to a media server is still the best production ready and cross (desktop) browser solution for recording video.

**More about the MediaStream Recording API on our blog:**

- [Media Recorder API is Now Supported by 65% of all Desktop Internet Users](https://blog.addpipe.com/media-recorder-api-is-now-supported-by-65-of-all-desktop-internet-users/)
- [Media Recorder API Demo: Video Recording](https://addpipe.com/media-recorder-api-demo/)
- [MediaStream Recorder API Now Available in Safari Technology Preview 73](https://blog.addpipe.com/safari-technology-preview-73-adds-limited-mediastream-recorder-api-support/)
- [Recording audio in the browser using MediaStream Recorder API](https://blog.addpipe.com/recording-audio-in-the-browser-using-pure-html5-and-minimal-javascript/)