WebSocket protocol
In websocket mode the visualizer connects to a server that has already computed the
FFT and streams it as compact binary frames — so the browser only draws. This lets the FFT
run on a separate device (a Raspberry Pi, a media server) feeding any number of browsers.
The pre-computed-FFT protocol
mode: 'websocket' expects a server that sends pre-computed FFT frames.
1. Config message (JSON), once on connect:
{ "type": "config", "mode": "fft", "bins": 80, "fps": 120 }
2. Binary FFT frames, continuously:
- One
uint8(0–255) per frequency bin —binsbytes per frame - 0 = silence, 255 = maximum amplitude
- Typically 100 Hz – 18 kHz, exponentially spaced
For best results the server should capture at 48 kHz+, apply a Hann/Hamming window, compute a 1024–2048-point FFT, map to exponentially-spaced bands, apply A-weighting, convert to dB, normalize to 0–255, and stream at 60–120 fps.
Reference servers
The repository's backend-examples/ has servers that capture system audio, compute FFT, and
stream it in this format: Python (pyalsaaudio + numpy, incl. a Raspberry Pi variant),
Node.js (node-audiorecorder + fft.js), and Rust (cpal + rustfft).
Two different WebSocket protocols
Don't confuse the visualizer's websocket mode with the raw-PCM engines:
| Sends over the wire | FFT runs | Consumed by | |
|---|---|---|---|
| Pre-computed FFT (this page) | uint8 FFT magnitudes | On the server | FFTVisualizer mode: 'websocket' |
| Raw PCM | Interleaved PCM audio | In the browser (WASM) | Core createWebSocketFft / Vue useWebSocketFft |
The raw-PCM path streams audio and does the FFT client-side; feed its output into the
visualizer with mode: 'external'. Its config message uses "mode": "pcm" with
sampleRate, bitDepth, and channels fields instead of the fft config above.