loading
Note:
This describes playback, it does not play anything A media session is metadata plus a remote control. Something else has to actually make sound - an <audio> element, WebAudio, a MediaStream - and most platforms only surface the session once audio is genuinely playing, so setting metadata on a silent page usually shows nothing.

Support check

IsSupported

Returns true when the runtime exposes navigator.mediaSession. During prerender/SSR the check returns false rather than throwing, so defer it to OnAfterRenderAsync.

C#
@inject Bit.Butil.MediaSession mediaSession

var supported = await mediaSession.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Play something, and describe it

SetMetadata / SetPlaybackState

SetMetadata is what the platform shows: title, artist, album and artwork. Offering several artwork sizes lets each surface pick what fits. SetPlaybackState keeps the system's play/pause icon in step with reality - set it on every play and pause, or the lock screen will disagree with your page.

C#
await mediaSession.SetMetadata(new MediaMetadata
{
    Title = "A test tone",
    Artist = "Bit.Butil",
    Album = "MediaSession demo",
    Artwork =
    [
        new MediaArtwork { Src = "images/cover-512.png", Sizes = "512x512", Type = "image/png" },
    ],
});

await mediaSession.SetPlaybackState(MediaSessionPlaybackState.Playing);
Live sample
Playback state None
metadata output
Results will appear here when you interact with the samples.

Hardware and lock-screen controls

SetActionHandler / ClearActionHandler

Registering a handler is also what makes the corresponding control appear on the platform. Engines implement different subsets, so SetActionHandler returns false for the ones this one doesn't know - which is the normal way to discover that SeekTo or the skip actions are unavailable. Try a media key on your keyboard, or the transport controls in your OS.

C#
var ok = await mediaSession.SetActionHandler(MediaSessionAction.Play, _ => Play());
await mediaSession.SetActionHandler(MediaSessionAction.Pause, _ => Pause());
await mediaSession.SetActionHandler(MediaSessionAction.NextTrack, _ => Next());

// seek actions carry their offset or target in the details:
await mediaSession.SetActionHandler(MediaSessionAction.SeekTo,
    details => SeekTo(details.SeekTime ?? 0));

await mediaSession.SetActionHandler(MediaSessionAction.SeekForward,
    details => SeekBy(details.SeekOffset ?? 10));

// remove a handler (and hide its control):
await mediaSession.ClearActionHandler(MediaSessionAction.NextTrack);
Live sample
action output
Results will appear here when you interact with the samples.

The scrubber

SetPositionState / ClearPositionState

Publishes duration, position and rate so the platform can draw an accurate progress bar and let the user seek from outside your page. It extrapolates between updates, so this needs calling when you seek or change rate - not once per frame. The position is clamped into the track's range here, because the spec throws when it overshoots the duration.

C#
await mediaSession.SetPositionState(
    durationSeconds: 240,
    positionSeconds: 37.5,
    playbackRate: 1);

// when playback ends entirely:
await mediaSession.ClearPositionState();
Live sample
position output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes navigator.mediaSession. Returns default (false) during prerender/SSR instead of throwing.
SetMetadata
ValueTask<bool> SetMetadata(MediaMetadata? metadata)
Describes the current track. Pass null to clear it. False when there is no media session, or the artwork was rejected.
SetPlaybackState
ValueTask SetPlaybackState(MediaSessionPlaybackState state)
None, Paused or Playing - what the platform's play/pause icon reflects.
SetPositionState
ValueTask<bool> SetPositionState(double durationSeconds, double positionSeconds, double playbackRate = 1)
Publishes the playback position for the platform's scrubber. Position is clamped into range; a rate of 0 is treated as 1.
ClearPositionState
ValueTask ClearPositionState()
Drops the published position, e.g. when playback stops entirely.
SetActionHandler
ValueTask<bool> SetActionHandler(MediaSessionAction action, Action<MediaSessionActionDetails> handler)
Handles a platform control, which is also what makes it appear. False when this engine doesn't implement that action. Registering twice replaces.
ClearActionHandler
ValueTask ClearActionHandler(MediaSessionAction action)
Removes a handler, which also hides the corresponding control.
DisposeAsync
ValueTask DisposeAsync()
On scope/circuit teardown, clears every handler this instance registered and resets the session.
MediaSessionActionDetails
Action, SeekTime, SeekOffset, FastSeek
SeekTime is the absolute target for SeekTo; SeekOffset is the step for the seek-by actions, and is null when the platform left the choice to you.
An unhandled error has occurred. Reload 🗙