HTML Audio
The core HTMLAudio singleton for robust audio playback.
The htmlAudio singleton manages playback of HTML5 audio with automatic retry logic, event handling, and volume fading. Use it alongside the Audio Store for full player functionality.
Installation
Copy and paste the following code into your project.
Import
Import the singleton and helpers from the audio library:
<script lang="ts">
import {
htmlAudio,
formatDuration,
type Track,
} from "$lib/html-audio";
</script> Core API
The htmlAudio Singleton
Manages the underlying HTMLAudioElement, playback state, retries, and custom events. Initialize on client start — the instance is built to be server-safe.
import { htmlAudio } from "$lib/html-audio";
// Initialize on the client
htmlAudio.init();
// Load and play
await htmlAudio.load({ url: "https://example.com/audio.mp3", startTime: 0 });
await htmlAudio.play(); The htmlAudio singleton must be initialized on the client.
Call htmlAudio.init() inside onMount or an $effect so the underlying HTMLAudioElement is created only in the browser environment.
Lifecycle
Playback
Browser autoplay restrictions:
The play() call returns a promise which may be rejected by browser autoplay policies if there was no recent user gesture.
Make sure playback is initiated by a user interaction.
Live streams: For live streams (when isLiveStream is
true) seeking is disabled and longer timeouts (60s instead of 30s) are used carefully to handle stream buffering.
Volume
State
Events
The library emits custom events via an internal EventTarget. You can listen to these without messing with the raw <audio> element events:
htmlAudio.addEventListener("bufferingStart", () =>
console.log("Buffering...")
);
htmlAudio.addEventListener("bufferingEnd", () => console.log("Ready to play"));
htmlAudio.addEventListener("playbackStarted", () => console.log("Playing"));
htmlAudio.addEventListener("audioError", () => console.error("Error"));
htmlAudio.addEventListener("bufferUpdate", (e) => {
if (e instanceof CustomEvent)
console.log("Buffered:", e.detail.bufferedTime);
}); Utilities
formatDuration
Format seconds into an MM:SS string. Extremely handy for UI constraints. Handles invalid input gracefully.
import { formatDuration } from "$lib/html-audio";
console.log(formatDuration(125)); // "2:05"
console.log(formatDuration(3661)); // "61:01" htmlAudio.isLive
Check if a duration value indicates a live stream.
import { htmlAudio } from "$lib/html-audio";
const duration = htmlAudio.getDuration();
if (htmlAudio.isLive(duration)) {
// Disable scrubbers, hide fast-forward buttons, etc.
} Live Stream Detection: The isLive() method checks
if a duration isNaN,Infinity, or -Infinity. A duration of 0 just means the metadata hasn't loaded yet.
Types
Track
A versatile representation of an audio track to be used across your components:
Examples
Basic Playback
Just wire it up on mount.
<script lang="ts">
import { htmlAudio } from "$lib/html-audio";
import { onMount } from "svelte";
onMount(() => {
htmlAudio.init();
});
async function playTrack(url: string) {
try {
await htmlAudio.load({ url, startTime: 0 });
await htmlAudio.play();
} catch (error) {
console.error("Playback failed:", error);
}
}
</script>
<button onclick={() => playTrack("/music.mp3")}>Play Track</button> Volume Fading
Awesome polish feature: you can smoothly fade the volume instead of jarring the user.
import { htmlAudio } from "$lib/html-audio";
// Immediate jump
htmlAudio.setVolume({ volume: 0.5 });
// Smooth, butter-like fade over 1 second (1000ms)
htmlAudio.setVolume({ volume: 0.8, fadeTime: 1000 });
// Mute with memory (remembers previous volume when toggled back)
htmlAudio.setMuted(true);
htmlAudio.setMuted(false); Listening to Progress
<script lang="ts">
import { htmlAudio, formatDuration } from "$lib/html-audio";
import { onMount, onDestroy } from "svelte";
let time = $state(0);
onMount(() => {
const updateTime = () => {
time = htmlAudio.getCurrentTime();
};
// Poll the time roughly every frame
const interval = setInterval(updateTime, 100);
return () => clearInterval(interval);
});
</script>
<span>{formatDuration(time)}</span> Related
- Audio Store — A Svelte 5 global store wrapping this class to provide reactive state.
- Audio Provider — Composable provider that orchestrates
htmlAudioinside your layout. - Audio Player — Composable player UI components.
Notes
- Singleton pattern: All methods access the exact same
htmlAudioinstance behind the scenes. - Server-safe: Most methods (
getVolume(), etc) have built-inisClient()guards, so they won't blow up during SSR. - Resilience: It handles native HTML5
<audio>random error events entirely manually, throwing up to 3 retries under the hood before giving up. - Polished Fades: Built-in volume cross-fades use
getAnimationFrame/ timers for smooth transitions. Just supplyfadeTime.