Usage
WaveformPlayer from @prepared/ui-waveform-player is the full-fidelity review surface for audio where operators need to see the clip's shape—amplitude over time, silence regions, overlapping speakers—while they listen. It wraps WaveSurfer.js with Prepared styling, an imperative ref, and first-class support for WaveformRegion annotations.
Reach for it when review is the task itself, not a quick sample. Long-form calls, training clips, evidence with annotations, and any workflow that pairs audio with a transcript are its territory.
Use WaveformPlayer when operators need to mark, label, or jump between segments of a clip—redacted spans, training flags, QA highlights. The region overlay makes the workflow visual; pairing regions with a keyboard-navigable list keeps it accessible.
When an audio surface sits alongside a transcript (QA review, coaching review), WaveformPlayer synchronizes well: the transcript drives seeks via the imperative ref, and the waveform provides a spatial map of the conversation. Keep both in view; don't stack them behind tabs.
The waveform pays for itself on longer clips, where scrubbing blind in an AudioPlayer is slow and error-prone. Below ~2 minutes, the inline player is usually the better fit.
AudioPlayer in-row; the waveform is heavy for cells.ref.play / ref.pause.WaveformRegion[] pass through to the canvas. Each region has an id, start, end, optional label, and color. Keep id stable so downstream code can map back to a domain object.play, pause, seekTo, getCurrentTime, addRegion, removeRegion, zoomTo—expose whichever actions your product UX needs, but don't hide core controls behind imperative-only paths.Large clips take time to decode. Render a loading placeholder with accessible text during decode; on error, show an inline message and keep retry reachable. Don't let the canvas crash silently.
Adding or removing regions should feel lossless. Edits to region boundaries should animate minimally (respect prefers-reduced-motion); selection state changes should update both the canvas overlay and any adjacent region list.
When zoom is exposed, anchor it to the playhead or the last selected region, not to the canvas center. Users expect the position they're focused on to stay in view after a zoom change.
When transcripts or external buttons drive playback, keep the internal controls hidden to avoid two sources of truth. Let ref.play and ref.pause remain the programmatic surface and hide the cluster via prop.
Do
Don't
WaveformPlayer in dense tables; the canvas is too heavy for row cells.Waveform canvases are inherently visual, so paired text paths (transcripts, region lists, time readouts) are required for screen reader users. See the Accessibility page for keyboard seek patterns, region announcements, and fallback paths when the canvas is unavailable.