The Media Capabilities API enables real time feedback about media playback to better enable adaptative streaming. It provides information about the audio and video decoding and encoding abilities of the device, exposing information such as whether a media configuration is supported and whether playback should be smooth and power efficient. In the future, it will provide access to display property information.
The MediaCapabilities
is published through the navigator.mediaCapabilities
and WorkerNavigator.mediaCapabilities
object.
If the object exists, the media capabilities interface is available. You can test for the presence of mediaCapabilities object 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. There are very specific ways to go about creating the configuration defined by the MediaDecodingConfiguration
dictionary.
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 VideoConfiguration
including values for thecontentType
, width
, height
, bitrate
, and framerate
:
contentType
muse be a valid video MIME type.width
and height
are the proportions of the video.bitrate
is the number of bits used to encode 1s of video.framerate
is the number of frames per one second of 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, and excluding the dimensions and framerate:
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 MediaEncodingConfiguration
, which requires the type of media being tested — 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 paramater of the MediaCapabilities.decodingInfo()
method to determine if a video matching this configuration would be decodable and if the playback would be smooth and power efficient.
var promise = navigator.mediaCapabilities.decodingInfo(videoConfiguration);
The decodingInfo()
and encodingInfo()
methods both return promises. Once the promises state is fulfilled, you can access the
Instead of the assigning the promise to a variable, we can post the values returned by the promise to console:
navigator.mediaCapabilities.decodingInfo(videoConfiguration).then(result => { console.log('This configuration is ' + (result.supported ? '' : 'not ') + 'supported, ' + (result.smooth ? '' : 'not ') + 'smooth, and ' + (result.powerEfficient ? '' : 'not ') + 'power efficient.') });
The response provided is defined by the MediaCapabilitiesInfo
interface.
In our video decoding example, a TypeError
would be raised if the media configuration passed to the decodingInfo()
method was invalid. The error can be due to the type
not being one of the two possible values, the contentType
not being a valid codec MIMME type, or invalid or omitted definitions required in the VideoConfiguration
.
navigator.mediaCapabilities.decodingInfo(videoConfiguration).then( console.log('It worked') ).catch(error => console.log('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/ogg; codecs=theora</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="tryit"></p> </form> <ul id="results"></ul>
let mc = { videoConfiguration : new Object(), tryit: function () { mc.createConfiguration(); mc.testit(); }, createConfiguration: function () { var 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: function () { let content = ''; navigator.mediaCapabilities.decodingInfo(mc.videoConfiguration).then(result => { var 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, ' + (result.smooth ? ' IS ' : ' is NOT ') + ' smooth, and' + (result.powerEfficient ? ' IS ' : ' IS NOT ') + 'power efficient.'; var ul = document.getElementById("results") li.innerHTML = content; ul.appendChild(li); }).catch((error) => { var li = document.createElement('li'), ul = document.getElementById("results"); li.innerText = 'Codec ' + mc.videoConfiguration.video.contentType + ' threw an error: ' + error; ul.appendChild(li); }); } } document.getElementById('tryit').addEventListener('click', mc.tryit);
Desktop | ||||||
---|---|---|---|---|---|---|
Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | |
Basic support | 66 | ? | 63 | ? | 55 | ? |
encodingInfo
|
67
|
? | 63 | ? | ? | ? |
decodingInfo
|
66 | ? | 63 | ? | 55 | ? |
Mobile | |||||||
---|---|---|---|---|---|---|---|
Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | iOS Safari | Samsung Internet | |
Basic support | 66 | 66 | ? | ? | 55 | ? | ? |
encodingInfo
|
67
|
67
|
? | ? | ? | ? | ? |
decodingInfo
|
66 | 66 | ? | ? | 55 | ? | ? |
© 2005–2018 Mozilla Developer Network and individual 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