Skip to main content

Overview

Beat App integrates with the browser’s Media Session API, allowing you to control playback from:
  • Operating system media controls
  • Hardware media keys (keyboard, headphones)
  • Lock screen controls (mobile devices)
  • Notification center widgets
  • Browser toolbar media buttons
Media Session API support varies by browser. Works best in Chrome, Edge, and Safari on desktop and mobile.

Metadata Display

When a track plays, Beat App sends metadata to the system for display in media controls:
const updateMediaSessionMetadata = (track) => {
  if ("mediaSession" in navigator) {
    navigator.mediaSession.metadata = new MediaMetadata({
      title: track.title,
      artist: track.artists?.[0]?.name || "",
      album: track.album?.name || "",
      artwork: track.thumbnailUrl
        ? [
            {
              src: `${PROXY_URL}${track.thumbnailUrl}`,
              sizes: "512x512",
              type: "image/jpeg",
            },
          ]
        : [],
    });
  }
};
This displays:
  • Track title
  • Artist name
  • Album name
  • Album artwork (512x512px)
Metadata is automatically updated whenever you play a new track via playerActions.playTrack(), playNext(), or playPrevious().

Playback State

The Media Session API receives real-time playback state updates:
audioEl.onplay = () => {
  playerStore.setKey("isPlaying", true);
  if ("mediaSession" in navigator) {
    navigator.mediaSession.playbackState = "playing";
  }
};
This ensures system controls show the correct play/pause state.

Position State

Beat App reports playback position for accurate progress display in system controls:
audioEl.onloadedmetadata = () => {
  playerStore.setKey("duration", audioEl.duration);
  if ("mediaSession" in navigator && !isNaN(audioEl.duration) && audioEl.duration !== Infinity) {
    navigator.mediaSession.setPositionState({
      duration: audioEl.duration,
      playbackRate: audioEl.playbackRate,
      position: audioEl.currentTime,
    });
  }
};

Seeking Updates

Position state is also updated when seeking:
seekTo: (time) => {
  if (!isNaN(time) && isFinite(time)) {
    audioEl.currentTime = time;
    playerStore.setKey("currentTime", time);
    if ("mediaSession" in navigator && !isNaN(audioEl.duration) && audioEl.duration !== Infinity) {
      navigator.mediaSession.setPositionState({
        duration: audioEl.duration,
        playbackRate: audioEl.playbackRate,
        position: audioEl.currentTime,
      });
    }
  }
}
Position state is only set when duration is a valid number (not NaN or Infinity) to avoid browser errors.

Action Handlers

Beat App registers handlers for media control actions (src/stores/playerStore.js:209):
1

Play/Pause

Handle play and pause button presses:
navigator.mediaSession.setActionHandler("play", () => playerActions.togglePause());
navigator.mediaSession.setActionHandler("pause", () => playerActions.togglePause());
2

Track Navigation

Handle previous and next track buttons:
navigator.mediaSession.setActionHandler("previoustrack", () => playerActions.playPrevious());
navigator.mediaSession.setActionHandler("nexttrack", () => playerActions.playNext());
3

Seeking

Handle seek bar interactions:
navigator.mediaSession.setActionHandler("seekto", (details) => {
  if (details.fastSeek && "fastSeek" in audioEl) {
    audioEl.fastSeek(details.seekTime);
    return;
  }
  playerActions.seekTo(details.seekTime);
});

Fast Seek Support

When available, Beat App uses the browser’s fast seek capability for smoother scrubbing:
if (details.fastSeek && "fastSeek" in audioEl) {
  audioEl.fastSeek(details.seekTime);
  return;
}
playerActions.seekTo(details.seekTime);
fastSeek() allows quicker seeking by approximating the target position instead of loading precise frame data.

Automatic Updates

Media metadata updates automatically when tracks change:
playTrack: async (track, newQueue = null) => {
  playerStore.setKey("currentTrack", track);
  audioEl.pause();
  updateMediaSessionMetadata(track); // Auto-update
  const audioUrl = await getAudioUrl(track.trackId);
  audioEl.src = audioUrl;
  audioEl.play();
}

Browser Compatibility

All Media Session features are wrapped in feature detection:
if ("mediaSession" in navigator) {
  // Media Session API is available
  navigator.mediaSession.metadata = new MediaMetadata({...});
  navigator.mediaSession.setActionHandler("play", handler);
}
This ensures Beat App works gracefully in browsers without Media Session support.

Supported Media Controls

Desktop

  • Keyboard media keys (Play, Pause, Next, Previous)
  • Browser toolbar controls
  • System media overlay (Windows, macOS)
  • Touch Bar controls (MacBook Pro)

Mobile

  • Lock screen controls
  • Notification shade widgets
  • Bluetooth headphone buttons
  • Car audio system controls

Implementation Details

Media Session setup happens when the player store mounts:
onMount(playerStore, () => {
  // Audio event listeners
  audioEl.onplay = () => { /* ... */ };
  audioEl.onpause = () => { /* ... */ };
  audioEl.onloadedmetadata = () => { /* ... */ };
  
  // Register Media Session handlers
  if ("mediaSession" in navigator) {
    navigator.mediaSession.setActionHandler("play", () => playerActions.togglePause());
    navigator.mediaSession.setActionHandler("pause", () => playerActions.togglePause());
    navigator.mediaSession.setActionHandler("previoustrack", () => playerActions.playPrevious());
    navigator.mediaSession.setActionHandler("nexttrack", () => playerActions.playNext());
    navigator.mediaSession.setActionHandler("seekto", (details) => {
      playerActions.seekTo(details.seekTime);
    });
  }
});
Action handlers are registered once when the app loads and remain active throughout the session.

Testing Media Controls

1

Desktop Testing

  1. Play a track in Beat App
  2. Minimize or switch tabs
  3. Use keyboard media keys or browser controls
  4. Verify playback responds correctly
2

Mobile Testing

  1. Play a track on mobile device
  2. Lock screen or switch apps
  3. Access media controls from lock screen/notification
  4. Test play, pause, next, and previous buttons
3

Metadata Verification

Check that system controls display:
  • Correct track title
  • Artist name
  • Album artwork
  • Accurate playback position

Common Use Cases

Listen to music while using other apps. Media controls remain accessible from:
  • System notification area
  • Lock screen
  • External devices

Next Steps

Music Playback

Learn about in-app player controls

Queue Management

Manage your playback queue

Build docs developers (and LLMs) love