MediaCapabilities: decodingInfo() 方法

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2020 年 1 月⁩ 起,所有主流浏览器均已支持。

* 此特性的某些部分可能存在不同级别的支持。

注意:此功能在 Web Workers 中可用。

MediaCapabilities 接口的 decodingInfo() 方法返回一个 Promise,该 Promise 以关于用户代理如何解码/显示具有给定配置的媒体的信息来 fulfilled。

解析后的对象包含三个布尔属性 supportedsmoothpowerefficient,它们指示是否支持解码描述的媒体,如果支持,则指示解码是否会流畅且省电。

该方法还可以用于测试用户代理解码使用密钥系统编码的媒体的能力,但前提是在主线程和安全上下文中调用。如果 configuration.keySystemConfiguration 属性中传递的配置支持解码数据,则解析后的 Promise 还包括一个 MediaKeySystemAccess 对象,该对象可用于创建 MediaKeys 对象以设置加密播放。

注意:使用此属性调用 decodingInfo() 可能会导致用户可见的效果,例如请求访问一个或多个系统资源的权限。因此,应仅在应用程序准备好使用提供的配置创建和使用 MediaKeys 对象时调用此函数。

语法

js
decodingInfo(configuration)

参数

configuration

一个对象,其中包含一个 type 属性,并且一个 videoaudio 属性,其中包含相应类型的配置,以及一个可选的 keySystemConfiguration,用于解码使用密钥系统加密的媒体。

type

正在测试的媒体类型。这接受以下三种值之一:

文件

表示用于普通文件播放的配置。

media-source

表示用于 MediaSource 播放的配置。

webrtc

表示使用 RTCPeerConnection 接收的配置(当设置了 keySystemConfiguration 时不允许)。

video

视频媒体源的配置对象。它具有以下属性:

contentType

包含有效视频 MIME 类型以及(可选)codecs 参数的字符串。

width

视频的宽度。

height

视频的高度。

bitrate

用于编码视频文件一秒钟的比特数。

framerate

构成视频播放一秒钟的帧数。

audio

音频媒体源的配置对象。它具有以下属性:

contentType

包含有效音频 MIME 类型以及(可选)codecs 参数的字符串。

channels

音频轨道使用的通道数。

bitrate

用于编码音频文件一秒钟的比特数。

samplerate

构成音频文件一秒钟的音频样本数。

keySystemConfiguration 可选

指定加密媒体密钥系统配置的对象。

注意:Navigator.requestMediaKeySystemAccess() 在其 supportedConfigurations 参数中接受相同数据类型的数组。

如果指定,则 type 必须是 media-sourcefile(而不是 webrtc)。它具有以下属性:

keySystem

标识媒体密钥系统的字符串。例如 org.w3.clearkeycom.widevine.alpha

initDataType 可选

一个字符串,指示初始化数据格式的数据类型名称,例如 "cenc""keyids""webm"。允许的名称定义在 Encrypted Media Extensions Initialization Data Format Registry 中。

distinctiveIdentifier 可选

一个字符串,指示实现是否可能为从该配置创建的任何对象的任何操作使用“独特标识符”(或独特永久标识符)。允许的值为:

required

返回的对象必须支持此功能。

可选

返回的对象可能支持此功能。这是默认值。

not-allowed

返回的对象不得支持或使用此功能。

persistentState 可选

一个字符串,指示返回的对象是否能够持久化会话数据或任何其他类型的状态。允许的值为:

required

返回的对象必须支持此功能。

可选

返回的对象可能支持此功能。这是默认值。

not-allowed

返回的对象不得支持或使用此功能。仅当不允许持久化状态时,才能创建“临时”会话。

sessionTypes 可选

一个字符串数组,指示必须支持的会话类型。允许的值包括:

temporary

一个会话,其中许可证、密钥和会话记录或相关数据不会持久化。应用程序不需要管理此类存储。实现必须支持此选项,这是默认选项。

persistent-license

一个会话,其中许可证(以及可能与会话相关的其他数据)将得到持久化。即使销毁了许可证,许可证及其关联密钥的记录也会保留,这证明了该许可证及其包含的密钥客户端不再可用。

