165

Waveform

Previous

Canvas-based audio waveform visualization components with recording, playback scrubbing, and microphone input support.

Waveform

Real-time audio visualization with smooth scrolling animation

<script setup lang="ts">
import { ScrollingWaveform } from '@/components/elevenlabs-ui/waveform'
</script>

<template>
  <div class="bg-card w-full rounded-lg border p-6">
    <div class="mb-4">
      <h3 class="text-lg font-semibold">
        Waveform
      </h3>
      <p class="text-muted-foreground text-sm">
        Real-time audio visualization with smooth scrolling animation
      </p>
    </div>
    <ScrollingWaveform
      :height="80"
      :bar-width="3"
      :bar-gap="2"
      :speed="30"
      :fade-edges="true"
      bar-color="gray"
    />
  </div>
</template>

Installation

pnpm dlx elevenlabs-ui-vue@latest add waveform

Usage

import {
AudioScrubber,
LiveMicrophoneWaveform,
MicrophoneWaveform,
RecordingWaveform,
ScrollingWaveform,
StaticWaveform,
Waveform,
} from "@/components/elevenlabs-ui/waveform"

Basic Waveform

<script setup lang="ts">
const data = Array.from({ length: 50 }, () => Math.random())
</script>

<template>
  <Waveform
    :data="data"
    :height="100"
    :bar-width="4"
    :bar-gap="2"
  />
</template>

Scrolling Animation

<template>
  <ScrollingWaveform
    :height="80"
    :speed="50"
    :bar-count="60"
    bar-color="hsl(var(--primary))"
    :fade-edges="true"
  />
</template>

Microphone Input

<script setup lang="ts">
const isRecording = ref(false)
</script>

<template>
  <MicrophoneWaveform
    :active="isRecording"
    :height="100"
    :sensitivity="1.5"
    @error="(error) => console.error('Microphone error:', error)"
  />
</template>

API Reference

Waveform

The base waveform component that displays audio data as bars.

<template>
  <Waveform :data="audioData" />
</template>

Props

PropTypeDescription
datanumber[]Array of values between 0 and 1 for each bar
barWidthnumberWidth of each bar in pixels. Default: 4
barHeightnumberHeight of each bar in pixels. Default: 4
barGapnumberGap between bars in pixels. Default: 2
barRadiusnumberBorder radius of bars. Default: 2
barColorstringCustom bar color. Uses foreground color by default
fadeEdgesbooleanApply fade effect to edges. Default: true
fadeWidthnumberWidth of fade effect in pixels. Default: 24
heightstring | numberHeight of the waveform. Default: 128

Emits

EventTypeDescription
barClick(index: number, value: number) => voidCallback when a bar is clicked

ScrollingWaveform

Continuously scrolling waveform with auto-generated bars.

<template>
  <ScrollingWaveform :speed="50" />
</template>

Props

PropTypeDescription
speednumberScroll speed in pixels per second. Default: 50
barCountnumberNumber of bars to display. Default: 60
...propsWaveformPropsAll Waveform props except data

AudioScrubber

Interactive waveform for audio playback with seek functionality.

<template>
  <AudioScrubber
    :data="waveformData"
    :currentTime="playbackTime"
    :duration="totalDuration"
    @seek="handleSeek"
  />
</template>

Props

PropTypeDescription
currentTimenumberCurrent playback time in seconds
durationnumberTotal duration in seconds. Default: 100
showHandlebooleanShow draggable handle. Default: true
...propsWaveformPropsAll standard Waveform props

Emits

EventTypeDescription
seek(time: number) => voidCallback when user seeks to a new time

MicrophoneWaveform

Real-time microphone input visualization.

<template>
  <MicrophoneWaveform :active="isListening" :sensitivity="1.5" />
</template>

Props

PropTypeDescription
activebooleanEnable/disable microphone input. Default: false
fftSizenumberFFT size for frequency analysis. Default: 256
smoothingTimeConstantnumberSmoothing factor (0-1). Default: 0.8
sensitivitynumberAmplitude sensitivity. Default: 1
...propsWaveformPropsAll standard Waveform props

Emits

EventTypeDescription
error(error: Error) => voidError callback

StaticWaveform

Waveform with deterministic random data based on seed.

<template>
  <StaticWaveform :bars="40" :seed="42" />
</template>

Props

PropTypeDescription
barsnumberNumber of bars to generate. Default: 40
seednumberRandom seed for consistent data
...propsWaveformPropsAll standard Waveform props

LiveMicrophoneWaveform

Advanced microphone visualization with recording history and playback scrubbing.

<template>
  <LiveMicrophoneWaveform
    :active="isRecording"
    :enableAudioPlayback="true"
    :playbackRate="1"
  />
</template>

Props

PropTypeDescription
activebooleanEnable/disable recording
historySizenumberMax bars to keep in history. Default: 150
updateRatenumberUpdate interval in ms. Default: 50
enableAudioPlaybackbooleanEnable audio scrubbing when stopped. Default: true
playbackRatenumberAudio playback speed. Default: 1
savedHistorynumberExternal ref to persist history
dragOffsetnumberExternal drag offset control
...propsScrollingWaveformPropsAll ScrollingWaveform props

Emits

EventTypeDescription
update:dragOffset(offset: number) => voidExternal drag offset setter

RecordingWaveform

Recording interface with scrubbing through recorded audio.

<template>
  <RecordingWaveform
    :recording="isRecording"
    @recording-complete="(data) => console.log('Recording data:', data)"
  />
</template>

Props

PropTypeDescription
recordingbooleanRecording state. Default: false
showHandlebooleanShow scrubbing handle. Default: true
updateRatenumberUpdate interval in ms. Default: 50
...propsWaveformPropsAll standard Waveform props

Emits

EventTypeDescription
recordingComplete(data: number[]) => voidCallback with recorded waveform data

Examples

Music Player Visualization

<script setup>
const audioData = computed(() =>
Array.from({ length: 100 }, () => 0.2 + Math.random() * 0.6)
)
</script>

<template>
  <AudioScrubber
    :data="audioData"
    :current-time="currentTime"
    :duration="duration"
    @seek="handleSeek"
    :height="60"
    :bar-width="3"
    :bar-gap="1"
    bar-color="hsl(var(--primary))"
  />
</template>

Voice Recorder

<script setup>
import { ref } from 'vue'

const recording = ref(false)
</script>

<template>
  <div class="space-y-4">
    <RecordingWaveform
      :recording="recording"
      :height="100"
      @recording-complete="(data) => {
        console.log('Recording complete', data)
      }"
    />

    <Button @click="recording = !recording">
      {{ recording ? 'Stop' : 'Start' }} Recording
    </Button>
  </div>
</template>

Live Audio Monitor

<script setup>
import { ref } from 'vue'

const active = ref(false)
</script>

<template>
  <MicrophoneWaveform
    :active="active"
    :height="80"
    :sensitivity="2"
    :bar-width="2"
    :bar-gap="1"
    @error="(error) => {
      console.error('Microphone error:', error)
      active = false
    }"
  />
</template>

Notes

  • All waveform components use HTML5 Canvas for high-performance rendering
  • Animations are synchronized using requestAnimationFrame for 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 --foreground but 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