MediaCapabilities: decodingInfo() 方法
MediaCapabilities
接口的 decodingInfo()
方法返回一个 Promise,该 Promise 会使用有关用户代理如何解码/显示具有给定配置的媒体的信息来完成。
已解析的对象包含三个布尔属性 supported
、smooth
和 powerefficient
,它们指示是否支持解码所描述的媒体,以及如果是,解码是否会平滑且节能。
该方法还可以用于测试用户代理对使用密钥系统解码媒体的功能,但前提是在主线程和安全上下文中调用。如果在 configuration.keySystemConfiguration
属性中传递的配置受支持用于解码数据,则已解析的 Promise 还将包含一个 MediaKeySystemAccess
对象,该对象可用于创建 MediaKeys
对象以设置加密播放。
注意: 使用此属性调用 decodingInfo()
可能会导致用户可见的效果,例如请求访问一个或多个系统资源的权限。因此,此函数应仅在应用程序准备好使用提供的配置创建和使用 MediaKeys
对象时调用。
语法
decodingInfo(configuration)
参数
configuration
-
一个对象,其中包含一个
type
属性,或者 一个video
或audio
属性,其中包含适当类型的配置,以及可选的keySystemConfiguration
(在解码使用密钥系统加密的媒体时)。type
-
正在测试的媒体类型。它可以取以下三个值之一
file
-
表示旨在用于普通文件播放的配置。
media-source
-
表示旨在用于
MediaSource
播放的配置。 webrtc
-
表示旨在使用
RTCPeerConnection
接收的配置(当设置了keySystemConfiguration
时不允许)。
video
-
视频媒体源的配置对象。它具有以下属性
audio
-
音频媒体源的配置对象。它具有以下属性
contentType
-
包含有效音频 MIME 类型的字符串,以及(可选)
codecs
参数。 channels
-
音频轨道使用的声道数。
bitrate
-
用于编码音频文件一秒钟的位数。
samplerate
-
构成音频文件一秒钟的音频样本数。
keySystemConfiguration
可选-
指定加密媒体的密钥系统配置的对象。
注意:
Navigator.requestMediaKeySystemAccess()
在其supportedConfigurations
参数中采用一些相同数据类型的数组。如果指定,则
type
必须为media-source
或file
(而不是webrtc
)。它具有以下属性keySystem
-
标识媒体密钥系统的字符串。例如
org.w3.clearkey
或com.widevine.alpha
。 initDataType
可选-
一个字符串,指示初始化数据格式的数据类型名称,例如
"cenc"
、"keyids"
和"webm"
。允许的名称在 加密媒体扩展初始化数据格式注册表 中定义。 distinctiveIdentifier
可选-
一个字符串,指示实现是否可以使用“独特标识符”(或独特永久标识符)来执行与从该配置创建的任何对象关联的任何操作。允许的值为
required
-
返回的对象必须支持此功能。
optional
-
返回的对象可能支持此功能。这是默认值
not-allowed
-
返回的对象不得支持或使用此功能。
persistentState
可选-
一个字符串,指示返回的对象是否必须能够持久化会话数据或任何其他类型的状态。允许的值为
required
-
返回的对象必须支持此功能。
optional
-
返回的对象可能支持此功能。这是默认值
not-allowed
-
返回的对象不得支持或使用此功能。当不允许持久化状态时,只能创建“临时”会话。
sessionTypes
可选-
一个字符串数组,指示必须支持的会话类型。允许的值包括
temporary
-
一个会话,其中许可证、密钥和与会话相关的记录或数据不会持久化。应用程序不需要管理此类存储。实现必须支持此选项,它是默认值。
persistent-license
-
一个会话,其中许可证(以及可能与会话相关的其他数据)将持久化。即使许可证被销毁,许可证和关联密钥的记录也会持久化,从而证明许可证及其包含的密钥不再可供客户端使用。
audio
可选-
与上面
audio
配置 关联的音频密钥系统轨道配置。如果设置,则audio
配置 也必须设置。encryptionScheme
-
与内容类型关联的加密方案,例如
cenc
、cbcs
、cbcs-1-9
。此值应由应用程序设置(它默认为null
,表示可以采用任何加密方案)。 robustness
-
与内容类型关联的鲁棒性级别。空字符串表示接受任何解密和解码内容类型的能力。
video
可选-
与上面
video
配置 关联的视频密钥系统轨道配置。如果设置,则video
配置 也必须设置。encryptionScheme
-
与内容类型关联的加密方案,例如
cenc
、cbcs
、cbcs-1-9
。此值应由应用程序设置(它默认为null
,表示可以采用任何加密方案)。 robustness
-
与内容类型关联的鲁棒性级别。空字符串表示接受任何解密和解码内容类型的能力。
返回值
一个 Promise
,使用包含以下属性的对象完成
supported
-
如果媒体内容可以解码,则为
true
。否则为false
。 smooth
-
如果媒体的播放可以在配置指定的帧速率下进行播放,而无需丢弃帧,则为
true
。否则为false
。 powerEfficient
-
如果媒体的播放将是节能的,则为
true
。否则为false
。 keySystemAccess
-
一个
MediaKeySystemAccess
,可用于创建MediaKeys
对象以设置加密播放,或者如果使用提供的配置不支持解码,则为null
。
浏览器会将支持的媒体配置报告为 smooth
和 powerEfficient
,直到记录了有关该设备的统计信息。所有受支持的音频编解码器都会将 powerEfficient
报告为 true。
异常
TypeError
-
如果传递给
decodingInfo()
方法的configuration
无效,则抛出此异常,原因可能是类型不是 video 或 audio、contentType
不是有效的编解码器 MIME 类型、媒体解码配置不是type
(file、media-source 或 webrtc)的有效值,或者传递给该方法的媒体配置中的任何其他错误,包括省略任何值。 InvalidStateError
DOMException
-
当
configuration.keySystemConfiguration
定义时,该方法在工作线程中被调用。 SecurityError
DOMException
-
该方法在安全上下文之外被调用,并且定义了
configuration.keySystemConfiguration
。
用法说明
与 Navigator.requestMediaKeySystemAccess() 的比较
decodingInfo()
和 Navigator.requestMediaKeySystemAccess()
方法(加密媒体扩展 API)反映了选择加密媒体解码配置的根本不同方法。
Navigator.requestMediaKeySystemAccess()
的配置参数采用可能的配置数组,并允许系统选择它认为合适的配置。
相比之下,decodingInfo()
每次只采用一个配置。预期调用者会多次执行 decodingInfo()
,从最优先的配置开始,并在找到满足应用程序要求(平滑、节能或两者兼而有之)的配置后停止。换句话说,选择决策权下放给了调用者。
示例
获取未加密媒体文件的解码信息
此示例显示如何为音频文件创建媒体配置,然后在 MediaCapabilities.decodingInfo()
中使用它。
//Create media configuration to be tested
const audioConfig = {
type: "file", // or 'media-source' or 'webrtc'
audio: {
contentType: "audio/ogg; codecs=vorbis", // valid content type
channels: 2, // audio channels used by the track
bitrate: 132700, // number of bits used to encode 1s of audio
samplerate: 5200, // number of audio samples making up that 1s.
},
};
// check support and performance
navigator.mediaCapabilities.decodingInfo(audioConfig).then((result) => {
if (result.supported) {
log(
`The audio configuration is supported${result.smooth ? ", smooth" : ", not smooth"}${result.powerEfficient ? ", power efficient" : ", not power efficient"}.`,
);
} else {
log("The audio configuration is not supported");
}
});
类似地,以下代码显示了视频文件的配置。
const videoConfig = {
type: "file",
video: {
contentType: "video/webm;codecs=vp8", // valid content type
width: 800, // width of the video
height: 600, // height of the video
bitrate: 10000, // number of bits used to encode 1s of video
framerate: 30, // number of frames making up that 1s.
},
};
// check support and performance
navigator.mediaCapabilities.decodingInfo(audioConfig).then((result) => {
if (result.supported) {
log(
`The video configuration is supported${result.smooth ? ", smooth" : ", not smooth"}${result.powerEfficient ? ", power efficient" : ", not power efficient"}.`,
);
} else {
log("The video configuration is not supported");
}
});
获取加密媒体的解码信息
此示例演示了如何使用 decodingInfo()
为加密内容选择媒体配置。
与前面的示例一样,我们定义了一个媒体配置,但这次我们使用 type
为 media-source
(而不是 file
),并指定音频和视频内容。我们还指定了一个简单的 keySystemConfiguration
。
const encryptedMediaConfig = {
type: "media-source", // or 'file'
audio: {
contentType: "audio/webm; codecs=opus",
channels: 2, // audio channels used by the track
bitrate: 132700, // number of bits used to encode 1s of audio
samplerate: 48000, // number of audio samples making up that 1s.
},
video: {
contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800, // width of the video
height: 600, // height of the video
bitrate: 10000, // number of bits used to encode 1s of video
framerate: 30, // number of frames making up that 1s.
},
keySystemConfiguration: {
keySystem: "org.w3.clearkey",
initDataType: "webm",
distinctiveIdentifier: "required",
},
};
在前面的示例中,我们使用了 promise 链式调用 来等待结果。在这里,我们选择使用 async
和 await
来等待结果,然后记录它。
getDecodingInfo(encryptedMediaConfig);
async function getDecodingInfo(mediaConfig) {
const result = await navigator.mediaCapabilities.decodingInfo(mediaConfig);
console.log(result);
if (!result.supported) {
log("This encrypted media configuration is not supported.");
return;
}
// keySystemAccess is returned if decoding encrypted media is supported
// This can be used to decrypt and playback the media
if (!result.keySystemAccess) {
log("Encrypted media support is not available.");
return;
}
log(
`The encrypted media configuration is supported${result.smooth ? ", smooth" : ", not smooth"}${result.powerEfficient ? ", power efficient" : ", not power efficient"}.`,
);
}
日志输出如下所示。
迭代加密媒体的解码信息
前面的示例演示了如何使用 decodingInfo()
获取单个配置的信息。实际上,该方法通常会以迭代的方式调用,并使用多个配置,选择第一个满足应用程序对流畅播放或能耗要求的支持的配置。工作原理如下所示。
假设我们已经有一个名为 orderedMediaConfigs
的媒体配置 Array
,我们已经按最想要到最不想要的方式排序,我们可以使用 Array.prototype.map()
为每个配置调用 decodingInfo()
,并获得一个包含所有返回的 Promise
对象的数组。
const capabilitiesPromises = orderedMediaConfigs.map((mediaConfig) =>
navigator.mediaCapabilities.decodingInfo(mediaConfig),
);
然后,我们使用 for await...of
循环 迭代这些 promise,并在它们解析时进行处理。在循环中,我们将最后一个支持的配置存储到 nonSmoothConfig
中,并在找到流畅的配置后立即退出循环,将其设置为我们的 bestConfig
。
// Assume this app wants a supported && smooth config.
let bestConfig = null;
let nonSmoothConfig = null;
for await (const mediaCapabilityInfo of capabilitiesPromises) {
if (!mediaCapabilityInfo.supported) continue;
if (!mediaCapabilityInfo.smooth) {
nonSmoothConfig = mediaCapabilityInfo;
continue;
}
bestConfig = mediaCapabilityInfo;
break;
}
如果我们在循环中找到一个流畅且支持的配置 (bestConfig
),我们将使用它来 创建媒体密钥 并解码媒体。如果没有发现任何流畅的配置,我们可以使用 nonSmoothConfig
来解码媒体。这将是最后一个找到的支持的配置,由于我们对原始 orderedMediaConfigs
的排序方式,它应该是帧率最低的配置。
let keys = null;
if (bestConfig) {
keys = await bestConfig.keySystemAccess.createMediaKeys();
// ... use keys to decode media using best config
} else if (nonSmoothConfig) {
console.log(
"No smooth configs found. Using lowest resolution configuration!",
);
keys = await nonSmoothConfig.keySystemAccess.createMediaKeys();
// ... use keys to decode media using lowest framerate config
} else {
console.log("No supported configs!");
// Fail!
}
如果没有支持的配置,我们别无选择,只能失败并通知用户。
规范
规范 |
---|
媒体功能 # ref-for-dom-mediacapabilities-decodinginfo |
浏览器兼容性
BCD 表只在浏览器中加载