# Waveform Component | AudioDN Docs

> Standalone waveform visualization component with multiple drawing styles including vertical bars, wavy curves, leaning reflections, and playhead indicators.

Source: https://audiodeliverynetwork.com/docs/components/waveform/

---

# Waveform

Building a custom player but want production-ready waveform visualization? The waveform is available as a standalone component — load only what you need, style it however you want, and wire it into your own playback logic.

## Usage

Install from npm and import the standalone waveform component, then set the `levels` property with amplitude data from the play session API response at `first_track.levels`.

```
npm install @audiodn/components
```

```
import '@audiodn/components/waveform'
```

```
<audiodn-waveform
  variant="vertical"
  height="100"
  line-width="2"
  gap="3"
  progress="0.6"
></audiodn-waveform>
```

Prefer no build step? Load it straight from a CDN instead:

```
<script type="module" src="https://unpkg.com/@audiodn/components@latest/dist/waveform.js"></script>
```

```
// Create a play session; its response includes the first track's level data.
const res = await fetch('https://api.audiodelivery.net/v1/play_session/track', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ track_id: 'TRACK_ID' })
});
const { first_track } = await res.json();

const waveform = document.querySelector('audiodn-waveform');
waveform.levels = first_track.levels.levels;
```

### Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `levels` | number\[\] | `[]` | Array of 0–1 amplitude values (set via JS property) |
| `variant` | string | `"vertical"` | Render style: `"vertical"` bars, `"wavy"` curves, or `"reflection"` bars with a leaning mirrored reflection |
| `height` | number | `120` | Canvas height in pixels |
| `line-width` | number | `2` | Width of each waveform bar or the wave stroke |
| `line-color` | string | `"#888888"` | Stroke color (overridden by CSS variable `--adn-waveform-color-fg`) |
| `gap` | number | `3` | Spacing between bars in the vertical variant |
| `scale-strength` | number | `0.4` | Controls amplitude scaling — lower values compress quiet/loud range |
| `reflection-angle` | number | `45` | `reflection` only: max lean of the reflection in degrees, reached at 0% / 100% progress |
| `reflection-size` | number | `0.25` | `reflection` only: reflection height as a fraction of the main waveform height |
| `reflection-opacity` | number | `0.55` | `reflection` only: opacity of the reflection at the baseline (fades to 0 downward) |
| `progress` | number | `0` | Playback progress position (0–1) |
| `duration` | number | `0` | Track duration in seconds |

## Vertical

Default vertical bar style. Configurable `line-width`, `gap`, and `height` via attributes.

```
<audiodn-waveform
  variant="vertical"
  height="100"
  line-width="2"
  gap="3"
  progress="0.6"
></audiodn-waveform>
```

```
// Level data is returned by the play session API:
// POST /v1/play_session/:scope
// Response: { first_track: { levels: { levels: [...], min, max, avg } } }

const { levels } = response.first_track;

const waveform = document.querySelector('audiodn-waveform');
waveform.levels = levels.levels; // array of 0–1 amplitude values

// Frameworks with property bindings (Vue, React, Svelte, Angular, etc.)
// can pass levels directly — no querySelector needed:
//   Vue:    <audiodn-waveform :levels="levels.levels" />
//   React:  <audiodn-waveform ref={r => r && (r.levels = data)} />
```

## Wavy

Smooth curved wave style using `variant="wavy"`.

```
<audiodn-waveform
  variant="wavy"
  height="100"
  line-width="2"
  gap="3"
  progress="0.35"
></audiodn-waveform>
```

```
const { levels } = response.first_track;

const waveform = document.querySelector('audiodn-waveform');
waveform.levels = levels.levels;
```

## Reflection

Flat-bottomed bars with a shorter, faded mirror image beneath, set with `variant="reflection"`. The reflection leans according to `progress` — it sweeps from right to left as playback moves from start (0) to end (1), giving the waveform a subtle sense of motion. Tune it with `reflection-angle`, `reflection-size`, and `reflection-opacity`.

```
<audiodn-waveform
  variant="reflection"
  height="100"
  line-width="2"
  gap="3"
  progress="0.3"
  reflection-angle="45"
  reflection-size="0.25"
  reflection-opacity="0.55"
></audiodn-waveform>
```

```
const { levels } = response.first_track;

const waveform = document.querySelector('audiodn-waveform');
waveform.levels = levels.levels;

// Update progress as the track plays — the reflection leans with it:
waveform.progress = currentTime / duration;
```

## Thin Lines

Narrow bars with tight spacing: `line-width="1"`, `gap="1"`. No `progress` set — the waveform renders at half opacity with no playhead.

```
<audiodn-waveform
  variant="vertical"
  height="80"
  line-width="1"
  gap="1"
></audiodn-waveform>
```

## Thick Wavy

Wide wavy curves with generous spacing: `line-width="4"`, `gap="6"`. No `progress` set — the waveform renders at half opacity with no playhead.

```
<audiodn-waveform
  variant="wavy"
  height="80"
  line-width="4"
  gap="6"
></audiodn-waveform>
```

## Playhead

Shows a playhead position at 40% with highlight overlay.

```
<audiodn-waveform
  variant="vertical"
  height="100"
  line-width="2"
  gap="3"
  progress="0.4"
></audiodn-waveform>
```

## Themes

Override CSS custom properties on the host to restyle the waveform. All properties use the `--adn-waveform-*` prefix, with `--adn-color-accent` as a shared fallback for the line color.

### Light / Dark (system preference)

```
.theme-wf-lightdark {
  --adn-waveform-color-fg: light-dark(#333, #ccc);
  --adn-waveform-color-playhead: light-dark(#333, #eee);
  --adn-waveform-playhead-width: 2px;
  --adn-waveform-bg: light-dark(#f5f5f5, #1a1a1a);
  --adn-waveform-border: 1px solid light-dark(#ddd, #333);
  --adn-waveform-radius: 8px;
  --adn-waveform-padding: 8px;
}
```

### Midnight

```
.theme-wf-midnight {
  --adn-waveform-color-fg: #7c3aed;
  --adn-waveform-color-playhead: #a78bfa;
  --adn-waveform-playhead-width: 2px;
  --adn-waveform-bg: #1a1a2e;
  --adn-waveform-border: 1px solid #3a3a5e;
  --adn-waveform-radius: 12px;
  --adn-waveform-padding: 12px;
}
```

### Electric

```
.theme-wf-electric {
  --adn-waveform-color-fg: #00d4ff;
  --adn-waveform-color-playhead: #e040fb;
  --adn-waveform-playhead-width: 3px;
  --adn-waveform-bg: #0a0a0f;
  --adn-waveform-border: 1px solid #00d4ff33;
  --adn-waveform-radius: 4px;
  --adn-waveform-padding: 8px;
}
```
