Audio player

Native audio playback for remote files and generated speech, with composable controls, bounded skip seeking, volume, and recoverable errors.

Two tones

Eight seconds: a low tone followed by a higher tone. No speech.

Compose audio playback

Generated audio playback

Eight seconds: a low tone followed by a higher tone. No speech.

This example plays a local eight-second tone file through the same base64 and mediaType adapter used for generated speech. Supply a transcript for spoken content. Replace the controls through useAudioPlayer when the surrounding interface needs a different composition.

Use it for

  • Supply src for a file or data with base64 and an audio mediaType for generated speech.
  • The default controls support play, pause, skip backward and forward, seeking, mute, and volume.
  • Replace children with AudioPlayerControls or application controls using useAudioPlayer inside the player.
  • Supply a readable transcript for spoken content. Provider generation and authorization remain application-owned.
  • The forwarded ref reaches the native audio element; onTimeChange can synchronize Transcription.
  • Source changes stop the old element and discard stale playback results. CSS-only markup uses native audio controls.

Avoid

  • Autoplaying generated speech without user activation.
  • Treating this component as a speech generation API.

React package

npm install @noorddev/vlak-react

Load the stylesheet once at your app root, then import the components you use.

import "@noorddev/vlak-react/css";
import { AudioPlayer, AudioPlayerControls, type GeneratedSpeechAudio } from "@noorddev/vlak-react";

Per-component imports are available at @noorddev/vlak-react/components/audio-player.

Copy the source

npx @noorddev/vlak-cli add audio-player

Adds the component and its dependencies to components/vlak/. Follow the StyleX setup to compile the source in your application.

shadcn registry

npx shadcn add https://vlak.dev/r/audio-player.json

Installs the same source through the shadcn CLI.

import { AudioPlayer, AudioPlayerControls, type GeneratedSpeechAudio } from "@noorddev/vlak-react";

export function SpokenBrief({ speech, transcript }: { speech: GeneratedSpeechAudio; transcript: string }) {
  return <AudioPlayer title="Spoken brief" data={speech} transcript={transcript}>
    <AudioPlayerControls seekOffset={5} />
  </AudioPlayer>;
}

See the integration example to compose these components with your application's model and data.

AudioPlayer

Native audio for URLs or generated speech, with replaceable controls and explicit media ownership.

PropTypeDefaultDescription
titlerequiredstring
srcstring
dataGeneratedSpeechAudio
transcriptReactNode
preload"none" | "metadata" | "auto""metadata"
onTimeChange(seconds: number) => void
onPlayingChange(playing: boolean) => void

Also accepts HTMLAttributes<HTMLDivElement>.

The ref reaches HTMLAudioElement.

AudioPlayerControls

Default transport, bounded skip seeking and volume; replace or compose with useAudioPlayer.

PropTypeDefaultDescription
seekOffsetnumber10
disabledbooleanfalse

Also accepts HTMLAttributes<HTMLDivElement>.

The ref reaches HTMLDivElement.

useAudioPlayer (hook)

Access the native media controller from controls nested inside AudioPlayer.

KeysDoes
TabMoves through playback, seeking, and volume controls
Enter, SpaceActivates playback, skip, mute, or retry
Arrow keys, Home, EndAdjusts the focused native seek or volume range
  • The player is a region named by its title, and icon buttons have explicit accessible labels and 44px targets.
  • Playback failures use a status region and permit retry. Native events own playback state.
  • The subtle 1px frame uses 4px corners; focus and forced-colors controls retain distinct outlines.

The same styles are available as CSS. Native HTML provides the static presentation; React or application code supplies state updates and actions.

npm install @noorddev/vlak
import "@noorddev/vlak/css";
<div class="rs-audio-player" role="region" aria-label="Spoken brief"><h3 class="rs-audio-player-heading">Spoken brief</h3><audio controls aria-label="Spoken brief" src="/brief.wav"></audio><p class="rs-audio-player-transcript">The brief is ready for review.</p></div>

Classes

.rs-audio-player.rs-audio-player-heading.rs-audio-player-controls.rs-audio-player-row.rs-audio-player-volume.rs-audio-player-status.rs-audio-player-transcript