Audio Scrub Player
A composable scrubbable audio player for local Blob/object-URL audio — play/pause, a draggable seek bar, and a duration readout. Ships a standalone ScrubBar.
Audio Scrub Player
Audio Scrub Player is a composable scrubbable player for local Blob / object-URL audio such as Kokoro TTS output (useSynthesizeSpeech) or a recording. It provides play/pause, a draggable seek bar, and a time/duration readout, and manages its own <audio> element and object-URL lifecycle. The draggable ScrubBar is exported standalone for reuse over any time-based source.
When to use it: play back a locally-synthesized or recorded clip with precise scrubbing — without the inconsistent look of native <audio controls>.
Preview
Installation
pnpm dlx shadcn@latest add @localmode/ui/audio/audio-scrub-playernpx shadcn@latest add @localmode/ui/audio/audio-scrub-playeryarn dlx shadcn@latest add @localmode/ui/audio/audio-scrub-playerbunx --bun shadcn@latest add @localmode/ui/audio/audio-scrub-playerData source & dependencies
Data source: plays any Blob / object-URL you pass — works with any backend. Recommended producer: useSynthesizeSpeech output (local Blob) from @localmode/react (on-device, optional).
@localmode/ui/lib/browser-utils—useObjectUrlfor Blob lifecycle (installed automatically as a registry dependency)clsx+tailwind-merge— via the sharedcn()util- No external player dependency — native
<audio>+ custom controls
Files installed
audio-scrub-player.tsx—AudioScrubPlayer+ScrubBarlib/browser-utils.ts— generic browser helpers (useObjectUrl)lib/utils.ts— thecn()helper (if not already present)
Props
AudioScrubPlayer
Prop
Type
ScrubBar
Prop
Type
Examples
Play Kokoro output
import { AudioScrubPlayer } from '@/components/audio-scrub-player';
import { useSynthesizeSpeech } from '@localmode/react';
import { transformers } from '@localmode/transformers';
export function Speak({ text }: { text: string }) {
const { data, execute } = useSynthesizeSpeech({
model: transformers.textToSpeech('onnx-community/Kokoro-82M-v1.0-ONNX'),
});
return (
<>
<button onClick={() => execute(text)}>Synthesize</button>
{data && <AudioScrubPlayer audio={data.audio} />}
</>
);
}Use the standalone ScrubBar
import { ScrubBar } from '@/components/audio-scrub-player';
<ScrubBar currentTime={time} duration={duration} onSeek={setTime} />Customization
AudioScrubPlayer owns its <audio> and reads duration / currentTime from the media events, so it works with any decodable Blob or URL. ScrubBar is controlled (pointer + keyboard, with ArrowLeft/ArrowRight for ±5s) — drop it into your own player shell if you need a different layout. The progress fill uses bg-primary; the thumb uses border-primary / bg-background.
Mic Selector
A microphone input-device picker with permission handling and live device enumeration — fully offline, browser device APIs only.
Synced Transcript Viewer
A karaoke-style transcript viewer that highlights words in lockstep with audio playback using word-level timestamps — click a word to seek.