運用 Media Session API 自訂媒體通知和播放控制項

如何整合硬體媒體鍵、自訂媒體通知等。

François Beaufort
François Beaufort

讓使用者知道瀏覽器目前播放的內容並控製播放功能 而沒有返回啟動該 API 的網頁 。網頁程式開發人員可以透過 中繼資料,或是播放、暫停等媒體事件 跳轉、追蹤變更及視訊會議等活動,例如忽略/取消靜音 麥克風、開啟/關閉攝影機,以及掛斷電話。這些自訂功能 可在電腦媒體中心、媒體通知等多種情境下使用 甚至在穿戴式裝置上我將說明 這篇文章。

媒體工作階段環境的螢幕截圖。
電腦的媒體中心、行動裝置上的媒體通知,以及穿戴式裝置。

關於 Media Session API

Media 工作階段 API 提供多項優點和功能:

  • 支援硬體媒體金鑰。
  • 媒體通知會在行動裝置、電腦和配對的穿戴式裝置上自訂。
  • 您可以在電腦上使用媒體中心
  • 螢幕鎖定媒體控制項適用於 ChromeOS 和行動裝置。
  • 子母畫面視窗控制選項適用於音訊播放視訊會議播放簡報
  • 在行動裝置上使用 Google 助理整合功能。

瀏覽器支援

  • Chrome:73.
  • Edge:79,
  • Firefox:82。
  • Safari:15。

資料來源

以下幾個例子說明瞭其中幾個重點。

範例 1:如果使用者按下「下一首曲目」按下鍵盤的媒體鍵 無論瀏覽器是否在前景執行,網頁程式開發人員都能處理這項使用者動作 或是背景工作

範例 2:使用者利用裝置在網路上收聽 Podcast 螢幕鎖定時,仍然可以按下「向後倒轉」鎖定圖示 讓網頁程式開發人員將播放時間往後調 秒內請求驗證碼。

範例 3:如果使用者的分頁正在播放音訊,很容易就能夠停止播放 從桌機的媒體中心播放,網頁程式開發人員就能 清除自己的狀態

範例 4:如果使用者正在進行視訊通話,可以按下「切換」 麥克風」,在子母畫面視窗中 正在接收麥克風資料。

全部透過兩個不同的介面完成:MediaSession 介面 和 MediaMetadata 介面前者可讓使用者控制 資訊。其二是告知 MediaSession 需要控制的項目。

為方便您說明,下圖呈現這些介面如何與特定介面關聯 媒體控制項中,在這個範例中就是行動裝置的媒體通知。

媒體工作階段介面的插圖。
行動裝置的媒體通知剖析。

讓使用者知道現在正在播放什麼內容

網站播放音訊或影片時,使用者會自動取得媒體 通知匣顯示在行動裝置的通知匣或媒體中心 電腦。當瀏覽器使用 文件的標題及最大的圖示圖片。媒體工作階段 API,您可以用更豐富的媒體來自訂媒體通知 中繼資料,例如標題、藝人姓名、專輯名稱和封面,如下所示。

Chrome 要求「完整」權限音訊焦點,只在 媒體時間長度為至少 5 秒。這可確保隨附音效 例如 dings 不會顯示通知

// 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 for 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 (在此例中)。有些動作會在使用者按下 透過耳機、另一個遠端裝置、鍵盤或與 媒體通知。

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.`);
}

設定完成後,媒體工作階段動作處理常式會透過媒體播放持續顯示。 這與事件監聽器的模式類似,差別只在於處理事件 表示瀏覽器會停止執行任何預設行為 信號代表網站支援媒體動作因此,媒體動作控制項 必須設定適當的動作處理常式,才會顯示。

macOS Big Sur 中「聽聲辨曲」小工具的螢幕截圖。
macOS Big Sur 的「聽聲辨曲」小工具。

播放 / 暫停

"play" 動作表示使用者想要繼續播放媒體 "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 值是以秒為單位 來移動媒體播放時間如未提供 ID (例如 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 值是以秒為單位 切換媒體播放時間

如果動作是 true,動作處理常式中提供的 fastSeek 布林值即為 true 若是序列中多次呼叫的,而這並非最後呼叫 依序排列

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.
});

設定播放位置

在通知中準確顯示媒體播放位置非常簡單 以在適當的時間設定位置狀態,如下所示。 位置狀態是由媒體播放速率、時間長度和 。

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);

視訊會議動作

當使用者將視訊通話新增至子母畫面視窗時, 瀏覽器可能會顯示麥克風和攝影機的控制項,以及結束通話的控制選項。 當使用者點選這些項目時,網站會透過影片處理 會議通訊動作。如需範例,請參閱視訊會議範例

子母畫面視窗中的視訊會議控制項螢幕截圖。
在子母畫面視窗中進行視訊會議控制項。
,瞭解如何調查及移除這項存取權。

切換麥克風

"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.
  • Edge:111。
  • Firefox:不支援。
  • Safari:不支援。

下一張投影片

"nextslide" 動作表示使用者想前往下一張投影片 進行示範

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

瀏覽器支援

  • Chrome:111.
  • Edge:111。
  • Firefox:不支援。
  • Safari:不支援。

範例

查看一些主打 Blender FoundationMedia Session 範例的範例 Jan Morgenstern 的研究

說明 Media Session API 的螢幕側錄。

資源