Настраивайте мультимедийные уведомления и элементы управления воспроизведением с помощью API сеанса мультимедиа.

Как интегрироваться с аппаратными мультимедийными клавишами, настроить мультимедийные уведомления и многое другое.

Франсуа Бофор
François Beaufort

Чтобы пользователи знали, что в данный момент воспроизводится в их браузере, и управляли этим, не возвращаясь на страницу, на которой оно было запущено, был введен API сеанса мультимедиа. Это позволяет веб-разработчикам настраивать этот опыт с помощью метаданных в пользовательских медиа-уведомлениях, мультимедийных событиях, таких как воспроизведение, пауза, поиск, отслеживание изменений, а также событиях видеоконференций, таких как отключение/включение звука микрофона, включение/выключение камеры и завершение разговора. Эти настройки доступны в нескольких контекстах, включая медиацентры на настольных компьютерах, мультимедийные уведомления на мобильных устройствах и даже на носимых устройствах. Я опишу эти настройки в этой статье.

Скриншоты контекстов медиа-сессии.
Медиа-концентратор на настольном компьютере, мультимедийные уведомления на мобильном устройстве и носимом устройстве.

Об API медиасеанса

API сеанса мультимедиа предоставляет несколько преимуществ и возможностей:

  • Поддерживаются аппаратные медиа-ключи.
  • Мультимедийные уведомления настраиваются на мобильном устройстве, настольном компьютере и подключенном носимом устройстве.
  • Медиа-хаб доступен на рабочем столе.
  • Элементы управления мультимедиа на экране блокировки доступны на ChromeOS и мобильных устройствах.
  • Элементы управления окном «картинка в картинке» доступны для воспроизведения звука , видеоконференций и презентации слайдов .
  • Доступна интеграция помощника на мобильном телефоне.

Поддержка браузера

  • 73
  • 79
  • 82
  • 15

Источник

Несколько примеров проиллюстрируют некоторые из этих положений.

Пример 1. Если пользователи нажимают мультимедийную клавишу «Следующая дорожка» на своей клавиатуре, веб-разработчики могут обрабатывать это действие пользователя независимо от того, находится ли браузер на переднем плане или на заднем плане.

Пример 2. Если пользователи слушают подкаст в Интернете, когда экран их устройства заблокирован, они все равно могут нажать значок «перейти назад» на элементах управления мультимедиа на экране блокировки, чтобы веб-разработчики переместили время воспроизведения назад на несколько секунд.

Пример 3. Если у пользователей есть вкладки, воспроизводящие аудио, они могут легко остановить воспроизведение из медиа-концентратора на рабочем столе, чтобы веб-разработчики имели возможность очистить свое состояние.

Пример 4. Если пользователи участвуют в видеозвонке, они могут нажать кнопку «переключить микрофон» в окне «Картинка в картинке», чтобы запретить веб-сайту получать данные с микрофона.

Все это делается через два разных интерфейса: интерфейс MediaSession и интерфейс MediaMetadata . Первый позволяет пользователям контролировать все, что воспроизводится. Во-вторых, как вы сообщаете MediaSession , чем нужно управлять.

Для иллюстрации на изображении ниже показано, как эти интерфейсы связаны с конкретными элементами управления мультимедиа, в данном случае с медиа-уведомлением на мобильном устройстве.

Иллюстрация интерфейсов медиа-сессии.
Анатомия медиа-уведомления на мобильном телефоне.

Сообщите пользователям, что воспроизводится

Когда веб-сайт воспроизводит аудио или видео, пользователи автоматически получают мультимедийные уведомления либо в области уведомлений на мобильном телефоне, либо в медиа-центре на настольном компьютере. Браузер делает все возможное, чтобы отобразить соответствующую информацию, используя заголовок документа и самое большое изображение значка, которое он может найти. С помощью API Media Session можно настроить медиа-уведомление с использованием более обширных метаданных мультимедиа, таких как заголовок, имя исполнителя, название альбома и обложка, как показано ниже.

Chrome запрашивает «полный» фокус звука, чтобы отображать мультимедийные уведомления только тогда, когда продолжительность мультимедиа составляет не менее 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 будет использоваться при следующем запуске воспроизведения. Вот почему важно обновлять его при изменении источника воспроизведения мультимедиа, чтобы в медиа-уведомлении отображалась соответствующая информация.

Есть несколько вещей, которые следует отметить относительно метаданных мультимедиа.

  • Массив изображений уведомлений поддерживает URL-адреса больших двоичных объектов и URL-адреса данных.
  • Если обложка не определена и имеется изображение значка (указанное с помощью <link rel=icon> ) желаемого размера, мультимедийные уведомления будут использовать его.
  • Целевой размер изображения уведомления в Chrome для Android — 512x512 . Для бюджетных устройств это 256x256 .
  • Атрибут title HTML-элемента мультимедиа используется в виджете «Сейчас играет» macOS.
  • Если медиа-ресурс встроен (например, в iframe), информация API сеанса мультимедиа должна быть установлена ​​из встроенного контекста. См. фрагмент ниже.
<iframe id="iframe">
  <video>...</video>
</iframe>
<script>
  iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    ...
  });
</script>

Позвольте пользователям контролировать, что воспроизводится

Действие медиа-сеанса — это действие (например, «воспроизведение» или «пауза»), которое веб-сайт может обрабатывать для пользователей, когда они взаимодействуют с текущим воспроизведением мультимедиа. Действия аналогичны событиям и работают так же. Как и события, действия реализуются путем установки обработчиков соответствующего объекта, в данном случае экземпляра 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 , предоставленное в обработчике действий, представляет собой время в секундах, на которое нужно переместить время воспроизведения мультимедиа. Если оно не предусмотрено (например, 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.
});

Установить позицию воспроизведения

Точное отображение позиции воспроизведения мультимедиа в уведомлении так же просто, как установка состояния позиции в подходящее время, как показано ниже. Состояние позиции представляет собой комбинацию скорости воспроизведения мультимедиа, продолжительности и текущего времени.

Снимок экрана: элементы управления мультимедиа на экране блокировки в 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.
});

Демонстрация действий со слайдами

Когда пользователь помещает презентацию своих слайдов в окно «Картинка в картинке», браузер может отображать элементы управления для навигации по слайдам. Когда пользователь нажимает на них, веб-сайт обрабатывает их через API сеанса мультимедиа. Пример см. в примере «Представление слайдов» .

Предыдущий слайд

Действие "previousslide" указывает, что пользователь хочет вернуться к предыдущему слайду при представлении слайдов.

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

Поддержка браузера

  • 111
  • 111
  • Икс
  • Икс

Следующий слайд

Действие "nextslide" указывает, что пользователь хочет перейти к следующему слайду при представлении слайдов.

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

Поддержка браузера

  • 111
  • 111
  • Икс
  • Икс

Образцы

Ознакомьтесь с некоторыми образцами Media Session, в которых представлены работы Blender Foundation и Яна Моргенштерна .

Скринкаст, иллюстрирующий API сеанса мультимедиа.

Ресурсы