Skip to content
Kura UI

Audio Waveform

beta

Canvas audio visualiser — live bars, mirrored history or oscilloscope line from a mic or media element, or recorded peaks with a seek scrubber.

@kura-ui/react/audio-waveformCopy page for agents.mdregistry.json

Simulated live input

minimal

Player with scrub, and every variant

Recorded peaks with play/pause, drag-to-seek and a timer; below, bars/spectrum, mirrored/history and line.

full
0:20
bars · spectrum
mirrored · history
line

Voice note in a chat bubble

A compact muted waveform with an icon-button play control.

composition
0:14
Voice note · transcribed

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/audio-waveform.json

Copies the source into components/kura/audio-waveform with its dependencies (kura-theme, kura-merge-refs, use-audio-analyser, use-reduced-motion, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • Show that the mic is live while dictating or talking to a voice agent (mirrored history).
  • Visualise playback of a model's spoken reply or an <audio> element (spectrum bars or line).
  • A recorded voice note / audio attachment with a played/unplayed split and drag-to-seek.

Reach for something else when

  • A complete dictation control with permissions, transcript and states — use voice-dictation (it renders this).
  • An ambient “the agent is speaking” blob — use agent-orb.
  • A non-audio progress indicator — use a progress bar or context-meter.

Props

PropTypeDefaultDescription
analyserAudioAnalyser—Live analyser from useAudioAnalyser. Share one between several visuals.
sourceMediaStream | HTMLMediaElement | null—Mic stream or media element to analyse internally when no analyser is passed.
simulateboolean | "speech" | "music" | "silence"—Synthetic data for docs, previews and pre-permission states.
peaksreadonly number[]—Static mode: amplitudes 0..1 of any length (resampled to the bar count). Build them with peaksFromSamples().
progressnumber—Playback position 0..1 in static mode; bars after it are faded.
onSeek(progress: number) => void—Turns the waveform into a seek slider (drag, click, arrow keys). Receives 0..1.
durationnumber—Duration in seconds for the slider's spoken value (“0:12 of 1:04”).
variant"bars" | "mirrored" | "line""mirrored"bars = bottom-aligned, mirrored = symmetric around the centre line, line = oscilloscope (live) or filled envelope (static).
display"history" | "spectrum"—Live data for bars/mirrored: history scrolls recent loudness right→left, spectrum shows frequency bands. Default: history for mirrored, spectrum for bars.
barWidthnumber3Bar width in CSS px.
barGapnumber2Gap between bars in CSS px.
minBarHeightnumber2Minimum bar height so silence reads as a dotted baseline.
tone"default" | "muted" | "accent""default"Colour from tokens: ink, subtle ink, or the jade signal (only for live AI listening — once per view).
activebooleantruePause the live animation; the last frame stays on screen.
labelstring—Accessible name. Default "Audio waveform", or "Seek" when onSeek is set.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. AudioWaveformRoot sized by CSS (default h-10 w-full). data-mode = live | static, data-variant, data-status (analyser status), data-scrubbing.data-slot="audio-waveform"

Accessibility

  • Role: img (display) or slider (with onSeek)
  • Display-only waveforms are role=img with a label; the canvas itself is aria-hidden.
  • With onSeek it is a focusable slider with aria-valuenow (0–100) and aria-valuetext (“0:12 of 1:04” when duration is set).
  • Colours come from tokens via currentColor, so contrast follows light/dark themes automatically.
  • Pair live waveforms with a text status (“Listening”, “Muted”) — the visual alone is not an accessible state.
  • Reduced motion: Live data becomes a calm level meter redrawn ~6×/s without sub-frame scrolling; static waveforms are unaffected.
KeysAction
ArrowRight / ArrowUpSeek forward 5% (Shift: 10%)
ArrowLeft / ArrowDownSeek back 5% (Shift: 10%)
Home / EndStart / end

Notes for agents

  • Size it with CSS (className="h-8 w-48"); the canvas tracks the element size and device pixel ratio automatically.
  • For a mic: const rec = useMediaRecorder(); <AudioWaveform source={rec.stream} />. For playback pass the <audio> element as source.
  • Pass one `analyser` to several visuals instead of creating an analyser per component.
  • peaksFromSamples(audioBuffer.getChannelData(0), 200) turns decoded audio into peaks.
  • Use tone="accent" only while the AI is actively listening, and only once per view.