# Voice
URL: /docs/ui/voice
Realtime voice session controls with connect, mute, and status indicator.
A control bar for realtime bidirectional voice sessions with an animated orb indicator. Works with any `RealtimeVoiceAdapter` (LiveKit, ElevenLabs, etc.).
Getting Started \[#getting-started]
Add the component \[#add-the-component]
This adds `/components/assistant-ui/voice.tsx` to your project, which you can adjust as needed.
Configure a voice adapter \[#configure-a-voice-adapter]
Pass a `RealtimeVoiceAdapter` to your runtime. See the [Realtime Voice guide](/docs/guides/voice) for details.
```tsx
const runtime = useChatRuntime({
adapters: {
voice: myVoiceAdapter,
},
});
```
Use in your application \[#use-in-your-application]
```tsx title="app/page.tsx"
import { Thread } from "@/components/assistant-ui/thread";
import { VoiceControl } from "@/components/assistant-ui/voice";
import { AuiIf } from "@assistant-ui/react";
export default function Chat() {
return (
s.thread.capabilities.voice}>
);
}
```
Anatomy \[#anatomy]
The `VoiceControl` component is built with the following hooks and conditionals:
```tsx
import { AuiIf, useVoiceState, useVoiceControls } from "@assistant-ui/react";
```
Examples \[#examples]
Conditionally show voice controls \[#conditionally-show-voice-controls]
Only render when a voice adapter is configured:
```tsx
s.thread.capabilities.voice}>
```
Voice toggle in composer \[#voice-toggle-in-composer]
Add a compact voice toggle button inside the composer action area:
```tsx
function ComposerVoiceToggle() {
const voiceState = useVoiceState();
const { connect, disconnect } = useVoiceControls();
const isActive =
voiceState?.status.type === "running" ||
voiceState?.status.type === "starting";
return (
s.thread.capabilities.voice}>
);
}
```
Custom indicator colors \[#custom-indicator-colors]
Override the indicator styles by targeting the `aui-voice-indicator` class:
```css
.aui-voice-indicator {
/* Override active color */
&.bg-green-500 {
background: theme("colors.blue.500");
}
}
```
States \[#states]
The `VoiceOrb` responds to five voice session states with distinct animations:
Variants \[#variants]
Four built-in color palettes. Size is controlled via `className`.
Sub-components \[#sub-components]
| Component | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| `VoiceOrb` | Animated orb visual with gradient, glow, and ripple effects. Accepts `state` and `variant` props. |
| `VoiceControl` | Control bar with status dot, connect/disconnect, and mute/unmute buttons. |
| `VoiceConnectButton` | Calls `connect()`. Shown when no session is active. |
| `VoiceMuteButton` | Toggles `mute()`/`unmute()`. Shown when session is running. |
| `VoiceDisconnectButton` | Calls `disconnect()`. Shown when session is active. |
All sub-components are exported and can be used independently for custom layouts.
State Selectors \[#state-selectors]
Use these with `AuiIf` or `useAuiState` to build custom voice UI:
| Selector | Type | Description |
| ----------------------------- | ------------------------------------ | ------------------------------------------------------------------------------ |
| `s.thread.capabilities.voice` | `boolean` | Whether a voice adapter is configured |
| `s.thread.voice` | `VoiceSessionState \| undefined` | `undefined` when no session |
| `s.thread.voice?.status.type` | `"starting" \| "running" \| "ended"` | Session phase |
| `s.thread.voice?.isMuted` | `boolean` | Microphone muted state |
| `s.thread.voice?.mode` | `"listening" \| "speaking"` | Who is currently active (user or agent) |
| `useVoiceVolume()` | `number` | Real-time audio level (0–1), separate from main state to avoid 20Hz re-renders |