# MediaStream Recording

## Editor’s Draft, 1 January 1970

This version:
  https://w3c.github.io/mediacapture-record/
Latest published version:
  https://www.w3.org/TR/mediastream-recording/
Previous Versions:
  https://www.w3.org/TR/2017/WD-mediastream-recording-20170405/
Feedback:
  public-media-capture@w3.org with subject line “`[mediastream-recording] … message topic …`” (archives)
Editor:
  Miguel Casas-Sanchez (Google Inc.)
Former Editors:
  Jim Barnett (Genesis)
  Travis Leithead (Microsoft Corp.)
Participate:
  Mailing list
  GitHub repo (new issue, open issues)
Implementation:
  Can I use Media Recording?
  Chromium Encode Acceleration Support

Copyright © 1970 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.

## Abstract

This document defines a recording API for use with `MediaStream`s.

## Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

If you wish to make comments regarding this document, please file an issue on the specification repository or send them to public-media-capture@w3.org (subscribe, archives).

This document was produced by the Web Real-Time Communications Working Group.

This document was produced by groups operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 March 2019 W3C Process Document.

## 1. Overview

This API attempts to make basic recording very simple, while still allowing for more complex use cases. In the simplest case, the application instantiates a `MediaRecorder` object, calls `start()` and then calls `stop()` or waits for the `MediaStreamTrack`(s) [GETUSERMEDIA] to be ended. The contents of the recording will be made available in the platform’s default encoding via the `ondataavailable` event. Functions are available to query the platform’s available set of encodings, and to select the desired ones if the author wishes. The application can also choose how much data it wants to receive at one time. By default a `Blob` containing the entire recording is returned when the recording finishes. However the application can choose to receive smaller buffers of data at regular intervals.

## 2. Media Recorder API

    [Exposed=Window,
     Constructor(MediaStream stream, optional MediaRecorderOptions options)]
    interface MediaRecorder : EventTarget {
      readonly attribute MediaStream stream;
      readonly attribute DOMString mimeType;
      readonly attribute RecordingState state;
      attribute EventHandler onstart;
      attribute EventHandler onstop;
      attribute EventHandler ondataavailable;
      attribute EventHandler onpause;
      attribute EventHandler onresume;
      attribute EventHandler onerror;
      readonly attribute unsigned long videoBitsPerSecond;
      readonly attribute unsigned long audioBitsPerSecond;

      void start(optional unsigned long timeslice);
      void stop();
      void pause();
      void resume();
      void requestData();

      static boolean isTypeSupported(DOMString type);
    };

### 2.1. Constructors

`MediaRecorder(MediaStream stream, optional MediaRecorderOptions options)`

  Parameter | Type | Nullable | Optional | Description
  --- | --- | --- | --- | ---
  stream | `MediaStream` | ✘ | ✘ | The `MediaStream` to be recorded. This will be the value of the `stream` attribute.
  options | `MediaRecorderOptions` | ✘ | ✔ | A dictionary of recording options.

  When the `MediaRecorder()` constructor is invoked, the User Agent MUST run the following steps:
  1. Let stream be the constructor’s first argument.
  2. Let options be the constructor’s second argument.
  3. If invoking is type supported with options’ `mimeType` member as its argument returns false, throw a `NotSupportedError` `DOMException` and abort these steps.
  4. Let recorder be a newly constructed `MediaRecorder` object.
  5. Let recorder have a [[ConstrainedMimeType]] internal slot, initialized to the value of options’ `mimeType` member.
  6. Let recorder have a [[ConstrainedBitsPerSecond]] internal slot, initialized to the value of options’ `bitsPerSecond` member, if it is present, otherwise `undefined`.
  7. Initialize recorder’s `stream` attribute to stream.
  8. Initialize recorder’s `mimeType` attribute to the value of recorder’s [[ConstrainedMimeType]] slot.
  9. Initialize recorder’s `state` attribute to `inactive`.
  10. Initialize recorder’s `videoBitsPerSecond` attribute to the value of options’ `videoBitsPerSecond` member, if it is present. Otherwise, choose a target value the User Agent deems reasonable for video.
  11. Initialize recorder’s `audioBitsPerSecond` attribute to the value of options’ `audioBitsPerSecond` member, if it is present. Otherwise, choose a target value the User Agent deems reasonable for audio.
  12. If recorder’s [[ConstrainedBitsPerSecond]] slot is not `undefined`, set recorder’s `videoBitsPerSecond` and `audioBitsPerSecond` attributes to values the User Agent deems reasonable for the respective media types, such that the sum of `videoBitsPerSecond` and `audioBitsPerSecond` is close to the value of recorder’s [[ConstrainedBitsPerSecond]] slot.
  13. Return recorder.

### 2.2. Attributes

`stream`, of type MediaStream, readonly
  The `MediaStream` [GETUSERMEDIA] to be recorded.
`mimeType`, of type DOMString, readonly
  The MIME type [RFC2046] used by the `MediaRecorder` object. The User Agent SHOULD be able to play back any of the MIME types it supports for recording. For example, it should be able to display a video recording in the HTML <video> tag.
  `mimeType` specifies the media type and container format for the recording via a type/subtype combination, with the codecs and/or profiles parameters [RFC6381] specified where ambiguity might arise. Individual codecs might have further optional specific parameters.
