Waveform
Canvas-based audio waveform visualization components with recording, playback scrubbing, and microphone input support.
Waveform
Real-time audio visualization with smooth scrolling animation
"use client"
import { ScrollingWaveform } from "@/components/ui/waveform"
export function WaveformDemo() {
return (
<div className="bg-card w-full rounded-lg border p-6">
<div className="mb-4">
<h3 className="text-lg font-semibold">Waveform</h3>
<p className="text-muted-foreground text-sm">
Real-time audio visualization with smooth scrolling animation
</p>
</div>
<ScrollingWaveform
height={80}
barWidth={3}
barGap={2}
speed={30}
fadeEdges={true}
barColor="gray"
/>
</div>
)
}
Installation
pnpm dlx @elevenlabs/cli@latest components add waveform
Usage
import {
AudioScrubber,
LiveMicrophoneWaveform,
MicrophoneWaveform,
RecordingWaveform,
ScrollingWaveform,
StaticWaveform,
Waveform,
} from "@/components/ui/waveform"Basic Waveform
const data = Array.from({ length: 50 }, () => Math.random())
<Waveform data={data} height={100} barWidth={4} barGap={2} />Scrolling Animation
<ScrollingWaveform
height={80}
speed={50}
barCount={60}
barColor="hsl(var(--primary))"
fadeEdges={true}
/>Microphone Input
const [isRecording, setIsRecording] = useState(false)
<MicrophoneWaveform
active={isRecording}
height={100}
sensitivity={1.5}
onError={(error) => console.error("Microphone error:", error)}
/>API Reference
Waveform
The base waveform component that displays audio data as bars.
<Waveform data={audioData} />Props
| Prop | Type | Description |
|---|---|---|
| data | number[] | Array of values between 0 and 1 for each bar |
| barWidth | number | Width of each bar in pixels. Default: 4 |
| barHeight | number | Height of each bar in pixels. Default: 4 |
| barGap | number | Gap between bars in pixels. Default: 2 |
| barRadius | number | Border radius of bars. Default: 2 |
| barColor | string | Custom bar color. Uses foreground color by default |
| fadeEdges | boolean | Apply fade effect to edges. Default: true |
| fadeWidth | number | Width of fade effect in pixels. Default: 24 |
| height | string | number | Height of the waveform. Default: 128 |
| onBarClick | (index: number, value: number) => void | Callback when a bar is clicked |
ScrollingWaveform
Continuously scrolling waveform with auto-generated bars.
<ScrollingWaveform speed={50} />Props
| Prop | Type | Description |
|---|---|---|
| speed | number | Scroll speed in pixels per second. Default: 50 |
| barCount | number | Number of bars to display. Default: 60 |
| ...props | WaveformProps | All Waveform props except data and onBarClick |
AudioScrubber
Interactive waveform for audio playback with seek functionality.
<AudioScrubber
data={waveformData}
currentTime={playbackTime}
duration={totalDuration}
onSeek={handleSeek}
/>Props
| Prop | Type | Description |
|---|---|---|
| currentTime | number | Current playback time in seconds |
| duration | number | Total duration in seconds. Default: 100 |
| onSeek | (time: number) => void | Callback when user seeks to a new time |
| showHandle | boolean | Show draggable handle. Default: true |
| ...props | WaveformProps | All standard Waveform props |
MicrophoneWaveform
Real-time microphone input visualization.
<MicrophoneWaveform active={isListening} sensitivity={1.5} />Props
| Prop | Type | Description |
|---|---|---|
| active | boolean | Enable/disable microphone input. Default: false |
| fftSize | number | FFT size for frequency analysis. Default: 256 |
| smoothingTimeConstant | number | Smoothing factor (0-1). Default: 0.8 |
| sensitivity | number | Amplitude sensitivity. Default: 1 |
| onError | (error: Error) => void | Error callback |
| ...props | WaveformProps | All standard Waveform props |
StaticWaveform
Waveform with deterministic random data based on seed.
<StaticWaveform bars={40} seed={42} />Props
| Prop | Type | Description |
|---|---|---|
| bars | number | Number of bars to generate. Default: 40 |
| seed | number | Random seed for consistent data |
| ...props | WaveformProps | All standard Waveform props |
LiveMicrophoneWaveform
Advanced microphone visualization with recording history and playback scrubbing.
<LiveMicrophoneWaveform
active={isRecording}
enableAudioPlayback={true}
playbackRate={1}
/>Props
| Prop | Type | Description |
|---|---|---|
| active | boolean | Enable/disable recording |
| historySize | number | Max bars to keep in history. Default: 150 |
| updateRate | number | Update interval in ms. Default: 50 |
| enableAudioPlayback | boolean | Enable audio scrubbing when stopped. Default: true |
| playbackRate | number | Audio playback speed. Default: 1 |
| savedHistoryRef | React.MutableRefObject<number[]> | External ref to persist history |
| dragOffset | number | External drag offset control |
| setDragOffset | (offset: number) => void | External drag offset setter |
| ...props | ScrollingWaveformProps | All ScrollingWaveform props |
RecordingWaveform
Recording interface with scrubbing through recorded audio.
<RecordingWaveform
recording={isRecording}
onRecordingComplete={(data) => console.log("Recording data:", data)}
/>Props
| Prop | Type | Description |
|---|---|---|
| recording | boolean | Recording state. Default: false |
| onRecordingComplete | (data: number[]) => void | Callback with recorded waveform data |
| showHandle | boolean | Show scrubbing handle. Default: true |
| updateRate | number | Update interval in ms. Default: 50 |
| ...props | WaveformProps | All standard Waveform props |
Examples
Music Player Visualization
function MusicPlayer() {
const [audioData] = useState(() =>
Array.from({ length: 100 }, () => 0.2 + Math.random() * 0.6)
)
return (
<AudioScrubber
data={audioData}
currentTime={currentTime}
duration={duration}
onSeek={handleSeek}
height={60}
barWidth={3}
barGap={1}
barColor="hsl(var(--primary))"
/>
)
}Voice Recorder
function VoiceRecorder() {
const [recording, setRecording] = useState(false)
return (
<div className="space-y-4">
<RecordingWaveform
recording={recording}
height={100}
onRecordingComplete={(data) => {
console.log("Recording complete", data)
}}
/>
<Button onClick={() => setRecording(!recording)}>
{recording ? "Stop" : "Start"} Recording
</Button>
</div>
)
}Live Audio Monitor
function AudioMonitor() {
const [active, setActive] = useState(false)
return (
<MicrophoneWaveform
active={active}
height={80}
sensitivity={2}
barWidth={2}
barGap={1}
onError={(error) => {
console.error("Microphone error:", error)
setActive(false)
}}
/>
)
}Notes
- All waveform components use HTML5 Canvas for high-performance rendering
- Animations are synchronized using
requestAnimationFramefor smooth 60fps updates - Microphone components require user permission to access audio input devices
- The components automatically handle device pixel ratio for crisp rendering on high-DPI displays
- Bar colors default to the CSS variable
--foregroundbut can be customized - Canvas-based implementation ensures high performance even with hundreds of bars
- ResizeObserver used for responsive canvas sizing
- Proper cleanup of audio contexts and media streams on unmount
- Supports both static data visualization and real-time audio input
- Click handlers available on bars for interactive waveforms
On This Page
InstallationUsageBasic WaveformScrolling AnimationMicrophone InputAPI ReferenceWaveformPropsScrollingWaveformPropsAudioScrubberPropsMicrophoneWaveformPropsStaticWaveformPropsLiveMicrophoneWaveformPropsRecordingWaveformPropsExamplesMusic Player VisualizationVoice RecorderLive Audio MonitorNotesDeploy and Scale Agents with ElevenLabs
ElevenLabs delivers the infrastructure and developer experience you need to ship reliable audio & agent applications at scale.
Talk to an expert