This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
* Some parts of this feature may have varying levels of support.
The Media Capabilities API provides several key features to help you better decide how to handle media, but also to determine how well media is being handled, in real time.
These features include:
MediaSource method isTypeSupported() or the HTMLMediaElement method canPlayType().Note: The display capabilities functionality mentioned in the third point above have not yet appeared in any browser. They will be a useful feature of the API once available, but there is a high probability of the display capabilities functionality changing a great deal before browser implementations arrive.
The MediaCapabilities is available using the mediaCapabilities property which is provided by both the navigator object and the WorkerNavigator object; in other words, the Media Capabilities API is available both on the main thread and from workers.
If the object exists, Media Capabilities API is available. You can, therefore, test for the presence of the API like so:
if ("mediaCapabilities" in navigator) {
// mediaCapabilities is available
} else {
// mediaCapabilities IS NOT available
}
Taking video as an example, to obtain information about video decoding abilities, you create a video decoding configuration which you pass as a parameter to MediaCapabilities.decodingInfo() method. This returns a promise that fulfills with information about the media capabilities as to whether the video can be decoded, and whether decoding will be smooth and power efficient. You can also test audio decoding as well as video and audio encoding.
The MediaCapabilities.decodingInfo() method takes as a parameter a media decoding configuration.
In our example, we are testing the decoding capabilities of a video configuration. The configuration requires the type of media being tested — e.g., a plain file or MediaSource — and a video configuration object that includes values for the contentType, width, height, bitrate, and framerate:
contentType must be a string specifying a valid video MIME type.width and height are the horizontal and vertical dimensions of the video; these are also used to determine the aspect ratio.bitrate is the number of bits used to encode one second of video.framerate is the number of frames which are played per second of time when playing the video.const videoConfiguration = {
type: "file",
video: {
contentType: "video/webm;codecs=vp8",
width: 800,
height: 600,
bitrate: 10000,
framerate: 15,
},
};
Had we been querying the decodability of an audio file, we would create an audio configuration including the number of channels and sample rate, leaving out the properties that apply only to video—namely, the dimensions and the frame rate:
const audioConfiguration = {
type: "file",
audio: {
contentType: "audio/ogg",
channels: 2,
bitrate: 132700,
samplerate: 5200,
},
};
Had we been testing encoding capabilities, we would have created a slightly different configuration. In this case the type of media being tested is either record (for recording media, i.e., a MediaRecorder object) or transmission (for media transmitted over electronic means like RTCPeerConnection) — plus either an audio or video configuration as described above.
Now that we've created a video decoding configuration we can pass it as a parameter of the decodingInfo() method to determine if a video matching this configuration would be decodable and if the playback would be smooth and power efficient.
let promise = navigator.mediaCapabilities.decodingInfo(videoConfiguration);
The decodingInfo() and encodingInfo() methods both return promises. Once the promise states are fulfilled, you can access the supported, smooth, and powerEfficient properties from the returned object.
Instead of the assigning the promise to a variable, we can output the values returned by the promise to the console:
navigator.mediaCapabilities.decodingInfo(videoConfiguration).then((result) => {
console.log(
`This configuration is ${result.supported ? "" : "not "}supported,`,
);
console.log(`${result.smooth ? "" : "not "}smooth, and`);
console.log(`${result.powerEfficient ? "" : "not "}power efficient.`);
});
In our video decoding example, a TypeError would be raised if the media configuration passed to the decodingInfo() method was invalid. There are a few reasons why an error might occur, including:
type isn't one of the two permitted values: file or media-source
contentType given isThe error can be due to the type not being one of the two possible values, the contentType not being a valid codec MIME type, or invalid or omitted definitions being omitted from the video configuration object.
navigator.mediaCapabilities
.decodingInfo(videoConfiguration)
.then(() => console.log("It worked"))
.catch((error) => console.error(`It failed: ${error}`));
li {
margin: 1em;
}
<form>
<p>
Select your video configuration and find out if this browser supports the
codec, and whether decoding will be smooth and power efficient:
</p>
<ul>
<li>
<label for="codec">Select a codec</label>
<select id="codec">
<option>video/webm; codecs=vp8</option>
<option>video/webm; codecs=vp9</option>
<option>video/mp4; codecs=avc1</option>
<option>video/mp4; codecs=avc1.420034</option>
<option>invalid</option>
</select>
</li>
<li>
<label for="size">Select a size</label>
<select id="size">
<option>7680x4320</option>
<option>3840x2160</option>
<option>2560x1440</option>
<option>1920x1080</option>
<option>1280x720</option>
<option selected>800x600</option>
<option>640x480</option>
<option>320x240</option>
<option value=" x ">none</option>
</select>
</li>
<li>
<label for="framerate">Select a framerate</label>
<select id="framerate">
<option>60</option>
<option>50</option>
<option>30</option>
<option>24</option>
<option selected>15</option>
</select>
</li>
<li>
<label for="bitrate">Select a bitrate</label>
<select id="bitrate">
<option>4000</option>
<option>2500</option>
<option>800</option>
</select>
</li>
</ul>
<p>
<input type="button" value="Test this Video Configuration" id="try-it" />
</p>
</form>
<ul id="results"></ul>
let mc = {
videoConfiguration: {},
tryIt() {
mc.createConfiguration();
mc.testIt();
},
createConfiguration() {
const size = document.getElementById("size").value.split("x");
mc.videoConfiguration = {
type: "file",
video: {
contentType: document.getElementById("codec").value,
width: size[0],
height: size[1],
bitrate: document.getElementById("bitrate").value,
framerate: document.getElementById("framerate").value,
},
};
},
testIt() {
let content = "";
navigator.mediaCapabilities
.decodingInfo(mc.videoConfiguration)
.then((result) => {
const li = document.createElement("li"),
mcv = mc.videoConfiguration.video;
content = `A ${mcv.width}x${mcv.height}, ${mcv.contentType} at ${
mcv.framerate
}fps and ${mcv.bitrate} bps video ${
result.supported ? " IS " : "IS NOT "
} supported,`;
content += `${result.smooth ? " IS " : " is NOT "} smooth, and`;
content += `${
result.powerEfficient ? " IS " : " IS NOT "
}power efficient.`;
const ul = document.getElementById("results");
li.textContent = content;
ul.appendChild(li);
})
.catch((error) => {
const li = document.createElement("li"),
ul = document.getElementById("results");
li.textContent = `Codec ${mc.videoConfiguration.video.contentType} threw an error: ${error}`;
ul.appendChild(li);
});
},
};
document.getElementById("try-it").addEventListener("click", mc.tryIt);
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
Using_the_Media_Capabilities_API |
66 | 79 | 63 | 53 | 13 | 66 | 63 | 48 | 13 | 9.0 | 66 | 13 |
decodingInfo |
66["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
79["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
63["Thewebrtc value of the type option is named transmission.", "Before Firefox 101, decodingInfo() ignored codecs parameter options for av01 codecs (treating them as av1)."] |
53["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
13 | 66["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
63["Thewebrtc value of the type option is named transmission.", "Before Firefox for Android 101, decodingInfo() ignored codecs parameter options for av01 codecs (treating them as av1)."] |
48["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
13 | 9.0["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
66["codecs string can contain any subset of optional parameters (should be all or none).", "Errors if codecs string contains unexpected characters (should evaluate string up to character)."] |
13 |
encodingInfo |
101 | 101 | 63Thewebrtc value of the type option is named transmission. |
87 | 15.4 | 101 | 63Thewebrtc value of the type option is named transmission. |
70 | 15.4 | 19.0 | 101 | 15.4 |
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Media_Capabilities_API/Using_the_Media_Capabilities_API