audio 可选

与上面的 audio 配置关联的音频密钥系统轨道配置。如果设置,则必须也设置 audio 配置

encryptionScheme

与内容类型相关的加密方案,例如 cenccbcscbcs-1-9。此值应由应用程序设置(默认为 null,表示可以使用任何加密方案)。

robustness

与内容类型相关的健壮性级别。空字符串表示可以接受任何解密和解码内容类型的能力。

video 可选

与上面的 video 配置关联的视频密钥系统轨道配置。如果设置,则必须也设置 video 配置

encryptionScheme

与内容类型相关的加密方案,例如 cenccbcscbcs-1-9。此值应由应用程序设置(默认为 null,表示可以使用任何加密方案)。

robustness

与内容类型相关的健壮性级别。空字符串表示可以接受任何解密和解码内容类型的能力。

返回值

一个 Promise,以一个包含以下属性的对象 fulfilled:

supported

如果媒体内容根本无法解码,则为 true。否则为 false

平滑

如果在不丢帧的情况下可以以配置中指定的帧率播放媒体,则为 true。否则为 false

powerEfficient

如果媒体播放将是省电的,则为 true。否则为 false

keySystemAccess

一个 MediaKeySystemAccess,可用于创建 MediaKeys 对象以设置加密播放,或者如果使用提供的配置不支持解码,则为 null

浏览器将报告支持的媒体配置为 smoothpowerEfficient,直到在该设备上记录了统计信息。所有支持的音频编解码器都将 powerEfficient 报告为 true。

异常

TypeError

如果传递给 decodingInfo() 方法的 configuration 无效,则抛出此异常,原因可能是类型不是 video 或 audio,contentType 不是有效的编解码器 MIME 类型,媒体解码配置不是 type(file、media-source 或 webrtc)的有效值,或者传递给方法的媒体配置中的任何其他错误,包括省略任何值。

InvalidStateError DOMException

当定义了 configuration.keySystemConfiguration 时,该方法在 worker 中调用。

SecurityError DOMException

该方法在安全上下文之外调用,并且定义了 configuration.keySystemConfiguration

用法说明

与 Navigator.requestMediaKeySystemAccess() 的比较

decodingInfo() 方法和 Encrypted Media Extensions APINavigator.requestMediaKeySystemAccess() 方法反映了选择加密媒体解码配置的基本不同的方法。

Navigator.requestMediaKeySystemAccess() 的配置参数接受一个可能的配置数组,并允许系统选择它认为合适的配置。

相比之下,decodingInfo() 一次只接受一个配置。预期调用者将多次执行 decodingInfo(),从最首选的配置开始,并在找到满足应用程序对流畅、省电或两者兼有的配置要求后立即停止。换句话说,选择决策被委托给了调用者。

示例

获取未加密媒体文件的解码信息

此示例演示了如何为音频文件创建媒体配置,然后在 MediaCapabilities.decodingInfo() 中使用它。

js
// 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");
  }
});

同样,下面的代码显示了视频文件的配置。

js
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(videoConfig).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() 为加密内容选择媒体配置。

与前面的示例一样,我们定义了一个媒体配置,但这次我们使用了 media-source(而不是 file)的 type,并指定了音频和视频内容。我们还指定了一个简单的 keySystemConfiguration

js
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 链来等待结果。在这里,我们选择使用 asyncawait 来等待结果,然后将其记录下来。

js
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.prototype.map() 为每个配置调用 decodingInfo(),并获得一个包含所有返回的 Promise 对象的数组。

js
const capabilitiesPromises = orderedMediaConfigs.map((mediaConfig) =>
  navigator.mediaCapabilities.decodingInfo(mediaConfig),
);

然后,我们使用 for await...of 循环来迭代解析的 Promise。在循环中,我们将最后一个支持的配置存储到 nonSmoothConfig,并在找到流畅的配置后立即退出循环,将其设置为 bestConfig

js
// 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 的方式,它应该是帧率最低的配置。

js
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!
}

如果没有支持的配置,我们将别无选择,只能失败并通知用户。

规范

规范
Media Capabilities
# dom-mediacapabilities-decodinginfo

浏览器兼容性

另见