`state`, of type RecordingState, readonly
  The current state of the `MediaRecorder` object.
`onstart`, of type EventHandler
  Called to handle the start event.
`onstop`, of type EventHandler
  Called to handle the stop event.
`ondataavailable`, of type EventHandler
  Called to handle the dataavailable event. The `Blob` of recorded data is contained in this event and can be accessed via its `data` attribute.
`onpause`, of type EventHandler
  Called to handle the pause event.
`onresume`, of type EventHandler
  Called to handle the resume event.
`onerror`, of type EventHandler
  Called to handle a `MediaRecorderErrorEvent`.
`videoBitsPerSecond`, of type unsigned long, readonly
  The target bitrate used to encode video tracks.
`audioBitsPerSecond`, of type unsigned long, readonly
  The target bitrate used to encode audio tracks.

### 2.3. Methods

For historical reasons, the following methods alter `state` synchronously and fire events asynchronously.
`start(optional unsigned long timeslice)`
  When a `MediaRecorder` object’s `start()` method is invoked, the UA MUST run the following steps:
  1. Let recorder be the `MediaRecorder` object on which the method was invoked.
  2. Let timeslice be the method’s first argument, if provided, or `undefined`.
  3. Let stream be the value of recorder’s `stream` attribute.
  4. Let tracks be the set of `live` tracks in stream’s track set.
  5. If the value of recorder’s `state` attribute is not `inactive`, throw an `InvalidStateError` `DOMException` and abort these steps.
  6. If the isolation properties of stream disallow access from recorder, throw a `SecurityError` `DOMException` and abort these steps.
  7. If stream is inactive, throw a `NotSupportedError` `DOMException` and abort these steps.
  8. If the [[ConstrainedMimeType]] slot specifies a media type, container, or codec, then run the following sub steps:
     1. Constrain the configuration of recorder to the media type, container, and codec specified in the [[ConstrainedMimeType]] slot.
     2. For each track in tracks, if the User Agent cannot record the track using the current configuration, then throw a `NotSupportedError` `DOMException` and abort all steps.
  9. If recorder’s [[ConstrainedBitsPerSecond]] slot is not `undefined`, set recorder’s `videoBitsPerSecond` and `audioBitsPerSecond` attributes to values the User Agent deems reasonable for the respective media types, for recording all tracks in tracks, such that the sum of `videoBitsPerSecond` and `audioBitsPerSecond` is close to the value of recorder’s [[ConstrainedBitsPerSecond]] slot.
  10. Let videoBitrate be the value of recorder’s `videoBitsPerSecond` attribute, and constrain the configuration of recorder to target an aggregate bitrate of videoBitrate bits per second for all video tracks recorder will be recording. videoBitrate is a hint for the encoder and the value might be surpassed, not achieved, or only be achieved over a long period of time.
  11. Let audioBitrate be the value of recorder’s `audioBitsPerSecond` attribute, and constrain the configuration of recorder to target an aggregate bitrate of audioBitrate bits per second for all audio tracks recorder will be recording. audioBitrate is a hint for the encoder and the value might be surpassed, not achieved, or only be achieved over a long period of time.
  12. Set recorder’s `state` to `recording`, and run the following steps in parallel:
      1. If the container and codecs to use for the recording have not yet been fully specified, the User Agent specifies them in recorder’s current configuration. The User Agent MAY take the sources of the tracks in tracks into account when deciding which container and codecs to use.
         By looking at the sources of the tracks in tracks when recording starts, the User Agent could choose a configuration that avoids re-encoding track content. For example, if the MediaStreamTrack is a remote track sourced from an RTCPeerConnection, the User Agent could pick the same codec as is used for the MediaStreamTrack’s RTP stream, should it be known. However, if the codec of the RTP stream changes while recording, the User Agent has to be prepared to re-encode it to avoid interruptions.
      2. Start recording all tracks in tracks using the recorder’s current configuration and gather the data into a `Blob` blob. Queue a task, using the DOM manipulation task source, to run the following steps:
         1. Let extendedMimeType be the value of recorder’s [[ConstrainedMimeType]] slot.
         2. Modify extendedMimeType by adding media type, subtype and codecs parameter reflecting the configuration used by the MediaRecorder to record all tracks in tracks, if not already present. This MAY include the profiles parameter [RFC6381] or further codec-specific parameters.
         3. Set recorder’s `mimeType` attribute to extendedMimeType.
         4. Fire an event named start at recorder.
      3. If at any point stream’s isolation properties change so that `MediaRecorder` is no longer allowed access to it, the UA MUST immediately stop gathering data, discard any data that it has gathered, and queue a task, using the DOM manipulation task source, that runs the following steps:
         1. Inactivate the recorder with recorder.
         2. Fire an error event named `SecurityError` at recorder.
         3. Fire a blob event named dataavailable at recorder with blob.
         4. Fire an event named stop at recorder.
      4. If at any point, a track is added to or removed from stream’s track set, the UA MUST immediately stop gathering data, discard any data that it has gathered, and queue a task, using the DOM manipulation task source, that runs the following steps:
         1. Inactivate the recorder with recorder.
         2. Fire an error event named `InvalidModificationError` at recorder.
         3. Fire a blob event named dataavailable at recorder with blob.
         4. Fire an event named stop at recorder.
      5. If the UA at any point is unable to continue gathering data for reasons other than isolation properties or stream’s track set, it MUST stop gathering data, and queue a task, using the DOM manipulation task source, that runs the following steps:
         1. Inactivate the recorder with recorder.
         2. Fire an error event named `UnknownError` at recorder.
         3. Fire a blob event named dataavailable at recorder with blob.
         4. Fire an event named stop at recorder.
      6. If timeslice is not `undefined`, then once a minimum of timeslice milliseconds of data have been collected, or some minimum time slice imposed by the UA, whichever is greater, start gathering data into a new `Blob` blob, and queue a task, using the DOM manipulation task source, that fires a blob event named dataavailable at recorder with blob.

         Note that an `undefined` value of timeslice will be understood as the largest `unsigned long` value.

      7. If all recorded tracks become `ended`, then stop gathering data, and queue a task, using the DOM manipulation task source, that runs the following steps:
         1. Inactivate the recorder with recorder.
         2. Fire a blob event named dataavailable at recorder with blob.
         3. Fire an event named stop at recorder.

  Note that `stop()`, `requestData()`, and `pause()` also affect the recording behavior.

  The UA MUST record `stream` in such a way that the original Tracks can be retrieved at playback time. When multiple `Blob`s are returned (because of `timeslice` or `requestData()`), the individual Blobs need not be playable, but the combination of all the Blobs from a completed recording MUST be playable.

  If any Track within the `MediaStream` is `muted` or not `enabled` at any time, the UA will only record black frames or silence since that is the content produced by the Track.

  The Inactivate the recorder algorithm given a recorder, is as follows:

  1. Set recorder’s `mimeType` attribute to the value of the [[ConstrainedMimeType]] slot.
  2. Set recorder’s `state` attribute to `inactive`.
  3. If recorder’s [[ConstrainedBitsPerSecond]] slot is not `undefined`, set recorder’s `videoBitsPerSecond` and `audioBitsPerSecond` attributes to values the User Agent deems reasonable for the respective media types, such that the sum of `videoBitsPerSecond` and `audioBitsPerSecond` is close to the value of recorder’s [[ConstrainedBitsPerSecond]] slot.

  Parameter | Type | Nullable | Optional | Description
  --- | --- | --- | --- | ---
  timeslice | `unsigned long` | ✘ | ✔ | The minimum number of milliseconds of data to return in a single Blob.

