使用 Media Session API 自定义媒体通知和播放控件

如何与硬件媒体键集成、自定义媒体通知等。

François Beaufort
François Beaufort

让用户知道并控制浏览器中当前播放的内容 没有返回启动它的页面, 推出它可让网站开发者 自定义媒体通知中的元数据、媒体事件(例如播放、暂停、 搜寻、跟踪更改和视频会议事件(例如静音/取消静音) 麦克风、开启/关闭摄像头,以及挂断电话。这些自定义选项 适用于多种环境,包括桌面媒体中心、媒体通知 甚至在穿戴式设备上。我将在 本文。

<ph type="x-smartling-placeholder">
</ph> 媒体会话上下文的屏幕截图。
桌面设备上的媒体中心、移动设备上的媒体通知以及穿戴式设备。

Media Session API 简介

Media Session API 具有多项优势和功能:

  • 支持硬件媒体键。
  • 在移动设备、桌面设备和配对的穿戴式设备上自定义媒体通知。
  • 媒体中心适用于桌面设备。
  • ChromeOS 和移动设备都支持锁定屏幕媒体控件。
  • 画中画窗口控件适用于音频播放视频会议演示幻灯片
  • 可在移动设备上集成 Google 助理。

浏览器支持

  • Chrome:73。 <ph type="x-smartling-placeholder">
  • Edge:79。 <ph type="x-smartling-placeholder">
  • Firefox:82。 <ph type="x-smartling-placeholder">
  • Safari:15。 <ph type="x-smartling-placeholder">

来源

我们将通过几个例子来说明其中一些要点。

示例 1:如果用户按下“下一首”媒体键 无论浏览器在前台运行,Web 开发者都可以处理此用户操作 或背景

示例 2:如果用户在使用设备上收听网页中的播客 但仍可以点击“快退”按钮锁形图标 屏幕媒体控件,可让网站开发者将播放时间向后调少一点 。

示例 3:如果用户的标签页正在播放音频,他们可以轻松地停止播放 以便网站开发者能够 清除其状态

示例 4:如果用户正在进行视频通话,可以按一下“切换开关” 麦克风”控制在画中画窗口中,以便阻止网站 正在接收麦克风数据。

这全部通过两个不同的接口完成:MediaSession 接口 和 MediaMetadata 接口。第一种方案让用户可以控制 。第二个是告诉 MediaSession 需要控制什么。

为了说明这一点,下图展示了这些接口如何与特定的 媒体控件,在本示例中为移动设备上的媒体通知。

<ph type="x-smartling-placeholder">
</ph> 媒体会话界面图示。
移动设备上的媒体通知详解。

让用户了解当前播放的内容

当网站播放音频或视频时,用户会自动获得媒体内容 在移动设备的通知栏中显示通知,或在媒体中心打开这些通知 。浏览器会使用 以及能够找到的最大图标图片。使用媒体会话 API 中,可以通过一些更丰富的媒体来自定义媒体通知 例如标题、音乐人姓名、专辑名称和海报图片,如下所示。

Chrome 请求“full”音频焦点,以便仅在 媒体时长至少为 5 秒。这样可以确保 不会显示通知

// After media (video or audio) starts playing
await document.querySelector("video").play();

if ("mediaSession" in navigator) {
  navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    artist: 'Rick Astley',
    album: 'Whenever You Need Somebody',
    artwork: [
      { src: 'https://via.placeholder.com/96',   sizes: '96x96',   type: 'image/png' },
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/192', sizes: '192x192', type: 'image/png' },
      { src: 'https://via.placeholder.com/256', sizes: '256x256', type: 'image/png' },
      { src: 'https://via.placeholder.com/384', sizes: '384x384', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  });

  // TODO: Update playback state.
}

播放结束后,无需“释放”作为 通知会自动消失。请注意 下次播放开始时将使用navigator.mediaSession.metadata 。因此,在播放媒体时 进行更改,以确保在媒体通知中显示相关信息。

关于媒体元数据,有几点需要注意。

  • 通知图形数组支持 blob 网址和数据网址。
  • 如果未定义海报图片,并且有所需尺寸的图标图片(使用 <link rel=icon> 指定),媒体通知将使用该图片。
  • Chrome(Android 版)中的通知图片目标尺寸为 512x512。对于 是 256x256
  • 媒体 HTML 元素的 title 属性用于“闻曲知音” macOS 微件。
  • 如果媒体资源是嵌入的(例如在 iframe 中),则 Media Session API 信息必须从嵌入式上下文进行设置。请参阅以下代码段。
<iframe id="iframe">
  <video>...</video>
</iframe>
<script>
  iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    ...
  });
</script>

您还可以向媒体元数据添加各个章节的信息,例如章节的标题、时间戳和屏幕截图。这样一来,用户便可以在媒体内容中导航。

