Guide

WebSocket protocol

The remote-FFT wire protocol the visualizer speaks in websocket mode, and the reference servers.

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 — bins bytes 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 wireFFT runsConsumed by
Pre-computed FFT (this page)uint8 FFT magnitudesOn the serverFFTVisualizer mode: 'websocket'
Raw PCMInterleaved PCM audioIn 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.

Copyright © 2026