# 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";
s.thread.voice == null}> s.thread.voice?.status.type === "running"}>
``` 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 |