A real-time audio spectrogram visualizer built with React, TypeScript, WebGL2, and the Web Audio API.
Live analysis and visualization of microphone, desktop, and audio file inputs, with features for musicians, voice coaches and audio enthusiasts.
Inspired by Friture: A real-time audio analyzer and Praat: Doing Phonetics by Computer.
-
Multiple Visualization Modes:
- Linear, Logarithmic, and Mel frequency scales
- Customizable frequency range (20Hz - 20kHz)
- Adjustable FFT size and smoothing
- Grayscale, Inferno, and Magma color maps
- Multiple inputs (microphone, desktop, audio files) rendered as tinted, mixable layers
-
Musical Features:
- Note detection and pitch tracking
- Musical note guidelines and frequency markers
- Interactive pitch feedback with cents deviation
- Reference tone generator with adjustable volume
- Karaoke-style file playback: load a song, sing along, and compare your voice against the track as separate colors
-
Advanced Settings:
- Automatic pitch following
- Per-source volume and alignment delay
- Customizable tick markers
- Adjustable time window
- Multiple interpolation modes
-
Mobile Friendly
- Click anywhere on the page to start the audio analysis
- Allow microphone access when prompted by your browser
- Use the settings panel (gear, top left) to enable desktop audio, load an audio file, and customize the visualization (frequency range, FFT size, note guidelines, …)
Loading an audio file shows a playback bar at the bottom — play along karaoke-style and compare your voice against the track.
Space: Pause/Resume the visualizationT: Cycle through tick variantsC: Switch color mapsG: Toggle note guidelinesF: Toggle pitch following
- React 19: UI layer (a thin shell — the audio/render engine runs outside React)
- Tailwind CSS 4: Styling
- WebGL2: Performant spectrogram rendering (one texture layer per audio source)
- Web Audio API: Capture via per-source
AudioWorklettaps, per-source gain/delay nodes, audio file playback, and the reference tone generator - TypeScript: Type-safe JavaScript alternative
- Vite + Bun: Build tooling and package management
- Biome: Linting and formatting
Capture and analysis never touch the main thread.
Each source's audio worklet streams raw sample blocks over a MessagePort directly into the analysis worker.
The worker runs one DSP tick per 10 ms of captured audio — 100 columns per second, driven by the audio clock itself, immune to display refresh rates and main-thread jank — and transfers spectrum columns and pitch results back.
The main thread only routes columns into per-source histories and the GPU texture, and draws on requestAnimationFrame.
src/lib/engine.ts— application core wiring audio, worker, and renderersrc/lib/audio/—AudioSourceimplementations (microphone, desktop, audio file playback), the capture worklet, per-source history ring buffers, and theAudioEnginesource manager (per-source volume/delay graph chains)src/lib/analyzer/— the analysis worker (FFT, smoothing, Pitchy pitch detection) and its message protocolsrc/lib/render/— WebGL2 spectrogram renderer and the 2D overlay renderersrc/lib/store_utils.ts— tiny hand-rolled external store with auseSyncExternalStoreReact bindingsrc/components/— the React shell (canvas host, settings panel, transport bar, notices)
git clone https://github.com/Paul1365972/spectrogram.git
cd spectrogram
bun install
bun devbun run build creates a production build in ./dist/ (preview it with bun preview).
