Media Session APIでメディア通知をカスタマイズする

UI開発者 古川

Media Session APIは、メディアを再生したときに表示されるメディア通知をカスタマイズするAPIです。具体的には、メディア通知に表示されるメタデータと、再生・一時停止・シークなどのメディアイベント発生時の動作をカスタマイズできます。

今回はMedia Session APIの概要と実装のポイントを紹介します。

(サポート状況の詳細はBrowser compatibilityを参照してください)

メディア通知とは

メディア通知とは、動画や音声などのメディアを再生している間に表示される、再生ボタンなどの操作機能がある通知を指します。例えば以下のキャプチャのように、Webページ上でメディアを再生する際に表示されるものです。

Androidで表示されているメディア通知のキャプチャ

デフォルトでは再生ボタンと一時停止ボタンが表示されます。Media Session APIを用いることで、再生ボタンに加えて再生位置の移動などのインターフェースやメタデータの表示を行うことが可能です。

Androidで表示されているMedia Session APIを適用させたメディア通知のキャプチャ

Google Chromeでの動作デモ

以下のキャプチャは、Webページにある動画に対しGoogle ChromeでMedia Settion APIを介して動画をコントロールしている様子のキャプチャです。

Google ChromeのMedia Hubからメディアの再生をコントロールしている様子

動画のコントロールは、キーボードなどのハードウェアのメディアキーや、Google ChromeであればMedia Hubからでも利用できます。またPicture in Pictureに表示されている動画もメディア通知から制御が可能です。

Windows 10のGoogle ChromeでMedia HubからPicture in Pictureを操作しているキャプチャ

以下に実装のポイントを抜粋します。実装方法の詳細はChromeが提供するMedia Session Samplesを参照してください。

※ 2020年3月現在Media Session APIは仕様策定中のため、以下に記載されている仕様は今後変更される可能性があります

Webページ上にあるメディアのメタデータをメディア通知に表示する

Media Sesstion APIにはMediaSessionMediaMetadataの2つの異なるインターフェイスがあります。MediaSessionインターフェイスはメディアの動作を制御するもので、MediaMetadataはメディア通知に表示するメタデータを提供するものです。

メタデータをメディア通知に表示するには、MediaMetadata.MediaMetadata()コンストラクタでメタデータのオブジェクトを作成し、navigator.MediaSession.metadataプロパティに設定します。

if ('mediaSession' in navigator){
    navigator.mediaSession.metadata = new MediaMetadata({
      src: './video/video.mp4',
      title: '夏の花火大会',
      artist: 'ミツエーリンクス',
      album: '季節のお気に入り動画',
      artwork: [
        { src: './images/icon-144.png', sizes: '144x144', type: 'image/png' },
        { src: './images/icon-192.png', sizes: '192x192', type: 'image/png' },
        { src: './images/icon-512.png', sizes: '512x512', type: 'image/png' },
      ]
    });
}

artworkはデバイス側が適したサイズを判定して表示します。デスクトップ版のGoogle Chromeでは512pxのサイズの画像が表示されるようです。

イベントハンドラーの設定と開放

MediaSession.setActionHandler()メソッドは、メディア通知上に表示されるコントローラーでの再生や一時停止などの操作のためのイベントハンドラーを設定できます。

navigator.mediaSession.setActionHandler('play', () => { /* ... */ });
navigator.mediaSession.setActionHandler('pause', () => { /* ... */ });
navigator.mediaSession.setActionHandler('previoustrack', () => { /* ... */ });
navigator.mediaSession.setActionHandler('nexttrack', () => { /* ... */ });
navigator.mediaSession.setActionHandler('seekbackward', () => { /* ... */ });
navigator.mediaSession.setActionHandler('seekforward', () => { /* ... */ });

MediaSession.setActionHandler()のイベントはサポート状況がブラウザによって異なるため、try-catch文などで実装を行うとブラウザサポート対応が容易になります。また、イベントハンドラーを削除したい場合は、nullを設定します。

navigator.mediaSession.setActionHandler('pause', null);

また、動画が再生されているかをメディア通知に伝えるにはMediaSession.playbackStateプロパティを利用します。値はnonepaused、もしくはplayingを指定します。

navigator.mediaSession.setActionHandler('play', play);
navigator.mediaSession.setActionHandler('pause', pause);

const play = async () => {
  await video.play();
  navigator.mediaSession.playbackState = "playing";
}

const pause = () => {
  video.pause();
  navigator.mediaSession.playbackState = "paused";
}

再生中の動画の位置やスピードの調整

MediaSession.setPositionState()は再生中のメディアに関する情報をメディア通知に提供するメソッドです。たとえばnavigator.mediaSession.setActionHandler()seekforwardイベントはメディア通知から動画の早送り操作を行った際にイベントを発火させることが可能ですが、メディア通知に表示している動画の再生状態や現在の再生位置は自動的にアップデートしません。そのためメディア通知にシークバーを表示している場合などはMediaSession.setPositionState()を実行する必要があります。

const updatePositionState = () => {
  if ("setPositionState" in navigator.mediaSession) {
    navigator.mediaSession.setPositionState({
      duration: video.duration,
      playbackRate: video.playbackRate,
      position: video.currentTime
    });
  }
}

navigator.mediaSession.setActionHandler('seekforward', (event) => {
  const skipTime = event.seekOffset || 10;

  video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
  updatePositionState();
});

また、再生位置などメディアの情報のリセットはnullを渡します。

navigator.mediaSession.setPositionState(null);

まとめ

Media Session APIを利用すれば、メディア通知上から操作できるオーディオプレイヤーの実装も容易になります。はやく実装が進んでほしいAPIの1つですね!