An organic audio blob visualizer for conversational UIs. Creates a beautiful, responsive orb that reacts to voice input with natural, flowing animations.
- π€ Microphone Input - Real-time voice visualization with auto-calibration
- π Assistant Audio - Connect streaming audio for AI assistant interfaces
- π Organic Animation - Natural blob-like deformation with internal force system
- π¨ Customizable - Extensive theming and animation options
- π± Responsive - Adapts to any container size
- π Performance - Optimized for 60fps smooth animation
- π» TypeScript - Full type definitions included
- π Universal - Works in all modern browsers
<script type="module">
import { VoiceOrb } from 'https://cdn.jsdelivr.net/npm/voice-orb-visualizer@1/dist/voice-orb.mjs'
const orb = new VoiceOrb('#canvas', { color: '#2563eb' })
document.querySelector('#start').onclick = () => orb.startMicrophone()
</script>
<canvas id="canvas" width="400" height="400"></canvas>
<button id="start">Start Listening</button>npm install voice-orb-visualizerimport { VoiceOrb } from 'voice-orb-visualizer'
const orb = new VoiceOrb('#canvas', {
radius: 120,
color: '#2563eb',
debug: false
})
// Start microphone mode
await orb.startMicrophone()
// Or assistant mode for streaming audio
await orb.startAssistant()
orb.processAudioStream(audioBuffer)new VoiceOrb(canvas: HTMLCanvasElement | string, options?: VoiceOrbOptions)| Method | Description |
|---|---|
startMicrophone() |
Start microphone input mode |
startAssistant() |
Start assistant audio mode |
startTest() |
Start test mode (no microphone needed) |
stop() |
Stop all audio processing |
processAudioStream(data) |
Process audio data for assistant mode |
connectAudio(audioElement) |
Connect HTML audio element |
setOptions(options) |
Update options at runtime |
getMode() |
Get current mode |
destroy() |
Clean up and destroy instance |
Visual Options
{
// Size & Layout
radius?: number // Base orb radius (default: 100)
padding?: number // Container padding (default: 10)
// Appearance
color?: string // Fill color (default: '#2563eb')
fillMode?: 'solid' | 'gradient'
strokeWidth?: number // Border width (default: 0)
strokeColor?: string // Border color (default: '#ffffff')
opacity?: number // Overall opacity (default: 1)
}Audio Processing
{
fftSize?: 256 | 512 | 1024 // FFT size for analysis (default: 512)
smoothingTimeConstant?: number // Audio smoothing (default: 0.8)
autoCalibration?: boolean // Auto-calibrate to environment (default: true)
sensitivity?: number // Volume sensitivity (default: 0.05)
volumeLerpFactor?: number // Volume smoothing speed (default: 0.12)
}Animation & Motion
{
pointCount?: number // Blob vertices (default: 24)
animationSpeed?: number // Global animation speed (default: 1.0)
maxOffset?: number // Maximum orb movement (default: 50)
fadeOutMs?: number // Fade out duration (default: 1200)
forceStrength?: number // Internal force strength (default: 1.0)
}Callbacks
{
onCalibrated?: (baseline: number, gain: number) => void
onVolume?: (volume: number) => void
onError?: (error: Error) => void
onModeChange?: (mode: string) => void
}const orb = new VoiceOrb('#canvas')
document.querySelector('#start').onclick = async () => {
try {
await orb.startMicrophone()
} catch (error) {
console.error('Microphone access denied:', error)
}
}const orb = new VoiceOrb('#canvas')
await orb.startAssistant()
// Connect HTML audio element
const audio = document.querySelector('audio')
orb.connectAudio(audio)
// Or process audio data directly
orb.processAudioStream(audioBuffer)const orb = new VoiceOrb('#canvas', {
radius: 150,
color: '#ff6b6b',
pointCount: 32,
sensitivity: 0.1,
animationSpeed: 1.5,
onVolume: (volume) => {
console.log('Current volume:', volume)
}
})import { useEffect, useRef } from 'react'
import { VoiceOrb } from 'voice-orb-visualizer'
function VoiceVisualizer() {
const canvasRef = useRef(null)
const orbRef = useRef(null)
useEffect(() => {
orbRef.current = new VoiceOrb(canvasRef.current, {
color: '#2563eb',
radius: 120
})
return () => orbRef.current?.destroy()
}, [])
const startListening = async () => {
await orbRef.current?.startMicrophone()
}
return (
<div>
<canvas ref={canvasRef} width={400} height={400} />
<button onClick={startListening}>Start</button>
</div>
)
}- Chrome 66+
- Firefox 60+
- Safari 11.1+
- Edge 79+
Requires: Web Audio API, getUserMedia, Canvas 2D, ES2018
Microphone mode requires user permission and HTTPS in production. The library handles permission requests automatically.
- Optimized for 60fps on modern devices
- Automatically caps devicePixelRatio at 2x for performance
- Uses requestAnimationFrame for smooth animation
- Minimal memory allocations during animation
- Basic Example - All features with controls
- React Example - React integration
- Assistant Mode - Streaming audio visualization
MIT License - see LICENSE file for details.
Contributions welcome! Please read our contributing guidelines first.
Made with β€οΈ for conversational AI interfaces