`stop()`
  When a `MediaRecorder` object’s `stop()` method is invoked, the UA MUST run the following steps:
  1. Let recorder be the `MediaRecorder` object on which the method was invoked.
  2. If recorder’s `state` attribute is `inactive`, abort these steps.
  3. Inactivate the recorder with recorder.
  4. Queue a task, using the DOM manipulation task source, that runs the following steps:
     1. Stop gathering data.
     2. Let blob be the Blob of collected data so far, then fire a blob event named dataavailable at recorder with blob.
     3. Fire an event named stop at recorder.
  5. return `undefined`.
`pause()`
  When a `MediaRecorder` object’s `pause()` method is invoked, the UA MUST run the following steps:
  1. If `state` is `inactive`, throw an `InvalidStateError` `DOMException` and abort these steps.
  2. If `state` is `paused`, abort these steps.
  3. Set `state` to `paused`, and queue a task, using the DOM manipulation task source, that runs the following steps:
     1. Stop gathering data into blob (but keep it available so that recording can be resumed in the future).
     2. Let target be the MediaRecorder context object. Fire an event named pause at target.
  4. return `undefined`.
`resume()`
  When a `MediaRecorder` object’s `resume()` method is invoked, the UA MUST run the following steps:
  1. If `state` is `inactive`, throw an `InvalidStateError` `DOMException` and abort these steps.
  2. If `state` is `recording`, abort these steps.
  3. Set `state` to `recording`, and queue a task, using the DOM manipulation task source, that runs the following steps:
     1. Resume (or continue) gathering data into the current blob.
     2. Let target be the MediaRecorder context object. Fire an event named resume at target.
  4. return `undefined`.
`requestData()`
  When a `MediaRecorder` object’s `requestData()` method is invoked, the UA MUST run the following steps:
  1. If `state` is `inactive` throw an `InvalidStateError` `DOMException` and terminate these steps. Otherwise the UA MUST queue a task, using the DOM manipulation task source, that runs the following steps:
     1. Let blob be the `Blob` of collected data so far and let target be the `MediaRecorder` context object, then fire a blob event named dataavailable at target with blob. (Note that blob will be empty if no data has been gathered yet.)
     2. Create a new Blob and gather subsequent data into it.
  2. return `undefined`.
`isTypeSupported(DOMString type)`
  Check to see whether a `MediaRecorder` can record in a specified MIME type. If true is returned from this method, it only indicates that the `MediaRecorder` implementation is capable of recording `Blob` objects for the specified MIME type. Recording may still fail if sufficient resources are not available to support the concrete media encoding. When this method is invoked, the User Agent must return the result of is type supported, given the method’s first argument.

  Parameter | Type | Nullable | Optional | Description
  --- | --- | --- | --- | ---
  type | `DOMString` | ✘ | ✘ | A MIME Type, including parameters when needed, specifying a container and/or codec formats for recording.

  The is type supported algorithm consists of the following steps.
  1. Let type be the algorithm’s argument.
  2. If type is an empty string, then return true (note that this case is essentially equivalent to leaving up to the UA the choice of both container and codecs).
  3. If type does not contain a valid MIME type string, then return false.
  4. If type contains a media type or media subtype that the MediaRecorder does not support, then return false.
  5. If type contains a media container that the MediaRecorder does not support, then return false.
  6. If type contains more than one audio codec, or more than one video codec, then return false.
  7. If type contains a codec that the MediaRecorder does not support, then return false.
  8. If the MediaRecorder does not support the specified combination of media type/subtype, codecs and container then return false.
  9. Return true.

