W3C

MediaStream Recording

W3C Working Draft 05 February 2013

This version:
http://www.w3.org/TR/2013/WD-mediastream-recording-20130205/
Latest published version:
http://www.w3.org/TR/mediastream-recording/
Latest editor's draft:
https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html
Editors:
Jim Barnett, Genesys
Travis Leithead, Microsoft Corp.

Abstract

This document defines a recording API for use with MediaStreams as defined in Media Capture and Streams [GETUSERMEDIA].

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

The API this document describes derives from a proposal originally developed by Ian Hickson, then included in an early version of the WebRTC API. The API has significantly evolved based on the ongoing work on Media Capture and Streams [GETUSERMEDIA], and to take into account the requirements highlighted in MediaStream Capture Scenarios. This is its first publication as a Working Draft on its own.

This document is not complete. It is subject to major changes and, while early experimentations are encouraged, it is therefore not intended for implementation. The Media Capture Task Force, a joint task force of the Device APIs and WebRTC Working Groups, expects this specification to evolve significantly based on:

This document was published by the Web Real-Time Communication Working Group and Device APIs Working Group as a First Public Working Draft. If you wish to make comments regarding this document, please send them to public-media-capture@w3.org (subscribe, archives). All comments are welcome.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by groups operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures (Web Real-Time Communication Working Group, Device APIs Working Group) made in connection with the deliverables of the groups; 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.

Table of Contents

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 the MediaRecorder object, calls record() and then calls stopRecord() or waits for the MediaStream to be ended. 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 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

[Constructor (MediaStream stream)]
interface MediaRecorder : EventTarget {
    readonly attribute MediaStream        stream;
    readonly attribute RecordingStateEnum state;
    readonly attribute unsigned long      imageWidth;
    readonly attribute unsigned long      imageHeight;
    readonly attribute DOMString          mimeType;
             attribute EventHandler       onrecording;
             attribute EventHandler       onstop;
             attribute EventHandler       ondataavailable;
             attribute EventHandler       onpause;
             attribute EventHandler       onresume;
             attribute EventHandler       onmutetrack;
             attribute EventHandler       onunmutetrack;
             attribute EventHandler       onphoto;
             attribute EventHandler       onerror;
             attribute EventHandler       onwarning;
    void              record (optional long? timeslice);
    void              stop ();
    void              pause ();
    void              resume ();
    void              muteTrack (DOMString trackID);
    void              unmuteTrack (DOMString trackID);
    void              takePhoto (DOMString trackID);
    void              requestData ();
    AvailableSettings getOptions ();
    void              setOptions (RecordingSettings optionValues);
};

2.1 Attributes

imageHeight of type unsigned long, readonly
The height of the video or photo image to capture. The initial value will be a platform-supplied default.
imageWidth of type unsigned long, readonly
The width of the video or photo image to capture. The initial value will be a platform-supplied default.
mimeType of type DOMString, readonly
The MIME type for recording. It specifies the container format as well as the audio and video capture formats. The initial value will be a platform-supplied default.
ondataavailable of type EventHandler
Called to handle the dataavailable event. Note that the Blob (see [FILE-API]) of recorded data is contained in this event and can be accessed via the 'data' attribute.
onerror of type EventHandler
Called to handle the recordingerror event.
onmutetrack of type EventHandler
Called to handle the mutetrack event.
onpause of type EventHandler
Called to handle the pause event.
onphoto of type EventHandler
Called to handle the photo event. The photo event returns a photo (as a Blob) in a compressed format (for example: PNG/JPEG) rather than a raw ImageData object due to the expected large, uncompressed size of the resulting photos.
onrecording of type EventHandler
Called to handle the recording event.
onresume of type EventHandler
Called to handle the resume event.
onstop of type EventHandler
Called to handle the stop event.
onunmutetrack of type EventHandler
Called to handle the unmutetrack event.
onwarning of type EventHandler
Called to handle the recordingwarning event.
state of type RecordingStateEnum, readonly
The current state of the MediaRecorder object.
stream of type MediaStream, readonly
The MediaStream passed in to the constructor.

