setMediaSession
Hand one sound to the operating system's media controls. That puts a title and cover art on a phone's lock screen and in the notification shade, and makes the play/pause key on a keyboard and the buttons on a headset control your audio. Reach for it with anything long, like a podcast, an audiobook or a radio stream.
setMediaSession(id: string, info?: MediaSessionInfo): void;
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
id | string | required | The sound or stream the controls should drive. |
info | MediaSessionInfo | {} | Metadata, skip offsets and track callbacks, see below. |
MediaSessionInfo
export interface MediaSessionInfo {
title?: string;
artist?: string;
album?: string;
artwork?: { src: string; sizes?: string; type?: string }[];
seekBackwardOffset?: number;
seekForwardOffset?: number;
onPreviousTrack?: () => void;
onNextTrack?: () => void;
}
| Property | Type | Default | Description |
|---|---|---|---|
title | string | '' | The main line. |
artist | string | '' | Shown underneath. |
album | string | '' | Shown on some platforms. |
artwork | { src, sizes?, type? }[] | [] | Cover images. At least one 512x512 image works best everywhere. |
seekBackwardOffset | number | 15 | Seconds the skip-back button jumps. |
seekForwardOffset | number | 30 | Seconds the skip-forward button jumps. |
onPreviousTrack | () => void | none | Wires the previous-track button. Leave it out and the button is not shown. |
onNextTrack | () => void | none | Wires the next-track button. |
MediaSessionInfo is exported from soundhub as a type.
Returns
Nothing.
Example
import { SoundHub } from 'soundhub';
const soundHub = new SoundHub();
await soundHub.loadStream('episode-42', '/audio/episode-42.mp3');
soundHub.play('episode-42');
soundHub.setMediaSession('episode-42', {
title: 'Episode 42: naming things',
artist: 'The Podcast',
album: 'Season 3',
artwork: [
{ src: '/cover-192.png', sizes: '192x192', type: 'image/png' },
{ src: '/cover-512.png', sizes: '512x512', type: 'image/png' },
],
onNextTrack: () => playEpisode(43),
onPreviousTrack: () => playEpisode(41),
});
What it wires up
| Control | What happens |
|---|---|
| Play | resume if the sound is paused, otherwise play from the start |
| Pause | pause |
| Stop | stop |
| Skip backward | seek back by seekBackwardOffset, never before 0 |
| Skip forward | seek forward by seekForwardOffset |
| Scrubber | seek to the dragged position |
| Previous and next | Your onPreviousTrack and onNextTrack, if you passed them |
Good to know
- Only one sound owns the media controls. Calling it again, for the same id or another one, takes over the controls. Call it with new metadata when the track changes; you do not need
clearMediaSessionin between. - Metadata is only replaced when you pass at least one of
title,artist,albumorartwork. Otherwise what was already on the lock screen stays. - The playback state and scrubber position follow every event the hub dispatches for this id. Progress events keep the scrubber moving; they are on by default through
trackProgressinSoundHubConfig. - When the operating system sends its own skip distance, that is used instead of
seekBackwardOffsetorseekForwardOffset. - Media Session is in current Chrome, Edge, Firefox and Safari, on desktop and mobile. Where it is missing, the method logs a line in debug mode and returns. Your audio plays as normal.
See also
clearMediaSession: take the sound off the media controls.loadStream: stream long audio instead of decoding it all.getStreamElement: the stream's audio element.