Audio level
A Web Audio level meter for a microphone stream or a media element: a perceptual level and log-spaced frequency bands for orbs, waveforms and visualizers.
On this page
Pick a state and the orb morphs into it. Simulated voices, or your microphone.
Installation
Usage
import { useChatcnAudioLevel } from "@/hooks/use-chatcn-audio-level"
import { useChatcnMicrophone } from "@/hooks/use-chatcn-voice-devices"
const mic = useChatcnMicrophone()
const meter = useChatcnAudioLevel(mic.stream, { updateRate: 0 })
<button onClick={mic.start}>Use microphone</button>
<VoiceOrb state="listening" level={meter.getLevel} />Pass a MediaStream (microphone, WebRTC remote track) or an <audio> or <video> element. getLevel and getBands are cheap enough to call every frame. The level state updates updateRate times a second for components that take a number; set it to 0 to skip re-renders entirely.
Bands
const output = useChatcnAudioLevel(audioRef.current, { updateRate: 0 })
<AudioVisualizer variant="bars" bands={output.getBands} />Without a microphone
useChatcnSimulatedLevel(speaking) returns the same getters, driven by a speech model (syllables, gaps between words, a phrase contour), so demos and tests look like someone talking. useChatcnVoiceMock drives a whole scripted call.
Options
| Option | Default | Notes |
|---|---|---|
updateRate | 20 | Hz for the level and bands state. 0 disables state |
bands | 0 | Band count for the bands state. getBands(n) works regardless |
floorDb, ceilingDb | -60, -12 | dBFS mapped onto 0 and 1 |
attack, release | 30, 7 | Envelope rates per second: snappy rise, gentle fall |
frequencyRange | [80, 8000] | Hz range of the bands, the speech range by default |
Returns
| Value | Type | Notes |
|---|---|---|
level | number | Smoothed level, throttled to updateRate |
bands | number[] | Throttled band levels when bands is set |
getLevel | () => number | Current level. One computation per frame however many readers |
getBands | (count) => Float32Array | Log-spaced bands, lowest first |
active | boolean | A source is connected and the audio context runs |
error | Error | undefined | For example a cross-origin media URL without CORS |
Notes
- One shared
AudioContextserves every meter. Browsers may start it suspended; it resumes on the next pointer or key press, and when a metered element plays. - A media element can be routed through Web Audio only once. The hook caches that route per element and keeps the element audible.
useChatcnMicrophonestops every track on stop and unmount, so the browser's recording indicator goes away when it should. Its errors come with messages that say how to fix them.