---
title: "Data modes"
description: "The three ways to get audio data into the visualizer — local, WebSocket, and external."
canonical_url: "https://www.fftvisualizer.com/guide/data-modes"
---
# Data modes

> The three ways to get audio data into the visualizer — local, WebSocket, and external.

The visualizer has one job — render a spectrum — and three ways to get the data, selected
with the `mode` option (a prop in Vue and React, a constructor option in Core).

<table>
<thead>
  <tr>
    <th>
      Mode
    </th>
    
    <th>
      How data arrives
    </th>
    
    <th>
      Use when
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        local
      </code>
    </td>
    
    <td>
      Captures mic or display audio and computes the FFT in-browser (Rust/WASM)
    </td>
    
    <td>
      You want a zero-backend, client-side visualizer
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket
      </code>
      
       <em>
        (default)
      </em>
    </td>
    
    <td>
      Connects to <code>
        websocketUrl
      </code>
      
       and reads <strong>
        pre-computed
      </strong>
      
       FFT frames
    </td>
    
    <td>
      A server/device already produces FFT data (e.g. a Raspberry Pi)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        external
      </code>
    </td>
    
    <td>
      You pass FFT magnitudes as <code>
        data
      </code>
      
       / <code>
        dataLeft
      </code>
      
       / <code>
        dataRight
      </code>
    </td>
    
    <td>
      You have your own audio pipeline (Web Audio, another analyser, etc.)
    </td>
  </tr>
</tbody>
</table>

## Local mode

Set `audioSource` to `display` to capture tab/system audio via screen sharing instead of the
microphone.

<code-group>

```ts [Core]
new FFTVisualizer(canvas, { mode: 'local', audioSource: 'mic', bands: 80 })
```

```vue [Vue]
<FFTVisualizer mode="local" audio-source="mic" :bands="80" />
```

```tsx [React]
<FFTVisualizer mode="local" audioSource="mic" bands={80} />
```

</code-group>

## WebSocket mode

The server streams a small config message then binary FFT frames — see the
[WebSocket protocol](https://www.fftvisualizer.com/guide/websocket-protocol). Reference servers for Python, Node.js and
Rust are in the repository's `backend-examples/`.

<code-group>

```ts [Core]
new FFTVisualizer(canvas, {
  mode: 'websocket',
  websocketUrl: 'wss://your-server/fft',
  bands: 40,
  autoReconnect: true
})
```

```vue [Vue]
<FFTVisualizer
  mode="websocket"
  websocket-url="wss://your-server/fft"
  :bands="40"
  :auto-reconnect="true"
/>
```

```tsx [React]
<FFTVisualizer
  mode="websocket"
  websocketUrl="wss://your-server/fft"
  bands={40}
  autoReconnect
/>
```

</code-group>

<warning>

On an HTTPS page you must use a **wss://** URL — browsers block insecure `ws://` from
secure pages as mixed content.

</warning>

## External mode

Pass a `Uint8Array` of magnitudes (0–255); update it and the visual follows. For stereo,
pass `dataLeft` and `dataRight` instead of `data`.

<code-group>

```ts [Core]
const viz = new FFTVisualizer(canvas, { mode: 'external', bands: 40 })

// ...each frame, feed fresh magnitudes (the data is copied):
viz.feedData(myUint8Array)
```

```vue [Vue]
<script setup>
import { ref } from 'vue'
import { FFTVisualizer } from '@fft-visualizer/vue'

const data = ref(new Uint8Array(80))
// ...fill data.value from your own analyser each frame
</script>

<template>
  <FFTVisualizer mode="external" :data="data" :bands="40" />
</template>
```

```tsx [React]
import { useState } from 'react'
import { FFTVisualizer } from '@fft-visualizer/react'

const [data, setData] = useState(new Uint8Array(80))
// ...set a fresh array from your own analyser each frame

<FFTVisualizer mode="external" data={data} bands={40} />
```

</code-group>

<tip>

**Feed data by copy for in-place buffers.** Core's `feedData()` copies the data, so reusing
one `Uint8Array` each frame is fine. In both wrappers the `data` prop is compared **by
reference** — if you mutate the same array in place, the change goes unnoticed. Either pass a
fresh array, or call `feedData()` on the component ([Vue](https://www.fftvisualizer.com/vue/props#exposed-methods),
[React](https://www.fftvisualizer.com/react/props#imperative-handle)), which copies — and in React also skips a render per
frame.

</tip>


## Sitemap

See the full [sitemap](https://www.fftvisualizer.com/sitemap.md) for all pages.