2.2 Methods

getOptions
When a MediaRecorder object’s getOptions() method is invoked, the user agent must return an AvailableSettings structure containing the set of recording options that it supports. These are the legal values that can be set via setOptions.
No parameters.
Return type: AvailableSettings
muteTrack
When a MediaRecorder object’s muteTrack() method is invoked, then if state is not "recording" the user agent must raise an INVALID_STATE exception and return immediately. Otherwise if the trackID provided is not the id of a Track object in stream's audioTrackList or videoTrackList it must raise an INVALID_TRACK_ID exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. If the specified Track is a video track, begin inserting black frames into the Blob in place of any data coming from the underlying source. Otherwise (the Track is an audio track) insert silence into the Blob in place of any data coming from the underlying source.
  2. Raise a mutetrackrecording event.
ParameterTypeNullableOptionalDescription
trackIDDOMString The id of the audio or video track to mute.
Return type: void
pause
When a MediaRecorder object’s pause()method is invoked, then if state is "inactive" the user agent must raise an INVALID_STATE exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Set state to "paused".
  2. Stop gathering data into its current Blob (but keep the Blob available so that recording can be resumed in the future).
  3. Raise a pause event
No parameters.
Return type: void
record
When a MediaRecorder object’s record() method is invoked, then, if the state is not "inactive", the UA must raise an INVALID_STATE exception and return immediately. Otherwise, it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Set state to 'recording' and wait until media becomes available from stream.
  2. Once data becomes available raise a recording event and start gathering the data into a Blob (see [FILE-API]).
  3. If the timeSlice argument has been provided, then once timeSlice milliseconds of data have been collected, raise a dataavailable event containing the Blob of collected data, and start gathering a new Blob of data. Otherwise (if timeSlice has not been provided), continue gathering data into the original Blob.
  4. When the stream is ended set recording to 'false' and stop gathering data.
  5. Then raise a dataavailable event containing the Blob of data.
  6. Finally, raise a stoprecording event.

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

The UA must record the MediaStream in such a way that the original Tracks can be retrieved at playback time. If any Track within the MediaStream is muted at any time (i.e., if its readyState is set to muted), the UA must insert black frames or silence until the Track is unmuted. If the UA is unable to start recording or at any point is unable to continue recording, it must raise a recordingerror event, followed by a dataavailable event containing the Blob it has gathered, followed by the stoprecording event.

ParameterTypeNullableOptionalDescription
timeslicelong The number of milliseconds of data to return in a single Blob.
Return type: void
requestData
When a MediaRecorderobject’s requestData() method is invoked, then if state is not "recording" the user agent must raise an INVALID_STATE exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Raise a dataavailable event containing the current Blob of saved data.
  2. Create a new Blob and gather subsequent data into it.
No parameters.
Return type: void
resume
When a MediaRecorder object’s resume() method is invoked, then if state is "inactive" the user agent must raise an INVALID_STATE exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Set state to "recording".
  2. Resume (or continue) gathering data into its current Blob.
  3. Raise a resume event.