### 2.4. Data handling

To fire a blob event with a `Blob` blob means to fire an event at target using a `BlobEvent` with its `data` attribute initialized to blob.

Usually blob will be the data gathered by the UA after the last transition to `recording` `state`.

### 2.5. MediaRecorderOptions

    dictionary MediaRecorderOptions {
      DOMString mimeType = "";
      unsigned long audioBitsPerSecond;
      unsigned long videoBitsPerSecond;
      unsigned long bitsPerSecond;
    };

#### 2.5.1. Members

`mimeType`, of type DOMString, defaulting to `""`
  The container and codec format(s) [RFC2046] for the recording, which may include any parameters that are defined for the format.
  `mimeType` specifies the media type and container format for the recording via a type/subtype combination, with the codecs and/or profiles parameters [RFC6381] specified where ambiguity might arise. Individual codecs might have further optional or mandatory specific parameters.
`audioBitsPerSecond`, of type unsigned long
  Aggregate target bits per second for encoding of the Audio track(s), if any.
`videoBitsPerSecond`, of type unsigned long
  Aggregate target bits per second for encoding of the Video track(s), if any.
`bitsPerSecond`, of type unsigned long
  Aggregate target bits per second for encoding of all Video and Audio Track(s) present. This member overrides either `audioBitsPerSecond` or `videoBitsPerSecond` if present, and might be distributed among the present track encoders as the UA sees fit.

### 2.6. RecordingState

    enum RecordingState {
      "inactive",
      "recording",
      "paused"
    };

#### 2.6.1. Values

`inactive`
  Recording is not occuring: Either it has not been started or it has been stopped.
`recording`
  Recording has been started and the UA is capturing data.
`paused`
  Recording has been started, then paused, and not yet stopped or resumed.

## 3. Blob Event

    [Exposed=Window, Constructor(DOMString type, BlobEventInit eventInitDict)]
    interface BlobEvent : Event {
      [SameObject] readonly attribute Blob data;
      readonly attribute DOMHighResTimeStamp timecode;
    };

### 3.1. Constructors

`BlobEvent(DOMString type, BlobEventInit eventInitDict)`

### 3.2. Attributes

`data`, of type Blob, readonly
  The encoded `Blob` whose `type` attribute indicates the encoding of the blob data.
`timecode`, of type DOMHighResTimeStamp, readonly
  The difference between the timestamp of the first chunk in `data` and the timestamp of the first chunk in the first `BlobEvent` produced by this recorder as a `DOMHighResTimeStamp` [HR-TIME]. Note that the `timecode` in the first produced `BlobEvent` does not need to be zero.

### 3.3. BlobEventInit

    dictionary BlobEventInit {
      required Blob data;
      DOMHighResTimeStamp timecode;
    };

#### 3.3.1. Members

`data`, of type Blob
  A `Blob` object containing the data to deliver via `BlobEvent`.
`timecode`, of type DOMHighResTimeStamp
  The timecode to be used in initializing `BlobEvent`.

## 4. Error handling

### 4.1. General principles

This section is non-normative.

The UA will throw a `DOMException` when the error can be detected at the time that the call is made. In all other cases the UA will fire an event named `MediaRecorderErrorEvent`. If recording has been started and not yet stopped when the error occurs, let blob be the `Blob` of collected data so far; after raising the error, the UA will fire a dataavailable event with blob; immediately after the UA will then fire an event named `stop`. The UA may set platform-specific limits, such as those for the minimum and maximum `Blob` size that it will support, or the number of `MediaStreamTrack`s it will record at once. It will signal a fatal error if these limits are exceeded.

### 4.2. MediaRecorderErrorEvent

The `MediaRecorderErrorEvent` interface is defined for cases when an event is raised that was caused by an error.

To fire an error event named e with a `DOMException` named error means that an event with the name e, which does not bubble (except where otherwise stated) and is not cancelable (except where otherwise stated), and which uses the `MediaRecorderErrorEvent` interface with the `error` attribute set to error, must be created and dispatched at the given target.

    dictionary MediaRecorderErrorEventInit : EventInit {
      required DOMException error;
    };

    [Exposed=Window, Constructor(DOMString type, MediaRecorderErrorEventInit eventInitDict)]
    interface MediaRecorderErrorEvent : Event {
      [SameObject] readonly attribute DOMException error;
    };

#### 4.2.1. Constructors

`MediaRecorderErrorEvent(DOMString type, MediaRecorderErrorEventInit eventInitDict)`
  Constructs a new `MediaRecorderErrorEvent`.

  Parameter | Type | Nullable | Optional | Description
  --- | --- | --- | --- | ---
  type | `DOMString` | ✘ | ✘ |
  eventInitDict | `MediaRecorderErrorEventInit` | ✘ | ✘ |

#### 4.2.2. Attributes

`error`, of type DOMException, readonly
  The DOMException error that triggered the event.