navigator.mediaSession.metadata = new MediaMetadata({
  // title, artist, album, artwork, ...
  chapterInfo: [{
    title: 'Chapter 1',
    startTime: 0,
    artwork: [
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  }, {
    title: 'Chapter 2',
    startTime: 42,
    artwork: [
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  }]
});
ChromeOS 媒体通知中显示的章节信息。
ChromeOS 中带有章节的媒体通知。

允许用户控制播放内容

媒体会话操作是指网站可以执行的操作(例如“播放”或“暂停”)。 在用户与当前媒体播放互动时向其显示的句柄。操作包括 与事件类似,其工作方式与事件大致相同。与事件一样,操作也是 通过在适当的对象、 在此示例中为 MediaSession。有些操作会在用户点按 从耳机、其他远程设备或键盘上打开按钮,或 媒体通知

<ph type="x-smartling-placeholder">
</ph> Windows 10 中媒体通知的屏幕截图。
Windows 10 中的自定义媒体通知

由于某些媒体会话操作可能不受支持,因此建议您 请使用 try…catch 代码块。

const actionHandlers = [
  ['play',          () => { /* ... */ }],
  ['pause',         () => { /* ... */ }],
  ['previoustrack', () => { /* ... */ }],
  ['nexttrack',     () => { /* ... */ }],
  ['stop',          () => { /* ... */ }],
  ['seekbackward',  (details) => { /* ... */ }],
  ['seekforward',   (details) => { /* ... */ }],
  ['seekto',        (details) => { /* ... */ }],
  /* Video conferencing actions */
  ['togglemicrophone', () => { /* ... */ }],
  ['togglecamera',     () => { /* ... */ }],
  ['hangup',           () => { /* ... */ }],
  /* Presenting slides actions */
  ['previousslide', () => { /* ... */ }],
  ['nextslide',     () => { /* ... */ }],
];

for (const [action, handler] of actionHandlers) {
  try {
    navigator.mediaSession.setActionHandler(action, handler);
  } catch (error) {
    console.log(`The media session action "${action}" is not supported yet.`);
  }
}

取消设置媒体会话操作处理脚本只需将其设为 null 即可。

try {
  // Unset the "nexttrack" action handler at the end of a playlist.
  navigator.mediaSession.setActionHandler('nexttrack', null);
} catch (error) {
  console.log(`The media session action "nexttrack" is not supported yet.`);
}

设置后,媒体会话操作处理程序将在媒体播放期间持续有效。 这与事件监听器模式类似,不同之处在于它会处理事件 意味着浏览器停止执行任何默认行为, 表明网站支持媒体操作的信号。因此,媒体操作控件 。

<ph type="x-smartling-placeholder">
</ph> macOS Big Sur 中“闻曲知音”微件的屏幕截图。
macOS Big Sur 中的“闻曲知音”微件。

播放 / 暂停

"play" 操作表示用户想要继续播放媒体 而 "pause" 表示希望暂停投放。

“播放/暂停”图标始终显示在媒体通知中,而相关的 媒体事件由浏览器自动处理。覆盖其默认设置 行为,处理“播放”和“pause”媒体操作(如下所示)。

在查找或播放媒体内容时,浏览器可能会将网站视为 加载实例在这种情况下,您可以通过将 navigator.mediaSession.playbackState"playing""paused",以确保 网站界面会与媒体通知控件保持同步。

const video = document.querySelector('video');

navigator.mediaSession.setActionHandler('play', async () => {
  // Resume playback
  await video.play();
});

navigator.mediaSession.setActionHandler('pause', () => {
  // Pause active playback
  video.pause();
});

video.addEventListener('play', () => {
  navigator.mediaSession.playbackState = 'playing';
});

video.addEventListener('pause', () => {
  navigator.mediaSession.playbackState = 'paused';
});

上一首

"previoustrack" 操作表示用户想要启动 如果媒体播放的概念是 开始播放,或者移至播放列表中的上一项(如果媒体播放时) 播放列表的概念

navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Play previous track.
});

下一首

"nexttrack" 操作表示用户想要将媒体播放移至 播放列表中的下一项(如果媒体播放具有播放列表概念)。

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Play next track.
});

停止

"stop" 操作表示用户想要停止播放媒体,并且 清除状态。

navigator.mediaSession.setActionHandler('stop', () => {
  // Stop playback and clear state if appropriate.
});

快退 / 快进

"seekbackward" 操作表示用户想要移动媒体 将播放时间向后调一小段时间,而 "seekforward" 表示想要 将媒体播放时间向前移动一小段时间。在这两种情况下, “短”是指几秒

操作处理程序中提供的 seekOffset 值是执行以下操作(以秒为单位)的时间: 将媒体播放时间往后移动。如果未提供(例如 undefined),则 您应该使用合理的时间(例如 10-30 秒)。

const video = document.querySelector('video');
const defaultSkipTime = 10; /* Time to skip in seconds by default */

navigator.mediaSession.setActionHandler('seekbackward', (details) => {
  const skipTime = details.seekOffset || defaultSkipTime;
  video.currentTime = Math.max(video.currentTime - skipTime, 0);
  // TODO: Update playback state.
});

