Voice Orb
An animated canvas voice-agent orb that reflects discrete agent states and pulses with input/output volume via callbacks — visual state decoupled from the audio source.
Voice Orb
Voice Orb is an animated canvas visualizer for voice agents. It reflects discrete agent states (idle / connecting / listening / thinking / speaking / muted) and reacts to input/output audio volume through getInputVolume() / getOutputVolume() callbacks. Visual state is fully decoupled from the audio source — the orb reads volume through the callbacks, which you can feed from useVoiceRecorder().getVolume() (mic input) or a Web Audio AnalyserNode (e.g. on the TTS output node).
Drive state from useLiveTranscribe() / useTurnTaker() and getInputVolume from useVoiceRecorder().getVolume().
When to use it: the centerpiece of a hands-free voice-agent UI, showing the agent's state and "loudness" at a glance.
Preview
Installation
pnpm dlx shadcn@latest add @localmode/ui/audio/voice-orbnpx shadcn@latest add @localmode/ui/audio/voice-orbyarn dlx shadcn@latest add @localmode/ui/audio/voice-orbbunx --bun shadcn@latest add @localmode/ui/audio/voice-orbData source & dependencies
Data source: renders the state you pass and reads volume through callbacks — works with any backend. Recommended producer: useLiveTranscribe / useTurnTaker for agent state and useVoiceRecorder().getVolume() for input volume from @localmode/react (on-device, optional).
clsx+tailwind-merge— via the sharedcn()util- No external visualizer dependency — pure Canvas 2D
Files installed
voice-orb.tsx— the componentlib/utils.ts— thecn()helper (if not already present)
Props
VoiceOrb
Prop
Type
Examples
Driven by the recorder's live volume
import { VoiceOrb } from '@/components/voice-orb';
import { useVoiceRecorder } from '@localmode/react';
export function Agent({ state }: { state: 'listening' | 'speaking' | 'idle' }) {
const recorder = useVoiceRecorder();
// The orb polls getInputVolume() on every animation frame; getVolume()
// returns the live RMS input level in [0, 1] while recording (0 otherwise).
return (
<>
<button onClick={recorder.isRecording ? () => recorder.stopRecording() : recorder.startRecording}>
{recorder.isRecording ? 'Stop' : 'Listen'}
</button>
<VoiceOrb state={state} getInputVolume={recorder.getVolume} />
</>
);
}For the speaking state, feed getOutputVolume from an AnalyserNode on your TTS output node — the agent's speech is not a microphone stream, so the recorder doesn't cover it.
Customization
The orb draws to a single canvas; tune the per-state pulse speed and base radius in STATE_CONFIG, or swap the radial gradient for your brand colors via color / glowColor (both accept CSS var(--…) tokens, resolved against the live canvas). Because volume comes through callbacks, the orb never touches your audio graph — point it at input, output, or any custom amplitude source.
Transcribed Note Card
A transcription list item pairing transcript text with inline audio playback — with a "transcribing…" placeholder that morphs into the populated card.
Voice Button
A press-to-record / release-to-transcribe push-to-talk button with an explicit state machine — idle → recording (pulse + live waveform) → processing → success/error.