No parameters.
Return type: void
setOptions
When a MediaRecorder object’s setOptions() method is invoked, then if state is not "inactive", the user agent must raise an INVALID_STATE exception and return immediately. Otherwise it must run the following steps before returning:
  1. Let currentOptions be the current set of options that are specified to be used for recording by the MediaRecorder. (If setOptions() has not yet been called, these will be the UA's defaults.)
  2. For each option that is specified in the optionVlaues argument, if the UA does not support it, raise a UNSUPPORTED_OPTION exception, set currentOptions back to its value in step 2, and terminate these steps. Otherwise replace the corresponding member of currentOptions with the specified value.
ParameterTypeNullableOptionalDescription
optionValuesRecordingSettings
Return type: void
stop
When a MediaRecorder object’s stopRecording method is invoked, then if state is "inactive", the user agent must raise an INVALID_STATE exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Set state to 'inactive' and stop gathering data.
  2. Raise a dataavailable event containing the Blob of data that has been gathered.
  3. Raise a recordingdone event
No parameters.
Return type: void
takePhoto
When a MediaRecorder object’s takePhoto() method is invoked, then if the trackID provided is not the id of a Track object in stream's videoTrackList whose readyState is "live", the UA must raise an INVALID_TRACK_ID exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Gather data from the Track into a Blob containing a single still image. The method of doing this will depend on the underlying device. Some devices may just do a frame grab, while others may temporarily stop streaming data, reconfigure themselves with the appropriate photo settings, take the photo, and then resume streaming. In this case, the stopping and restarting of streaming should cause mute and unmute events to fire on the Track in question.
  2. Raise an photo event containing the Blob.
ParameterTypeNullableOptionalDescription
trackIDDOMString The id of the video track from which to take a snapshot.
Return type: void
unmuteTrack
When a MediaRecorder object’s unmuteTrack() method is invoked, then if state is not "recording", the user agent must raise an INVALID_STATE exception and return immediately. Otherwise if the trackID provided is not the id of a Track object in stream's audioTrackList or videoTrackList it must raise an INVALID_TRACK_ID exception and return immediately. Otherwise it must queue a task, using the DOM manipulation task source, that runs the following steps:
  1. Until such time as data is available for this Track from the underlying media source, insert black frames (for a video track) or silence (for an audio track) into the current Blob.
  2. Once data is available for this Track from the underlying media source, start collecting it into the current Blob.
  3. Raise an unmutetrack event.
ParameterTypeNullableOptionalDescription
trackIDDOMString The id of the audio or video track to unmute.
Return type: void

The MediaRecorder() constructor takes one argument which must be of type MediaStream (see [GETUSERMEDIA]). When the constructor is invoked, the UA must construct a new MediaRecorder object, set its stream attribute to be the provided MediaStream, set its state attribute to 'inactive' and return the object.

2.3 RecordingStateEnum

enum RecordingStateEnum {
    "inactive",
    "recording",
    "paused"
};
Enumeration description
inactiveRecording is not occurring. (Either it has not been started or it has been stopped.).
recordingRecording has been started and the UA is capturing data..
pausedRecording has been started, then paused, and not yet stopped or resumed.

3. Blob Event

[Constructor]
interface BlobEvent : Event {
    readonly attribute Blob data;
};

3.1 Attributes

data of type Blob, readonly
Returns a Blob object whose type attribute indicates the encoding of the blob data. An implementation must return a Blob in a format that is capable of being viewed in an HTML <img> tag. .

BlobEventInit

dictionary BlobEventInit {
    Blob data;
};

3.2 Dictionary BlobEventInit Members

data of type Blob
A Blob object containing the data to deliver via this event.

4. Settings Dictionaries

dictionary AvailableSettings {
    CapabilityList  MimeType;
    CapabilityRange imageWidth;
    CapabilityRange imageHeight;
};

4.1 Dictionary AvailableSettings Members

MimeType of type CapabilityList
A list of the MIME types that can be selected as encodings for recording.
imageHeight of type CapabilityRange
The maximum and minimum height, in pixels, for the capture of video or photo images.
imageWidth of type CapabilityRange
The maximum and minimum width, in pixels, for the capture of video or photo images.
dictionary RecordingSettings {
    DOMString?     MimeType;
    unsigned long? imageWidth;
    unsigned long? imageHeight;
};

4.2 Dictionary RecordingSettings Members

MimeType of type DOMString, nullable
Used to set the value of mimeType.
imageHeight of type unsigned long, nullable
Used to set the value of imageWidth.
imageWidth of type unsigned long, nullable
Used to set the value of imageWidth.

5. Error Handling

5.1 General Principles

Errors are indicated in two ways: exceptions and objects passed to error callbacks. Both forms of error reporting must provide an object of type RecordingError. An exception must be thrown in the following cases:

In all other cases, an error object must be provided to the failure callback. The error name in the object provided must be picked from the RecordingErrorName enums. After raising the error, the UA must raise a dataavailable event, containing any data that it has gathered, and then a recordingdone event. The UA may set platform-specific limits, such those for the minimum and maximum Blob size that it will support, or the number of Tracks it will record at once. It must signal a fatal error if these limits are exceeded. If a non-fatal error occurs during recording, the UA should raise a recordingwarning event, with data indicating the nature of the problem, and continue recording.

5.2 RecordingError

interface RecordingError : Error {
    readonly attribute RecordingErrorEnum name;
    readonly attribute DOMString?         message;
};

5.2.1 Attributes

message of type DOMString, readonly, nullable
A human readable description of the error. This string may vary between different user agents.
name of type RecordingErrorEnum, readonly
A string representing the type of the error.
dictionary RecordingErrorInit {
    RecordingErrorEnum name;
    DOMString?         message;
};

5.2.2 Dictionary RecordingErrorInit Members

message of type DOMString, nullable
Used to set the message attribute.
name of type RecordingErrorEnum
Used to set the name attribute.

5.2.3 RecordingErrorNameEnum

enum RecordingErrorNameEnum {
    "OUT_OF_MEMORY",
    "ILLEGAL_STREAM_MODIFICATION",
    ""OTHER_RECORDING_ERROR""
};
Enumeration description
OUT_OF_MEMORYThe UA has exhausted the available memory. User agents should provide as much additional information as possible in the message attribute.
ILLEGAL_STREAM_MODIFICATIONA modification to the stream has occurred that makes it impossible to continue recording. An example would be the addition of a Track while recording is occurring. User agents should provide as much additional information as possible in the message attribute.
"OTHER_RECORDING_ERROR"Used for an fatal error other than those listed above. User agents should provide as much additional information as possible in the message attribute.

5.3 RecordingExceptionEnum

enum RecordingExcedptionEnum {
    "INVALID_STATE",
    "INVALID_MEDIASTREAM_TRACK_ID",
    "UNSUPPORTED_OPTION"
};
Enumeration description
INVALID_STATEThe function was called on a MediaRecorder that is an invalid state, or a state in which the function is not allowed to be executed.
INVALID_MEDIASTREAM_TRACK_ID The argument provided is not the ID of any MediaStreamTrack belonging to the MediaRecorder's stream.
UNSUPPORTED_OPTIONThe UA cannot provide the codec or recording option that has been requested.

6. Event summary

This section is non-normative.

The following additional events fire on MediaRecorder objects:

Event name Interface Fired when...
recording Event The UA has started recording data on the MediaStream.
stoprecording Event The UA has stopped recording data on 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.
photo BlobEvent The UA uses this event to return a photo to the application (as a Blob). The 'data' attribute of this event contains a Blob of recorded snapshot data.
pause Event The UA has paused recording data on the MediaStream.
resume MediaStreamEvent The UA has resumed recording data on the MediaStream.
mutetrack MediaStreamTrackEvent The MediaRecorder has muted recording on a Track.
unmutetrack MediaStreamTrackEvent The MediaRecorder has unmuted recording on a Track.
recordingerror RecordingError A fatal error has occurred and the UA has stopped recording. More detailed error information is available in the 'message' attribute.
recordingwarning CustomEvent A problem has occurred, but the UA has not stopped recording. More detailed information is available in the 'message' attribute. [Not clear if we need this event.]

A. A. Open Issues

  1. Do we need an MTI format?
  2. Do we need a "setSyncPoint()" operator and a "syncpoint" signal, so that the client can tell the recorder to insert a point at which a recording can be broken up (typically a new I-frame)?
  3. Do we need to ask the user's permission before we record?

B. References

B.1 Normative references

[FILE-API]
Arun Ranganathan; Jonas Sicking. File API. 20 October 2011. W3C Working Draft. URL: http://www.w3.org/TR/2011/WD-FileAPI-20111020/
[GETUSERMEDIA]
D. Burnett; A. Narayanan. Media Capture and Streams 28 June 2012. W3C Working Draft. URL: http://www.w3.org/TR/2012/WD-mediacapture-streams-20120628/