Skip to main content

Introduction

React Voice Visualizer is a comprehensive audio recording and visualization library built on top of the Web Audio API. It provides a clean separation between state management (via hooks) and visualization (via components), making it easy to integrate audio recording capabilities into React applications.

Architecture

The library follows a modular architecture with two primary parts:
1

Hook Layer - useVoiceVisualizer

Manages all recording and playback state, handles audio processing, and provides control functions. This hook encapsulates the complex Web Audio API logic.
2

Component Layer - VoiceVisualizer

Renders the visual representation of audio data on a canvas element and provides UI controls. The component is highly customizable with props for colors, dimensions, and behavior.

Separation of Concerns

const App = () => {
  // Hook handles all logic and state
  const controls = useVoiceVisualizer();
  
  // Component handles visualization
  return <VoiceVisualizer controls={controls} />;
};
This architecture allows you to:
  • Use the hook independently for custom UIs
  • Access recording state and controls programmatically
  • Customize the visualization component without touching logic

Data Flow

The library processes audio through a series of Web Audio API nodes:
1

Audio Capture

navigator.mediaDevices.getUserMedia() requests microphone access and returns a MediaStream
2

Dual Processing

The stream is connected to two paths:
  • MediaRecorder: Records audio chunks and generates a Blob when stopped
  • AudioContext + AnalyserNode: Provides real-time frequency data for visualization
3

Real-time Visualization

The AnalyserNode continuously outputs frequency data into a Uint8Array, which is rendered on canvas using requestAnimationFrame
4

Recording Completion

When recording stops, the MediaRecorder produces a Blob, which is decoded into an AudioBuffer for playback and waveform generation

Key Web Audio API Concepts

AudioContext

The AudioContext is the central object for all audio processing:
// Created when recording starts (useVoiceVisualizer.tsx:162)
audioContextRef.current = new window.AudioContext();
The AudioContext creates and connects various audio processing nodes. Learn more in the Web Audio API documentation.

AnalyserNode

Provides real-time frequency and time-domain analysis:
// Create analyser and connect to audio stream (useVoiceVisualizer.tsx:163-169)
analyserRef.current = audioContextRef.current.createAnalyser();
dataArrayRef.current = new Uint8Array(
  analyserRef.current.frequencyBinCount
);
sourceRef.current = audioContextRef.current.createMediaStreamSource(stream);
sourceRef.current.connect(analyserRef.current);
The AnalyserNode outputs audio data that drives the live visualization.

MediaRecorder

Records the audio stream and produces a Blob:
// Initialize and start recording (useVoiceVisualizer.tsx:170-175)
mediaRecorderRef.current = new MediaRecorder(stream);
mediaRecorderRef.current.addEventListener('dataavailable', handleDataAvailable);
mediaRecorderRef.current.start();

AudioBuffer

When recording stops, the Blob is decoded into an AudioBuffer:
// Process the recorded blob (useVoiceVisualizer.tsx:119-122)
const audioBuffer = await blob.arrayBuffer();
const audioContext = new AudioContext();
const buffer = await audioContext.decodeAudioData(audioBuffer);
setBufferFromRecordedBlob(buffer);
The AudioBuffer provides raw PCM data used to generate the static waveform visualization.

Canvas Rendering

All visualization is rendered on an HTML5 Canvas element:
  • Live Recording: Uses drawByLiveStream to render time-domain data from the AnalyserNode
  • Recorded Audio: Uses drawByBlob to render a static waveform from the AudioBuffer
Both rendering functions paint rounded rectangles representing audio amplitude at specific time intervals.
The canvas uses devicePixelRatio for crisp rendering on high-DPI displays. The actual canvas width may be 2x or 3x the CSS width (VoiceVisualizer.tsx:352).

Internal Reference Management (v2.x.x)

Starting in version 2.x.x, the library manages the audio element reference (audioRef) internally. You no longer need to pass ref={audioRef} to components manually.
The hook uses useRef to maintain references to:
  • audioRef - HTMLAudioElement for playback (useVoiceVisualizer.tsx:53)
  • mediaRecorderRef - MediaRecorder instance (useVoiceVisualizer.tsx:46)
  • audioContextRef - AudioContext for processing (useVoiceVisualizer.tsx:47)
  • analyserRef - AnalyserNode for real-time data (useVoiceVisualizer.tsx:48)
  • canvasRef - Canvas element for rendering (VoiceVisualizer.tsx:145)
These refs persist across renders and are cleaned up when clearCanvas() is called.

Next Steps

Recording

Learn how audio recording works with MediaRecorder

Visualization

Understand canvas rendering and audio data processing

Playback

Explore audio playback and synchronized visualization

API Reference

View the complete hook API documentation

Build docs developers (and LLMs) love