Spectrogram
spectrogramVisualizersLive mode keeps a scrolling history of FFT energy. Static mode analyzes supplied PCM. Prepared mode renders a bounded host-produced magnitude grid with explicit frame times and frequency bins, so a module face needs no audio buffer or FFT work. PitchRead uses prepared mode beneath its MIDI roll with the same seconds and logarithmic pitch bounds. The mapping helpers are pure and downloadable; color indicates source energy, not model confidence.
Bone / Studio
Loading interactive preview…
Planar / Flat
Loading interactive preview…
Midnight / Minimal
Loading interactive preview…
Ember / Vintage
Loading interactive preview…
Ink / Studio
Loading interactive preview…
Mint / Flat
Loading interactive preview…
Install
Copies the source into your project. Anything it depends on comes with it.
$ pnpm dlx shadcn@latest add @pluginui/core-spectrogramPulls in
use-audio-sourcecontrol-themeprepared-spectrogramstft
First time? Add the registry to your components.json once:
{
"registries": {
"@pluginui": "https://pluginui.com/r/{name}.json"
}
}Usage
Connect the documented props to your application or host.
import { Spectrogram } from "@/components/ui/spectrogram"
<Spectrogram analyser={analyserNode} height={220} colorScale="viridis" />
// The host prepares this grid outside the face and realtime callback.
<Spectrogram mode="prepared" prepared={host.spectrogram}
durationSeconds={clipDuration} minFrequency={lowHz} maxFrequency={highHz}
showAxis={false} height={150} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| mode / prepared | "realtime" | "static" | "prepared" / PreparedSpectrogramData | "realtime" | Prepared data contains frame-major Uint8 magnitudes, frames, bins, explicit frameTimesSeconds, binFrequencyHz, durationSeconds and the quantization dB range. It never invokes PCM analysis. |
| durationSeconds | number | — | Prepared mode's horizontal timeline domain. Defaults to the source duration; a longer domain leaves the remainder empty instead of stretching the image. |
| analyser | AnalyserNode | — | A live analyser to read frequency data from. |
| getData | (target: Float32Array) => boolean | void | — | Supply dB magnitudes yourself instead of using an analyser. |
| colorScale | "viridis" | "plasma" | "inferno" | "magma" | "cividis" | "turbo" | "grayscale" | "heat" | (value: number) => [r, g, b] | "viridis" | Built-in colour ramp, or your own magnitude → RGB function. |
| scale | "log" | "linear" | "log" | Frequency axis mapping. Linear spends most of the height above 10 kHz; log is the musically useful one. |
| minFrequency / maxFrequency | number | 20 / Nyquist | The frequency range shown, bottom to top. |
| minDecibels / maxDecibels | number | -90 / -10 | The magnitude range mapped onto the colour ramp. |
| gain | number | 1 | Magnitude multiplier applied after normalisation, before clamping. |
| scrollSpeed | number | 1 | Pixels the image scrolls per frame. Higher is faster and coarser. |
| sampleRate | number | — | Needed for the frequency axis when driving from getData. |
| showAxis | boolean | true | Draw the decade frequency labels down the left edge. |
| height | number | 200 | Display height in pixels; width defaults to 100%. |
| paused | boolean | false | Stop the animation loop and hold the last frame. |
Interaction
- Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
- Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
- Double-click resets to
defaultValue. - Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
- Proper
sliderandswitchroles with livearia-valuetext, so a screen reader announces the formatted value rather than the raw number. - The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.