Если вы разрабатываете веб‑плеер и хотите, чтобы на заблокированном экране iPhone (или в Центре управления) отображались кнопки для переключения треков, а не стандартные перемотки на 10 секунд назад/вперёд, то вам поможет Media Session API. Многие разработчики сталкиваются с тем, что по умолчанию iOS показывает именно кнопки перемотки, и их попытки добавить предыдущий/следующий трек не работают. В этой статье я расскажу, какой код нужно написать, чтобы добиться правильного поведения.
Содержание
Что такое Media Session API?
Media Session API — это стандартный веб‑интерфейс, который позволяет сайту взаимодействовать с медиа‑уведомлениями на устройстве. С его помощью можно управлять воспроизведением, отображать информацию о треке (название, исполнитель, обложка) и задавать действия для кнопок на заблокированном экране, в гарнитуре или на умных часах.
В частности, для iOS (начиная с версии 12.2) поддерживаются следующие действия:
play/pauseprevioustrack/nexttrackseekbackward/seekforward(перемотка на заданный интервал)- и другие
По умолчанию браузер Safari на iOS может показывать кнопки перемотки, если вы не задали обработчики для предыдущего/следующего трека. Но даже если вы зададите previoustrack и nexttrack, iOS всё равно может отображать перемотку, если не отключить явно seekbackward и seekforward.
Ключевой момент: отключение ненужных действий
Чтобы на заблокированном экране появились именно кнопки «предыдущий» и «следующий», необходимо:
- Установить обработчики для
previoustrackиnexttrack. - Удалить (или не устанавливать) обработчики для
seekbackwardиseekforward. - Убедиться, что медиа‑сессия активна (то есть хотя бы один раз вызвано воспроизведение и установлен
metadata).
Вот минимальный код, который решает задачу:
// Проверяем поддержку API if ('mediaSession' in navigator) { // Устанавливаем метаданные (название, исполнитель и т.д.) navigator.mediaSession.metadata = new MediaMetadata({ title: 'Название трека', artist: 'Исполнитель', album: 'Альбом', artwork: [{ src: 'cover.jpg', sizes: '512x512', type: 'image/jpeg' }] }); // Задаём действия для предыдущего и следующего треков navigator.mediaSession.setActionHandler('previoustrack', () => { // Ваш код: переключение на предыдущий трек console.log('Предыдущий трек'); }); navigator.mediaSession.setActionHandler('nexttrack', () => { // Ваш код: переключение на следующий трек console.log('Следующий трек'); }); // ВАЖНО: отключаем обработчики перемотки, чтобы они не отображались navigator.mediaSession.setActionHandler('seekbackward', null); navigator.mediaSession.setActionHandler('seekforward', null); }Почему это работает?
Браузер Safari на iOS анализирует, какие обработчики установлены через Media Session API. Если для
seekbackwardилиseekforwardзадана функция, он показывает кнопки перемотки. Если же эти обработчики отсутствуют (или явно удалены черезnull), но присутствуютprevioustrackиnexttrack, то он отображает соответствующие кнопки. Таким образом, явное удаление ненужных действий гарантирует нужный результат.Полный пример интеграции с плеером
Рассмотрим более полный пример, где у нас есть аудиоэлемент, плейлист и мы хотим, чтобы кнопки на заблокированном экране управляли переключением треков.
<audio id="audio" controls></audio> <button id="prev">⏮</button> <button id="playPause">▶</button> <button id="next">⏭</button><script> const audio = document.getElementById('audio'); const playlist = ['track1.mp3', 'track2.mp3', 'track3.mp3']; let currentIndex = 0; function loadTrack(index) { audio.src = playlist[index]; audio.load(); // Обновляем метаданные медиа-сессии updateMediaSession(playlist[index]); } function updateMediaSession(trackUrl) { if ('mediaSession' in navigator) { // Извлекаем имя файла для отображения const fileName = trackUrl.split('/').pop().replace('.mp3', ''); navigator.mediaSession.metadata = new MediaMetadata({ title: fileName, artist: 'Неизвестный исполнитель', album: 'Мой плейлист' }); } } function play() { audio.play(); } function pause() { audio.pause(); } function prev() { currentIndex = (currentIndex - 1 + playlist.length) % playlist.length; loadTrack(currentIndex); play(); } function next() { currentIndex = (currentIndex + 1) % playlist.length; loadTrack(currentIndex); play(); } // Инициализация первого трека loadTrack(0); // Связываем кнопки на странице document.getElementById('prev').addEventListener('click', prev); document.getElementById('next').addEventListener('click', next); document.getElementById('playPause').addEventListener('click', () => { audio.paused ? play() : pause(); }); // Настраиваем Media Session if ('mediaSession' in navigator) { navigator.mediaSession.setActionHandler('previoustrack', prev); navigator.mediaSession.setActionHandler('nexttrack', next); // Отключаем перемотку navigator.mediaSession.setActionHandler('seekbackward', null); navigator.mediaSession.setActionHandler('seekforward', null); // Также можно добавить обработчики play/pause (они обычно работают автоматически) navigator.mediaSession.setActionHandler('play', play); navigator.mediaSession.setActionHandler('pause', pause); } // Синхронизация состояния воспроизведения с медиа-сессией audio.addEventListener('play', () => { if ('mediaSession' in navigator) { navigator.mediaSession.playbackState = 'playing'; } }); audio.addEventListener('pause', () => { if ('mediaSession' in navigator) { navigator.mediaSession.playbackState = 'paused'; } }); audio.addEventListener('ended', next); </script>Важные нюансы
- HTTPS обязательно. Media Session API на iOS работает только на страницах, загруженных по HTTPS (исключение — localhost). Убедитесь, что ваш хостинг использует SSL‑сертификат.
- Метаданные должны быть установлены до первого воспроизведения. Лучше всего обновлять их при загрузке каждого трека.
- Не забывайте про
playbackState. Установкаnavigator.mediaSession.playbackState = 'playing'или'paused'помогает правильно отображать состояние кнопки Play/Pause на заблокированном экране. - iOS может кэшировать обработчики. Если вы уже пробовали другие варианты, возможно, потребуется перезагрузить страницу или даже очистить кэш Safari, чтобы изменения вступили в силу.
- Поддержка других платформ. Этот код также будет работать на Android (Chrome) и в десктопных браузерах, где медиа-уведомления тоже поддерживаются.
Заключение
Добавление кнопок «предыдущий трек» и «следующий трек» на заблокированный экран iOS для веб‑плеера сводится к правильному использованию Media Session API. Главный секрет — явно удалить обработчики перемотки (seekbackward и seekforward), установив их в null, и задать обработчики для previoustrack и nexttrack. После этого iOS будет отображать именно те кнопки, которые нужны вашему плееру.
Надеюсь, эта статья помогла вам разобраться. Если остались вопросы — пишите в комментариях!