Audio Player
A composable audio player component system.
Loading...
<script lang="ts">
import * as AudioPlayer from "$lib/components/ui/audio/player/index.js";
</script>
<AudioPlayer.Root>
<AudioPlayer.ControlBar>
<AudioPlayer.Play />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay />
<AudioPlayer.Volume />
</AudioPlayer.ControlBar>
</AudioPlayer.Root> Installation
Install @lucide/svelte :
Copy and paste the following code into your project.
Setup
Wrap your app with AudioProvider at the root level. It powers everything behind the scenes—state, playback, events, retries, and preloading—so all audio components stay in sync.
First, wrap your app with AudioProvider at the root level:
<script lang="ts">
import { AudioProvider } from "$lib/components/ui/audio/provider/index.js";
let { children } = $props();
</script>
<AudioProvider tracks={initialTracks}>{@render children()}</AudioProvider> Usage
Use the component you need :
<script lang="ts">
import * as AudioPlayer from "$lib/components/ui/audio/player/index.js";
</script>
<AudioPlayer.Root>
<AudioPlayer.ControlBar>
<AudioPlayer.ControlGroup>
<AudioPlayer.SkipBack />
<AudioPlayer.Rewind />
<AudioPlayer.Play />
<AudioPlayer.FastForward />
<AudioPlayer.SkipForward />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay />
<AudioPlayer.TimeDisplay remaining />
<AudioPlayer.Volume />
</AudioPlayer.ControlGroup>
</AudioPlayer.ControlBar>
</AudioPlayer.Root> Stacked Layout
A player with stacked variant, showing time displays above and below the seek bar.
Loading...
<script lang="ts">
import * as AudioPlayer from "$lib/components/ui/audio/player/index.js";
</script>
<AudioPlayer.Root>
<AudioPlayer.ControlBar variant="stacked">
<AudioPlayer.ControlGroup>
<AudioPlayer.TimeDisplay />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay remaining />
</AudioPlayer.ControlGroup>
<AudioPlayer.ControlGroup>
<AudioPlayer.ControlGroup className="justify-between md:justify-start">
<AudioPlayer.SkipBack />
<AudioPlayer.Play />
<AudioPlayer.SkipForward />
</AudioPlayer.ControlGroup>
<AudioPlayer.Volume />
</AudioPlayer.ControlGroup>
</AudioPlayer.ControlBar>
</AudioPlayer.Root> Player with Queue
A full-featured player with queue management, shuffle, and repeat controls. Uses AudioPlayerControlGroup for flexible layout management.
Loading...
<script lang="ts">
import * as AudioPlayer from "$lib/components/ui/audio/player/index.js";
import {
AudioQueue,
AudioQueueRepeatMode,
AudioQueueShuffle
} from "$lib/components/ui/audio/queue/index.js";
</script>
<AudioPlayer.Root>
<AudioPlayer.ControlBar variant="stacked">
<AudioPlayer.ControlGroup>
<AudioPlayer.TimeDisplay />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay remaining />
</AudioPlayer.ControlGroup>
<AudioPlayer.ControlGroup>
<AudioPlayer.ControlGroup>
<AudioPlayer.SkipBack />
<AudioPlayer.Play />
<AudioPlayer.SkipForward />
</AudioPlayer.ControlGroup>
<AudioQueueShuffle />
<AudioQueueRepeatMode />
<AudioPlayer.Volume />
<AudioQueue />
</AudioPlayer.ControlGroup>
</AudioPlayer.ControlBar>
</AudioPlayer.Root> For more queue management options, see the Audio Queue documentation.
API Reference
AudioPlayer.Root
A styled container component for audio controls. This is a presentational wrapper that provides consistent styling. All audio components are self-contained and read state from the global store.
Props
Inherits all props from HTMLDivElement.
Example
<AudioPlayer.Root>{/* Your audio controls */}</AudioPlayer.Root> AudioPlayer.ControlBar
A container component that holds audio player controls. Use it to wrap your control components.
Props
Example
<AudioPlayer.ControlBar>
<AudioPlayer.Play />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay />
</AudioPlayer.ControlBar> Stacked Layout
<AudioPlayer.ControlBar variant="stacked">
<AudioPlayer.ControlGroup>
<AudioPlayer.TimeDisplay />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay remaining />
</AudioPlayer.ControlGroup>
</AudioPlayer.ControlBar> AudioPlayer.ControlGroup
A flexible wrapper component for grouping audio controls and managing flex layouts. Useful for creating custom layouts with flex-col, justify-between, etc.
Props
Example
<AudioPlayer.ControlBar variant="stacked">
<AudioPlayer.ControlGroup>
<AudioPlayer.TimeDisplay />
<AudioPlayer.SeekBar />
<AudioPlayer.TimeDisplay remaining />
</AudioPlayer.ControlGroup>
<AudioPlayer.ControlGroup class="justify-between">
<AudioPlayer.ControlGroup>
<AudioPlayer.SkipBack />
<AudioPlayer.Play />
<AudioPlayer.SkipForward />
</AudioPlayer.ControlGroup>
<AudioPlayer.Volume />
</AudioPlayer.ControlGroup>
</AudioPlayer.ControlBar> AudioPlayer.Play
A button that toggles play/pause state. Shows a loading spinner when buffering or loading, and automatically handles the Space bar keyboard shortcut.
Props
Keyboard Shortcuts: Automatically handles the Space bar to toggle play/pause when focus is on
document.body.
AudioPlayer.SkipBack
Navigates to the previous track. If the current track has played for more than 3 seconds, it restarts the current track instead.
Accepts class, size, and variant props (same as AudioPlayer.Play).
AudioPlayer.SkipForward
Navigates to the next track in the queue.
Accepts class, size, and variant props (same as AudioPlayer.Play).
AudioPlayer.Rewind
Seeks backward by 10 seconds. Disabled on live streams.
Accepts class, size, and variant props (same as AudioPlayer.Play).
AudioPlayer.FastForward
Seeks forward by 10 seconds. Disabled on live streams.
Accepts class, size, and variant props (same as AudioPlayer.Play).
AudioPlayer.SeekBar
A slider that shows playback progress and allows seeking. Locked and shows 100% for live streams.
Props
AudioPlayer.TimeDisplay
Displays the current playback time or remaining time.
Props
On live streams: the non-remaining display shows elapsed time, and the remaining display shows a pulsing LIVE badge with a Radio icon.
AudioPlayer.Volume
A dropdown button that opens a volume slider. Includes a mute toggle button inside the dropdown. Hidden on mobile (hidden md:flex).
Props
Notes
Important Information :
Component Architecture: All audio components are self-contained and read state directly from the global
audioStore— a Svelte 5 reactive class instance (using$statefields) defined inaudio-store.svelte.ts. The audio player uses the HTML5 audio element under the hood via thehtmlAudiosingleton fromhtml-audio.ts.AudioProvider Role: The
AudioProvidercomponent manages the audio element lifecycle by importing thehtmlAudiosingleton directly (no hook needed). It initialises theHTMLAudioElementinsideonMount, registers all playback event listeners via anAbortController(automatically cleaned up on destroy), handles error retries (up to 3 retries with exponential backoff), preloads the next track into a secondary muted<audio>element, and uses seven$effectrunes to reactively syncaudioStorestate changes (track changes, play/pause, seek, volume, mute, playback rate, and localStorage persistence) back to the audio element. It also restores the last playback position fromlocalStorageon mount.AudioProvideris required for all audio components to function correctly.Previous Button Behavior:
AudioPlayer.SkipBackrestarts the current track if it has been playing for more than 3 seconds, otherwise it navigates to the previous track in the queue.State Persistence:
audioStoreautomatically persists queue, current track, volume, playback rate, repeat mode, shuffle, insert mode, and playback position tolocalStorageunder the keyaudio:ui:store, restored on page reload.
Live Stream Limitations: Live streams disable seeking, rewind, fast-forward, and playback speed controls. The seek bar is locked at 100% progress, and the time display switches to a pulsing LIVE badge. Live streams are detected automatically via the HTML5 audio.duration value (Infinity or NaN).