The MediaStream Recording API, sometimes simply referred to as the Media Recording API or the MediaRecorder API, is closely affiliated with the Media Capture and Streams API and the WebRTC API. The MediaStream Recording API makes it possible to capture the data generated by a MediaStream
or HTMLMediaElement
object for analysis, processing, or saving to disk. It's also surprisingly easy to work with.
Basic concepts
The MediaStream Recording API is comprised of a single major interface, MediaRecorder
, which does all the work of taking the data from a MediaStream
and delivering it to you for processing. The data is delivered by a series of dataavailable
events, already in the format you specify when creating the MediaRecorder
. You can then process the data further or write it to file as desired.
Overview of the recording process
The process of recording a stream is simple:
- Set up a
MediaStream
orHTMLMediaElement
(in the form of an<audio>
or<video>
element) to serve as the source of the media data. - Create a
MediaRecorder
object, specifying the source stream and any desired options (such as the container's MIME type or the desired bit rates of its tracks). - Set
MediaRecorder.ondataavailable
to an event handler for thedataavailable
event; this will be called whenever data is available for you. - Once the source media is playing and you've reached the point where you're ready to record video, call
MediaRecorder.start()
to begin recording. - Your
dataavailable
event handler gets called every time there's data ready for you to do with as you will; the event has adata
attribute whose value is aBlob
that contains the media data. You can force adataavailable
event to occur, thereby delivering the latest sound to you so you can filter it, save it, or whatever. - Recording stops automatically when the source media stops playing.
- You can stop recording at any time by calling
MediaRecorder.stop()
.
Note: Individual Blob
s containing slices of the recorded media will not necessarily be individually playable. The media needs to be reassembled before playback.
If anything goes wrong during recording, an error
event is sent to the MediaRecorder
. You can listen for error
events by setting up a onerror
event handler.
Example here, we use an HTML Canvas as source of the MediaStream
, and stop recording after 9 seconds.
var canvas = document.querySelector("canvas"); // Optional frames per second argument. var stream = canvas.captureStream(25); var recordedChunks = []; console.log(stream); var options = { mimeType: "video/webm; codecs=vp9" }; mediaRecorder = new MediaRecorder(stream, options); mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(); function handleDataAvailable(event) { console.log("data-available"); if (event.data.size > 0) { recordedChunks.push(event.data); console.log(recordedChunks); download(); } else { // ... } } function download() { var blob = new Blob(recordedChunks, { type: "video/webm" }); var url = URL.createObjectURL(blob); var a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; a.href = url; a.download = "test.webm"; a.click(); window.URL.revokeObjectURL(url); } // demo: to download after 9sec setTimeout(event => { console.log("stopping"); mediaRecorder.stop(); }, 9000);
Examining and controlling the recorder status
You can also use the properties of the MediaRecorder
object to determine the state of the recording process, and its pause()
and resume()
methods to pause and resume recording of the source media.
If you need or want to check to see if a specific MIME type is supported, that's possible as well. Just call MediaRecorder.isTypeSupported()
.
Examining potential input sources
If your goal is to record camera and/or microphone input, you may wish to examine the available input devices before beginning the process of constructing the MediaRecorder
. To do so, you'll need to call navigator.mediaDevices.enumerateDevices()
to get a list of the available media devices. You can then examine that list and identify the potential input sources, and even filter the list based on desired criteria.
In this code snippet, enumerateDevices()
is used to examine the available input devices, locate those which are audio input devices, and create <option>
elements that are then added to a <select>
element representing an input source picker.
navigator.mediaDevices.enumerateDevices() .then(function(devices) { devices.forEach(function(device) { let menu = document.getElementById("inputdevices"); if (device.kind == "audioinput") { let item = document.createElement("option"); item.innerHTML = device.label; item.value = device.deviceId; menu.appendChild(item); } }); });
Code similar to this can be used to let the user restrict the set of devices they wish to use.
For more information
To learn more about using the MediaStream Recording API, see Using the MediaStream Recording API, which shows how to use the API to record audio clips. A second article, Recording a media element, describes how to receive a stream from an <audio>
or <video>
element and use the captured stream (in this case, recording it and saving it to a local disk).
Reference
BlobEvent
- Each time a chunk of media data is finished being recorded, it's delivered to consumers in
Blob
form using aBlobEvent
of typedataavailable
. MediaRecorder
- The primary interface that implements the MediaStream Recording API.
MediaRecorderErrorEvent
- The interface that represents errors thrown by the MediaStream Recording API. Its
error
property is aDOMException
that specifies that error occurred.
Specifications
Specification | Status | Comment |
---|---|---|
MediaStream Recording | Working Draft | Initial definition |
Browser compatibility
MediaRecorder
Desktop | Mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
MediaRecorder | Chrome Full support 47 | Edge Full support 79 | Firefox
Full support
25
| IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 47 | Chrome Android Full support 47 | Firefox Android
Full support
25
| Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
MediaRecorder() constructor | Chrome Full support 47 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 47 | Chrome Android Full support 47 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
audioBitsPerSecond | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 71 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android ? | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
error event | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
ignoreMutedMedia | Chrome No support 49 — 57 | Edge No support No | Firefox ? | IE No support No | Opera No support 36 — 44 | Safari No support No | WebView Android No support 49 — 57 | Chrome Android No support 49 — 57 | Firefox Android ? | Opera Android No support 36 — 44 | Safari iOS No support No | Samsung Internet Android No support 5.0 — 7.0 |
isTypeSupported | Chrome Full support 47 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 47 | Chrome Android Full support 47 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
mimeType | Chrome
Full support
49
| Edge Full support 79 | Firefox
Full support
25
| IE No support No | Opera Full support 36 | Safari No support No | WebView Android
Full support
49
| Chrome Android
Full support
49
| Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
ondataavailable | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onerror | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onpause | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 65 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 65 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onresume | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 65 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 65 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onstart | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onstop | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
onwarning | Chrome Full support 49 | Edge Full support 79 | Firefox No support 25 — 71 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
pause | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
requestData | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
resume | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
start | Chrome Full support 47 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 47 | Chrome Android Full support 47 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
state | Chrome
Full support
49
| Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android
Full support
49
| Chrome Android
Full support
49
| Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
stop | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
stream | Chrome
Full support
49
| Edge Full support 79 | Firefox Full support 25 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android
Full support
49
| Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
videoBitsPerSecond | Chrome Full support 49 | Edge Full support 79 | Firefox Full support 71 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android ? | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
warning event | Chrome Full support 49 | Edge Full support 79 | Firefox No support 25 — 71 | IE No support No | Opera Full support 36 | Safari No support No | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox Android Full support 25 | Opera Android Full support 36 | Safari iOS No support No | Samsung Internet Android Full support 5.0 |
Legend
- Full support
- Full support
- No support
- No support
- Compatibility unknown
- Compatibility unknown
- Experimental. Expect behavior to change in the future.
- Experimental. Expect behavior to change in the future.
- Non-standard. Expect poor cross-browser support.
- Non-standard. Expect poor cross-browser support.
- Deprecated. Not for use in new websites.
- Deprecated. Not for use in new websites.
- See implementation notes.
- See implementation notes.
See also
- Using the MediaStream Recording API
- Recording a media element
- simpl.info MediaStream Recording demo, by Sam Dutton
navigator.mediaDevices.getUserMedia()
- HTML5’s Media Recorder API in Action on Chrome and Firefox
- MediaRecorder polyfill for Safari and Edge
- TutorRoom: HTML5 video capture/playback/download using getUserMedia and the MediaRecorder API (source on GitHub)
- Simple video recording demo
- Advanced media stream recorder sample
- OpenLang: HTML5 video language lab web application using MediaDevices and the MediaStream Recording API for video recording (source on GitHub)
- MediaStream Recorder API Now Available in Safari Technology Preview 73