#### 4.2.3. MediaRecorderErrorEventInit

`error`, of type DOMException
  The `DOMException` causing the error that triggered the event. An explanatory message about the error circumstances MAY be provided in its message attribute.
  If an implementation places non-standard properties on `DOMException`, exposing e.g. stack traces or error line numbers, these are encouraged to point to whichever method call most closely identifies the run-time operation that caused the error, e.g. `start()`.

### 4.3. Exception Summary

Each of the exceptions defined in this document is a `DOMException` with a specific type.

Name | Description
--- | ---
`InvalidStateError` | An operation was called on an object on which it is not allowed or at a time when it is not allowed, or if a request is made on a source object that has been deleted or removed.
`NotSupportedError` | An operation could not be performed because the MIME type was not supported or the set of tracks could not be recorded by the MIME type. User agents should provide as much additional information as possible in the `message` attribute.
`SecurityError` | The isolation properties of the `MediaStream` do not allow the MediaRecorder access to it.
`InvalidModificationError` | The set of `MediaStreamTrack`s of the recoded `MediaStream` has changed, preventing any further recording.

## 5. Event summary

The following additional events fire on `MediaRecorder` objects:

Event name | Interface | Fired when...
--- | --- | ---
start | `Event` | The UA has started recording data from the MediaStream.
stop | `Event` | The UA has stopped recording data from the MediaStream.
dataavailable | `BlobEvent` | The UA generates this even to return data to the application. The `data` attribute of this event contains a `Blob` of recorded data.
pause | `Event` | The UA has paused recording data from the MediaStream.
resume | `Event` | The UA has resumed recording data from the MediaStream.
error | `MediaRecorderErrorEvent` | An error has occurred, e.g. out of memory or a modification to the `stream` has occurred that makes it impossible to continue recording (e.g. a Track has been added to or removed from the said `stream` while recording is occurring).

## 6. Privacy and Security Considerations

This section is non-normative.

Given that the source of data for `MediaRecorder` is always going to be a `stream`, a large part of the security is essentially offloaded onto the [GETUSERMEDIA] and its "Privacy and Security Consideration" Section. In particular, the source `stream` is assumed to be coming from a secure context.

### 6.1. Resource exhaustion

Video and audio encoding can consume a great deal of resources. A malicious website could try to block or bring down the UA by configuring too large a workload, e.g. encoding large frame resolutions and/or framerates.

`MediaRecorder` can be configured to hold on to the encoded data for a certain period of time upon `start()` by means of the `timeslice` parameter. Too large a time slice parameter can force the UA to buffer a large amount of data, causing jankiness and othermise memory exhaustion.

UAs should take measures to avoid the encoding and buffering process from exhausting the resources.

## 7. Examples

Slightly modified versions of these examples can be found in e.g. this codepen collection.

### 7.1. Check for `MediaRecorder` and content types

This example checks if the implementation supports a few popular codec/container combinations.

The following example can also be found in e.g. this codepen with minimal modifications.

    if (window.MediaRecorder == undefined) {
      console.error('MediaRecorder not supported, boo');
    } else {
      var contentTypes = ["video/webm",
                          "video/webm;codecs=vp8",
                          "video/x-matroska;codecs=avc1",
                          "audio/webm",
                          "video/mp4;codecs=avc1",
                          "video/invalid"];
      contentTypes.forEach(contentType => {
        console.log(contentType + ' is '
            + (MediaRecorder.isTypeSupported(contentType) ?
                'supported' : 'NOT supported '));
      });
    }

### 7.2. Recording webcam video and audio

This example captures an video+audio `MediaStream` using `getUserMedia()`, plugs it into a `<video>` tag and tries to record it, retrieving the recorded chunks via the `ondataavailable` event. Note that the recording will go on forever until either MediaRecorder is `stop()`ed or all the `MediaStreamTrack`s of the recorded `MediaStream` are `ended`.

The following example can also be found in e.g. this codepen with minimal modifications.

    <html>
    <body>
    <video autoplay/>
    <script>
      var recordedChunks = [];

      function gotMedia(stream) {
        // |video| shows a live view of the captured MediaStream.
        var video = document.querySelector('video');
        video.src = URL.createObjectURL(stream);

        var recorder = null;
        try {
          recorder = new MediaRecorder(stream, {mimeType : "video/webm"});
        } catch (e) {
          console.error('Exception while creating MediaRecorder: ' + e);
          return;
        }

        recorder.ondataavailable = (event) => {
          console.log(' Recorded chunk of size ' + event.data.size + "B");
          recordedChunks.push(event.data);
        };

        recorder.start(100);
      }

      navigator.mediaDevices.getUserMedia({video: true , audio: true})
          .then(gotMedia)
          .catch(e => { console.error('getUserMedia() failed: ' + e); });
    </script>
    </body>
    </html>

The `recordedChunks` can be saved to a file using e.g. the function `download()` in the MediaRecorder Web Fundamentals article.

## Conformance

### Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with `class="example"`, like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with `class="note"`, like this:

Note, this is an informative note.

### Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

### Conformance Classes

A conformant user agent must implement all the requirements listed in this specification that are applicable to user agents.

A conformant server must implement all the requirements listed in this specification that are applicable to servers.

## Index

### Terms defined by this specification