navigator.mediaSession.setActionHandler('seekforward', (details) => {
  const skipTime = details.seekOffset || defaultSkipTime;
  video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
  // TODO: Update playback state.
});

跳转至特定时间

"seekto" 操作表示用户想要移动媒体播放 特定时间

操作处理程序中提供的 seekTime 值是执行以下操作(以秒为单位)的时间: 将媒体播放时间移至。

如果操作是fastSeek 作为序列的一部分被多次调用,且这不是最后一次调用 序列。

const video = document.querySelector('video');

navigator.mediaSession.setActionHandler('seekto', (details) => {
  if (details.fastSeek && 'fastSeek' in video) {
    // Only use fast seek if supported.
    video.fastSeek(details.seekTime);
    return;
  }
  video.currentTime = details.seekTime;
  // TODO: Update playback state.
});

设置播放位置

在通知中准确显示媒体播放位置很简单 在适当的时间设置定位状态,如下所示。通过 位置状态是媒体播放速率、时长和 。

<ph type="x-smartling-placeholder">
</ph> ChromeOS 中锁定屏幕媒体控件的屏幕截图。
ChromeOS 中的锁定屏幕媒体控件

必须提供时长为正值。位置必须为正值, 短于时长。播放速率必须大于 0。

const video = document.querySelector('video');

function updatePositionState() {
  if ('setPositionState' in navigator.mediaSession) {
    navigator.mediaSession.setPositionState({
      duration: video.duration,
      playbackRate: video.playbackRate,
      position: video.currentTime,
    });
  }
}

// When video starts playing, update duration.
await video.play();
updatePositionState();

// When user wants to seek backward, update position.
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
  /* ... */
  updatePositionState();
});

// When user wants to seek forward, update position.
navigator.mediaSession.setActionHandler('seekforward', (details) => {
  /* ... */
  updatePositionState();
});

// When user wants to seek to a specific time, update position.
navigator.mediaSession.setActionHandler('seekto', (details) => {
  /* ... */
  updatePositionState();
});

// When video playback rate changes, update position state.
video.addEventListener('ratechange', (event) => {
  updatePositionState();
});

重置位置状态只需将其设置为 null 即可。

// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);

视频会议操作

当用户将其视频通话置于画中画窗口中时, 浏览器可能会显示麦克风和摄像头控件以及挂断电话的控件。 用户点击这些广告后,网站会通过视频对其进行处理 下面的视频会议操作。如需查看示例,请参阅视频会议示例

<ph type="x-smartling-placeholder">
</ph> 画中画窗口中视频会议控件的屏幕截图。
画中画窗口中的视频会议控件。

开启/关闭麦克风

"togglemicrophone" 操作表示用户想要静音或取消静音 麦克风。setMicrophoneActive(isActive) 方法会告知浏览器 确定网站当前是否将麦克风视为工作状态

let isMicrophoneActive = false;

navigator.mediaSession.setActionHandler('togglemicrophone', () => {
  if (isMicrophoneActive) {
    // Mute the microphone.
  } else {
    // Unmute the microphone.
  }
  isMicrophoneActive = !isMicrophoneActive;
  navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});

切换相机

"togglecamera" 操作表示用户想要启用 或关闭摄像头。setCameraActive(isActive) 方法可指示 浏览器会将网站视为处于活动状态。

let isCameraActive = false;

navigator.mediaSession.setActionHandler('togglecamera', () => {
  if (isCameraActive) {
    // Disable the camera.
  } else {
    // Enable the camera.
  }
  isCameraActive = !isCameraActive;
  navigator.mediaSession.setCameraActive(isCameraActive);
});

挂断

"hangup" 操作表示用户想要结束通话。

navigator.mediaSession.setActionHandler('hangup', () => {
  // End the call.
});

演示幻灯片操作

当用户将其幻灯片演示文稿放入画中画窗口时, 浏览器可能会显示用于浏览幻灯片的控件。当用户 点击这些后,网站会通过 Media Session API 对其进行处理。对于 请参阅演示幻灯片示例

上一张幻灯片

"previousslide" 操作表明用户想要返回 上一张幻灯片。

navigator.mediaSession.setActionHandler('previousslide', () => {
  // Show previous slide.
});

浏览器支持

  • Chrome:111。 <ph type="x-smartling-placeholder">
  • Edge:111。 <ph type="x-smartling-placeholder">
  • Firefox:不支持。 <ph type="x-smartling-placeholder">
  • Safari:不支持。 <ph type="x-smartling-placeholder">

下一张幻灯片

"nextslide" 操作表明用户想要转到下一张幻灯片 。

navigator.mediaSession.setActionHandler('nextslide', () => {
  // Show next slide.
});

浏览器支持

  • Chrome:111。 <ph type="x-smartling-placeholder">
  • Edge:111。 <ph type="x-smartling-placeholder">
  • Firefox:不支持。 <ph type="x-smartling-placeholder">
  • Safari:不支持。 <ph type="x-smartling-placeholder">

示例

查看一些介绍 Blender Foundation Jan Morgenstern 作品

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
说明 Media Session API 的抓屏。

资源