audiocn-svelte
Esc

Start typing to search the docs

Level Meter

A peak and RMS level meter with zones, peak hold, a scale, a readout and a clip light.

4 min read · 709 words

−∞ dB

Installation

$ pnpm dlx shadcn-svelte@latest add https://juddisjudd.github.io/audiocn-svelte/r/level-meter.json

Usage

<script lang="ts">
	import { LevelMeter } from "#lib/components/ui/level-meter/index.js";
</script>

<LevelMeter aria-label="Microphone level" peakDb={-12} />

With no children, LevelMeter renders one track per channel with a peak bar and a peak-hold tick. Add children to control the anatomy.

Anatomy

<LevelMeter source={analyser.meter}>
	<LevelMeterChannels>
		<LevelMeterChannel index={0}>
			<LevelMeterTrack>
				<LevelMeterBar measure="rms" />
				<LevelMeterBar measure="peak" />
				<LevelMeterHold />
			</LevelMeterTrack>
		</LevelMeterChannel>
		<LevelMeterScale />
	</LevelMeterChannels>
	<LevelMeterValue />
	<LevelMeterClip />
</LevelMeter>

Examples

Default

Values

Pass peakDb (and optionally rmsDb) for data that arrives slowly. The meter still moves smoothly between updates.

Quiet
Good
Hot
Clipping

Vertical

−∞ dB

Variants

solid
segmented
gradient

Peak and RMS

Layer an rms bar over a translucent peak bar for a dual meter.

Ballistics

peak rises in 15 ms and falls steadily; vu is slow and averaged; instant follows the input exactly.

peak
vu
instant

Colors and zones

Override the meter tokens with a class, or pass your own zones.

Build your own visual

Each channel writes its live level to --meter-level (0..1). Anything inside a LevelMeterChannel can use it in CSS.

Microphone

−∞ dB

Feeding data

A meter accepts levels three ways. See Feeding data.

<script lang="ts">
	import { LevelMeter, type LevelMeterActions } from "#lib/components/ui/level-meter/index.js";

	let meter = $state<LevelMeterActions>();

	// From your own frame loop:
	const onFrame = (peakDb: number) => meter?.paint({ channels: [{ peakDb }] });
</script>

<!-- A source: subscribes and paints itself, without going through Svelte state. -->
<LevelMeter source={analyser.meter} />

<!-- Values: for slow data. Ballistics smooth the movement. -->
<LevelMeter peakDb={-9.1} rmsDb={-18} />

<!-- A handle: for callers that own their own frame loop. -->
<LevelMeter bind:this={meter} />

Theming

Token or variableWhereDefault
--meter-ok, --meter-warn, --meter-clipthemegreen, amber, --destructive
--meter-thicknessroot0.5rem (sm 0.25rem, lg 0.75rem)
--meter-gaproot0.25rem, between channels
--meter-level, --meter-rms, --meter-holdeach channel, live0..1
Data attributeOnMeaning
data-orientation, data-variant, data-sizerootCurrent settings
data-zoneroot, channelsok, warn or clip
data-clippingrootThe signal clipped in the last 1.5 s
data-activechannelsThe level is above the bottom of the range
data-dimmedrootInside a muted or silenced channel strip
data-measurebarspeak or rms

Accessibility

  • The root has role="meter" with aria-valuemin, aria-valuemax and aria-valuenow in dB, and aria-valuetext such as "−12.0 dB". These update at most four times a second.
  • Give every meter a name with aria-label or aria-labelledby.
  • With reduced motion, the meter shows the current level four times a second instead of animating.

API reference

LevelMeter

PropTypeDefault
source

Subscribes and paints without going through Svelte state.

FrameSource<MeterFrame> | null—
peakDb

Mono peak level in dBFS, for declarative use.

number—
rmsDb

Mono RMS level in dBFS.

number—
channels

Levels per channel, for declarative multi-channel use.

ChannelLevel[]—
channelCount

Tracks to render before data arrives.

number1
minDb

Bottom of the displayed range.

number-60
maxDb

Top of the displayed range.

number0
zones

Colour zones: ok, warn from −20, clip from −9.

MeterZone[]DEFAULT_ZONES
ballistics

How the meter moves.

"peak" | "vu" | "instant" | Partial<BallisticsOptions>"peak"
taper

Scale law.

"linear" | "audio" | Taper"linear"
orientation

Inherited from a channel strip.

"horizontal" | "vertical""horizontal"
variant

segmented is an LED ladder.

"solid" | "segmented" | "gradient""solid"
segments

Segments for the segmented variant.

number24
size

Track thickness.

"sm" | "default" | "lg""default"

Exported functions

Bind the component with bind:this to call them. Their type is LevelMeterActions.

PropTypeDefault
paint

Paint a frame directly, for callers that own their own frame loop.

(frame: MeterFrame) => void—
reset

Drop the level and the peak hold to silence.

() => void—

LevelMeterChannel

PropTypeDefault
index

Which channel of the frames this track shows.

number0

LevelMeterBar

PropTypeDefault
measure

Which measurement the bar shows.

"peak" | "rms""peak"

LevelMeterScale, LevelMeterValue, LevelMeterClip

These wrap DbScale, DbReadout and ClipIndicator, and take their props. The range, orientation and data come from the meter. LevelMeterClip exports the same report and reset functions as ClipIndicator.

Last updated on October 7, 2026