- audioBitsPerSecond
  - attribute for MediaRecorder, in §2.2
  - dict-member for MediaRecorderOptions, in §2.5.1
- bitsPerSecond, in §2.5.1
- BlobEvent, in §3
- BlobEventInit, in §3.3
- BlobEvent(type, eventInitDict), in §3.1
- conformant server, in §Unnumbered section
- conformant user agent, in §Unnumbered section
- [[ConstrainedBitsPerSecond]], in §2.1
- [[ConstrainedMimeType]], in §2.1
- data
  - attribute for BlobEvent, in §3.2
  - dict-member for BlobEventInit, in §3.3.1
- dataavailable, in §5
- error
  - attribute for MediaRecorderErrorEvent, in §4.2.2
  - definition of, in §5
  - dict-member for MediaRecorderErrorEventInit, in §4.2.3
- fire an error event, in §4.2
- Inactivate the recorder, in §2.3
- "inactive", in §2.6.1
- inactive, in §2.6.1
- is type supported, in §2.3
- isTypeSupported(type), in §2.3
- MediaRecorder, in §2
- MediaRecorderErrorEvent, in §4.2
- MediaRecorderErrorEventInit, in §4.2
- MediaRecorderErrorEvent(type, eventInitDict), in §4.2.1
- MediaRecorderOptions, in §2.5
- MediaRecorder(stream), in §2.1
- MediaRecorder(stream, options), in §2.1
- mimeType
  - attribute for MediaRecorder, in §2.2
  - dict-member for MediaRecorderOptions, in §2.5.1
- ondataavailable, in §2.2
- onerror, in §2.2
- onpause, in §2.2
- onresume, in §2.2
- onstart, in §2.2
- onstop, in §2.2
- pause, in §5
- pause(), in §2.3
- "paused", in §2.6.1
- paused, in §2.6.1
- "recording", in §2.6.1
- recording, in §2.6.1
- RecordingState, in §2.6
- requestData(), in §2.3
- resume, in §5
- resume(), in §2.3
- start, in §5
- start(), in §2.3
- start(timeslice), in §2.3
- state, in §2.2
- stop, in §5
- stop(), in §2.3
- stream, in §2.2
- timecode
  - attribute for BlobEvent, in §3.2
  - dict-member for BlobEventInit, in §3.3.1
- To fire a blob event, in §2.4
- videoBitsPerSecond
  - attribute for MediaRecorder, in §2.2
  - dict-member for MediaRecorderOptions, in §2.5.1

https://dom.spec.whatwg.org/#event Referenced in:

- 3. Blob Event
- 4.2. MediaRecorderErrorEvent
- 5. Event summary (2) (3) (4)

https://dom.spec.whatwg.org/#dictdef-eventinit Referenced in:

- 4.2. MediaRecorderErrorEvent

https://dom.spec.whatwg.org/#eventtarget Referenced in:

- 2. Media Recorder API

https://dom.spec.whatwg.org/#concept-event-fire Referenced in:

- 2.3. Methods (2) (3) (4) (5) (6) (7) (8)
- 2.4. Data handling
- 4.1. General principles (2)
- 5. Event summary

https://w3c.github.io/FileAPI/#dfn-Blob Referenced in:

- 1. Overview
- 2.2. Attributes
- 2.3. Methods (2) (3) (4) (5)
- 2.4. Data handling
- 3. Blob Event
- 3.2. Attributes (2)
- 3.3. BlobEventInit
- 3.3.1. Members (2)
- 4.1. General principles (2)
- 5. Event summary

https://w3c.github.io/FileAPI/#dfn-type Referenced in:

- 3.2. Attributes

https://html.spec.whatwg.org/multipage/webappapis.html#eventhandler Referenced in:

- 2. Media Recorder API (2) (3) (4) (5) (6)
- 2.2. Attributes (2) (3) (4) (5) (6)

https://w3c.github.io/webappsec-secure-contexts/#secure-contexts Referenced in:

- 6. Privacy and Security Considerations

https://heycam.github.io/webidl/#idl-DOMException Referenced in:

- 2.1. Constructors
- 2.3. Methods (2) (3) (4) (5) (6) (7)
- 4.1. General principles
- 4.2. MediaRecorderErrorEvent (2) (3)
- 4.2.2. Attributes
- 4.2.3. MediaRecorderErrorEventInit (2) (3)
- 4.3. Exception Summary

https://heycam.github.io/webidl/#idl-DOMString Referenced in:

- 2. Media Recorder API (2)
- 2.2. Attributes
- 2.3. Methods
- 2.5. MediaRecorderOptions
- 2.5.1. Members
- 3. Blob Event
- 4.2. MediaRecorderErrorEvent
- 4.2.1. Constructors

https://heycam.github.io/webidl/#Exposed Referenced in:

- 2. Media Recorder API
- 3. Blob Event
- 4.2. MediaRecorderErrorEvent

https://heycam.github.io/webidl/#invalidmodificationerror Referenced in:

- 2.3. Methods
- 4.3. Exception Summary

https://heycam.github.io/webidl/#invalidstateerror Referenced in:

- 2.3. Methods (2) (3) (4)
- 4.3. Exception Summary

https://heycam.github.io/webidl/#notsupportederror Referenced in:

- 2.1. Constructors
- 2.3. Methods (2)
- 4.3. Exception Summary

https://heycam.github.io/webidl/#SameObject Referenced in:

- 3. Blob Event
- 4.2. MediaRecorderErrorEvent

https://heycam.github.io/webidl/#securityerror Referenced in:

- 2.3. Methods (2)
- 4.3. Exception Summary

https://heycam.github.io/webidl/#unknownerror Referenced in:

- 2.3. Methods

https://heycam.github.io/webidl/#idl-boolean Referenced in:

- 2. Media Recorder API

https://heycam.github.io/webidl/#idl-unsigned-long Referenced in:

- 2. Media Recorder API (2) (3)
- 2.2. Attributes (2)
- 2.5. MediaRecorderOptions (2) (3)
- 2.5.1. Members (2) (3)

### Terms defined by reference

- [DOM] defines the following terms:
  - Event
  - EventInit
  - EventTarget
  - fire an event
- [FileAPI] defines the following terms:
  - Blob
  - type
- [HTML] defines the following terms:
  - EventHandler
- [secure-contexts] defines the following terms:
  - secure contexts
- [WebIDL] defines the following terms:
  - DOMException
  - DOMString
  - Exposed
  - InvalidModificationError
  - InvalidStateError
  - NotSupportedError
  - SameObject
  - SecurityError
  - UnknownError
  - boolean
  - unsigned long

## References

### Normative References

[DOM]
  Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[FileAPI]
  Marijn Kruisselbrink; Arun Ranganathan. File API. 31 May 2019. WD. URL: https://www.w3.org/TR/FileAPI/
[GETUSERMEDIA]
  Daniel Burnett; et al. Media Capture and Streams. 3 October 2017. CR. URL: https://www.w3.org/TR/mediacapture-streams/
[HR-TIME]
  Jatinder Mann. High Resolution Time. 17 December 2012. REC. URL: https://www.w3.org/TR/hr-time/
[HTML]
  Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2046]
  N. Freed; N. Borenstein. Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types. November 1996. Draft Standard. URL: https://tools.ietf.org/html/rfc2046
[RFC2119]
  S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[SECURE-CONTEXTS]
  Mike West. Secure Contexts. 15 September 2016. CR. URL: https://www.w3.org/TR/secure-contexts/
[WebIDL]
  Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/

### Informative References

[RFC6381]
  R. Gellens; D. Singer; P. Frojdh. The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types. August 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6381

## IDL Index

    [Exposed=Window,
     Constructor(MediaStream stream, optional MediaRecorderOptions options)]
    interface MediaRecorder : EventTarget {
      readonly attribute MediaStream stream;
      readonly attribute DOMString mimeType;
      readonly attribute RecordingState state;
      attribute EventHandler onstart;
      attribute EventHandler onstop;
      attribute EventHandler ondataavailable;
      attribute EventHandler onpause;
      attribute EventHandler onresume;
      attribute EventHandler onerror;
      readonly attribute unsigned long videoBitsPerSecond;
      readonly attribute unsigned long audioBitsPerSecond;

      void start(optional unsigned long timeslice);
      void stop();
      void pause();
      void resume();
      void requestData();

      static boolean isTypeSupported(DOMString type);
    };

    dictionary MediaRecorderOptions {
      DOMString mimeType = "";
      unsigned long audioBitsPerSecond;
      unsigned long videoBitsPerSecond;
      unsigned long bitsPerSecond;
    };

    enum RecordingState {
      "inactive",
      "recording",
      "paused"
    };

    [Exposed=Window, Constructor(DOMString type, BlobEventInit eventInitDict)]
    interface BlobEvent : Event {
      [SameObject] readonly attribute Blob data;
      readonly attribute DOMHighResTimeStamp timecode;
    };

    dictionary BlobEventInit {
      required Blob data;
      DOMHighResTimeStamp timecode;
    };

    dictionary MediaRecorderErrorEventInit : EventInit {
      required DOMException error;
    };

    [Exposed=Window, Constructor(DOMString type, MediaRecorderErrorEventInit eventInitDict)]
    interface MediaRecorderErrorEvent : Event {
      [SameObject] readonly attribute DOMException error;
    };

#mediarecorder Referenced in:

- 1. Overview
- 2.1. Constructors
- 2.2. Attributes (2)
- 2.3. Methods (2) (3) (4) (5) (6) (7) (8) (9) (10) (11)
- 5. Event summary
- 6. Privacy and Security Considerations
- 6.1. Resource exhaustion
- 7.1. Check for MediaRecorder and content types

#dom-mediarecorder-start-timeslice-timeslice Referenced in:

- 2.3. Methods
- 6.1. Resource exhaustion

#dom-mediarecorder-mediarecorder Referenced in:

- 2.1. Constructors

#constrainedmimetype Referenced in:

- 2.1. Constructors
- 2.3. Methods (2) (3) (4)

#constrainedbitspersecond Referenced in:

- 2.1. Constructors (2)
- 2.3. Methods (2) (3) (4)

#dom-mediarecorder-stream Referenced in:

- 2. Media Recorder API
- 2.1. Constructors (2)
- 2.3. Methods (2)
- 5. Event summary (2)
- 6. Privacy and Security Considerations (2)

#dom-mediarecorder-mimetype Referenced in:

- 2. Media Recorder API
- 2.1. Constructors
- 2.2. Attributes
- 2.3. Methods (2)

#dom-mediarecorder-state Referenced in:

- 2. Media Recorder API
- 2.1. Constructors
- 2.3. Methods (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12)
- 2.4. Data handling

#dom-mediarecorder-onstart Referenced in:

- 2. Media Recorder API

#dom-mediarecorder-onstop Referenced in:

- 2. Media Recorder API

#dom-mediarecorder-ondataavailable Referenced in:

- 1. Overview
- 2. Media Recorder API
- 7.2. Recording webcam video and audio

#dom-mediarecorder-onpause Referenced in:

- 2. Media Recorder API

#dom-mediarecorder-onresume Referenced in:

- 2. Media Recorder API

#dom-mediarecorder-onerror Referenced in:

- 2. Media Recorder API

#dom-mediarecorder-videobitspersecond Referenced in:

- 2. Media Recorder API
- 2.1. Constructors (2) (3)
- 2.3. Methods (2) (3) (4) (5)

#dom-mediarecorder-audiobitspersecond Referenced in:

- 2. Media Recorder API
- 2.1. Constructors (2) (3)
- 2.3. Methods (2) (3) (4) (5)

#dom-mediarecorder-start Referenced in:

- 1. Overview
- 2. Media Recorder API
- 2.3. Methods
- 4.2.3. MediaRecorderErrorEventInit
- 6.1. Resource exhaustion

#abstract-opdef-inactivate-the-recorder Referenced in:

- 2.3. Methods (2) (3) (4) (5)

#dom-mediarecorder-stop Referenced in:

- 1. Overview
- 2. Media Recorder API
- 2.3. Methods (2)
- 7.2. Recording webcam video and audio

#dom-mediarecorder-pause Referenced in:

- 2. Media Recorder API
- 2.3. Methods (2)

#dom-mediarecorder-resume Referenced in:

- 2. Media Recorder API
- 2.3. Methods

#dom-mediarecorder-requestdata Referenced in:

- 2. Media Recorder API
- 2.3. Methods (2) (3)

#dom-mediarecorder-istypesupported Referenced in:

- 2. Media Recorder API

#abstract-opdef-is-type-supported Referenced in:

- 2.1. Constructors
- 2.3. Methods

#to-fire-a-blob-event Referenced in:

- 2.3. Methods (2) (3) (4) (5) (6) (7)
- 4.1. General principles

#dictdef-mediarecorderoptions Referenced in:

- 2. Media Recorder API
- 2.1. Constructors

#dom-mediarecorderoptions-mimetype Referenced in:

- 2.1. Constructors (2)
- 2.5. MediaRecorderOptions
- 2.5.1. Members

#dom-mediarecorderoptions-audiobitspersecond Referenced in:

- 2.1. Constructors
- 2.5. MediaRecorderOptions
- 2.5.1. Members

#dom-mediarecorderoptions-videobitspersecond Referenced in:

- 2.1. Constructors
- 2.5. MediaRecorderOptions
- 2.5.1. Members

#dom-mediarecorderoptions-bitspersecond Referenced in:

- 2.1. Constructors
- 2.5. MediaRecorderOptions

#enumdef-recordingstate Referenced in:

- 2. Media Recorder API
- 2.2. Attributes

#dom-recordingstate-inactive Referenced in:

- 2.1. Constructors
- 2.3. Methods (2) (3) (4) (5) (6)
- 2.6. RecordingState

#dom-recordingstate-recording Referenced in:

- 2.3. Methods (2) (3)
- 2.4. Data handling
- 2.6. RecordingState

#dom-recordingstate-paused Referenced in:

- 2.3. Methods (2)
- 2.6. RecordingState

#blobevent Referenced in:

- 2.4. Data handling
- 3.2. Attributes (2)
- 3.3.1. Members (2)
- 5. Event summary

#dom-blobevent-data Referenced in:

- 2.2. Attributes
- 2.4. Data handling
- 3. Blob Event
- 3.2. Attributes
- 5. Event summary

#dom-blobevent-timecode Referenced in:

- 3. Blob Event
- 3.2. Attributes

#dictdef-blobeventinit Referenced in:

- 3. Blob Event

#dom-blobeventinit-data Referenced in:

- 3.3. BlobEventInit

#dom-blobeventinit-timecode Referenced in:

- 3.3. BlobEventInit

#fire-an-error-event Referenced in:

- 2.3. Methods (2) (3)

#dictdef-mediarecordererroreventinit Referenced in:

- 4.2. MediaRecorderErrorEvent
- 4.2.1. Constructors

#mediarecordererrorevent Referenced in:

- 2.2. Attributes
- 4.1. General principles
- 4.2. MediaRecorderErrorEvent (2)
- 4.2.1. Constructors
- 5. Event summary

#dom-mediarecordererrorevent-error Referenced in:

- 4.2. MediaRecorderErrorEvent (2)

#dom-mediarecordererroreventinit-error Referenced in:

- 4.2. MediaRecorderErrorEvent

#start Referenced in:

- 2.2. Attributes
- 2.3. Methods

#stop Referenced in:

- 2.2. Attributes
- 2.3. Methods (2) (3) (4) (5)

#dataavailable Referenced in:

- 2.2. Attributes
- 2.3. Methods (2) (3) (4) (5) (6) (7)

#pause Referenced in:

- 2.2. Attributes
- 2.3. Methods

#resume Referenced in:

- 2.2. Attributes
- 2.3. Methods