Constructor
new WaveformPanel(workspace, callbacks)
Parameters:
| Name | Type | Description | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
workspace | object | the Workspace controller instance | ||||||||||||||||||||
callbacks | object | callback functions for region interactionsProperties
|
Classes
Methods
applyZoom(newZoom, anchorFracopt)
Applies a new zoom level to the WaveSurfer instance, updates the zoom label, and redraws the time ruler, minimap, and regions.
Parameters:
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
newZoom | number | desired zoom level (clamped to MIN_ZOOM..#maxZoom()) | ||
anchorFrac | number | | <optional> | null | if provided, the scroll position will be restored to this left-edge time fraction after the zoom re-renders |
attachScrollListener()
Attaches the scroll handler to WaveSurfer's scroll container. Must be called after WaveSurfer finishes loading (in onReady).
basePxPerSec() → {number}
Computes the number of pixels per second that makes the entire track fit exactly in the waveform container at zoom level 1.
Returns:
pixels per second
- Type:
- number
clearWaveformPanel()
Destroys the WaveSurfer instance and resets all audio and UI state to defaults.
clientXToTime(clientX) → {number}
Converts a clientX coordinate over the region lane to a time in seconds.
Parameters:
| Name | Type | Description |
|---|---|---|
clientX | number | viewport X coordinate |
Returns:
time in seconds
- Type:
- number
doZoom(newZoom)
Zooms to `newZoom` while keeping a fixed time point under the cursor or transport position. In cursor-anchor mode, computes the time fraction under the mouse and restores it after zoom so that pixel stays in place.
Parameters:
| Name | Type | Description |
|---|---|---|
newZoom | number | desired zoom level |
drawMinimap()
Redraws the minimap canvas, coloring bars by played/unplayed and viewport/non-viewport states, and positions the thumb overlay div.
drawRegions()
Redraws the region lane canvas from scratch using the cached render runs. Called on every frame during playback and on zoom/scroll/segment edits. Visual design: - Segments are grouped into "runs" (consecutive same-speaker segments with no large gap) and rendered as color bars that grow upward from the bottom. - Normal height ≈ 70% of lane; hovered ≈ 88%; selected/active = 100%. - Only the first and last segment of a run get rounded outer corners. - A speaker name label is drawn left-anchored inside each visible run. - If a split popup is open, a dashed vertical line shows the split preview.
getScrollEl() → {HTMLElement|null}
Returns the scrollable container element that WaveSurfer renders into. this is the parent of WaveSurfer's internal wrapper div. Returns null if no WaveSurfer instance exists yet.
Returns:
- Type:
- HTMLElement |
null
(async) initAudio(file)
Entry point for loading an audio file into the player. Validates the file, updates all relevant UI and AppState, then delegates the actual data work to loadAudioFile. Once loading completes, initialises WaveSurfer with the pre-computed peaks for fast zoom.
Parameters:
| Name | Type | Description |
|---|---|---|
file | File | must have type starting with "audio/" |
initWaveSurfer()
Creates (or re-creates) the WaveSurfer instance and registers all event handlers. Called both on initial file load and when switching projects. The old instance must be destroyed before calling this (resetWorkspace does it).
loadAudioFile(file)
Loads a local audio file: reads it as an ArrayBuffer, decodes it via the Web Audio API to extract sample rate and multi-channel buffers, then offloads peak extraction to an inline Web Worker so the UI stays responsive during processing. When the worker finishes, WaveSurfer is initialised with the pre-computed peaks for fast zoom.
Parameters:
| Name | Type | Description |
|---|---|---|
file | File | must have type starting with "audio/" |
loadFromProject(project)
Loads waveform data from the given project and draws regions.
Parameters:
| Name | Type | Description |
|---|---|---|
project | Project | the project to load waveform data from |
(async) loadWaveform()
Initialises WaveSurfer and loads the waveform URL from the active project. For server files without pre-computed peaks, checks the remote file size via a HEAD request and — if the file is large — extracts peaks in chunks using HTTP Range requests before handing off to WaveSurfer, preventing the tab from running out of memory on long recordings. Logs a warning if the waveform URL is not defined.
onFinish()
WaveSurfer 'finish' handler — playback reached the end naturally.
onLoading(percent)
WaveSurfer 'loading' handler — fires periodically during remote audio fetch.
Parameters:
| Name | Type | Description |
|---|---|---|
percent | number | loading progress 0–100 |
onPause()
WaveSurfer 'pause' handler — updates button icon and status indicators.
onPlay()
WaveSurfer 'play' handler — updates button icon and status indicators.
onReady()
WaveSurfer 'ready' handler — fires once the audio is fully decoded and ready. Two-pass peak extraction strategy: 1. First ready (no cachedWaveformPeaks): extract peaks from the decoded buffer and reload the file with them. this enables fast zooming without re-decode. 2. Second ready (_peaksInjected = true): skip extraction and finish normal setup. For server-streamed files, peaks weren't pre-computed before loading, so this path always runs. For local drag-drop, peaks are pre-computed in the Worker inside this.loadAudioFile(), so cachedWaveformPeaks is already set and the first pass is skipped.
onTimeUpdate(t)
WaveSurfer 'audioprocess' handler — fires frequently during playback. Coalesces updates via requestAnimationFrame to avoid redundant DOM writes. Handles: timecode display, playback-progress fraction, minimap, region highlight, transcript highlight, and follow-playhead auto-scroll.
Parameters:
| Name | Type | Description |
|---|---|---|
t | number | current playback time in seconds |
onWaveformScroll()
Scroll handler attached to WaveSurfer's internal scroll container. If a pendingScrollFrac is set (from applyZoom), applies the stored scroll position immediately and clears it; otherwise defers redraw to the next frame.
regionIndexAtTime(time) → {number}
Returns the index of the region at the given time
Parameters:
| Name | Type | Description |
|---|---|---|
time | number | time in seconds to look up |
Returns:
the segment index at the given time, or -1 if none
- Type:
- number
regionIndexAtX(clientX) → {number}
Given a mouse clientX coordinate over the region lane, returns the index of the transcript segment whose time range covers that position.
Parameters:
| Name | Type | Description |
|---|---|---|
clientX | number | mouse X in viewport coordinates |
Returns:
segment index, or -1 if no segment at that position
- Type:
- number
resetZoom()
Resets the zoom level to 1× (fit entire track in visible width).
resizeMinimap()
Sizes the minimap canvas to the wrapper's current CSS dimensions × dpr. Called on resize and after WaveSurfer reports 'ready'.
setHoveredRegion(regionIdx)
Updates the hovered region index and redraws the region canvas.
Parameters:
| Name | Type | Description |
|---|---|---|
regionIdx | number | segment index, or -1 to clear |
setSelectedRegion(regionIdx)
Seeks the playhead to the start of the selected segment and redraws.
Parameters:
| Name | Type | Description |
|---|---|---|
regionIdx | number | segment index, or -1 to clear |
setStatus(left, rightopt)
Updates the status bar text. If `right` is omitted, only the left side changes.
Parameters:
| Name | Type | Attributes | Description |
|---|---|---|---|
left | string | e.g. 'PLAYING', 'READY' | |
right | string | <optional> | e.g. '42.3%' |
setWaveformHeight(h)
Sets the waveform panel height (clamped to 40–400px), updates the CSS variable, and redraws the minimap and regions.
Parameters:
| Name | Type | Description |
|---|---|---|
h | number | desired height in pixels |
setupHandleDrag(el, side)
Registers a mousedown listener on a minimap edge handle that initiates a resize drag (changes zoom level by adjusting the visible fraction).
Parameters:
| Name | Type | Description |
|---|---|---|
el | HTMLElement | the handle element |
side | 'left' | | which edge is being dragged |
skipN(skipSeconds)
Seeks the playhead forward or backward by skipSeconds.
Parameters:
| Name | Type | Description |
|---|---|---|
skipSeconds | number | seconds to skip (negative = backward) |
timeToClientX(time) → {number}
Converts a time (seconds) to a clientX coordinate over the region lane.
Parameters:
| Name | Type | Description |
|---|---|---|
time | number | seconds |
Returns:
clientX in viewport pixels
- Type:
- number
togglePlay()
Toggles WaveSurfer playback.
updateTimeRuler()
Rebuilds the time ruler tick marks to match the current zoom level and scroll position. Tick interval is chosen from a set of "nice" values so there are approximately 8 visible ticks at any zoom. At very high zoom (≤10s visible) timestamps include decimal seconds.
updateTransportLabel()
Repositions the yellow transport line label to match the current playback position. Hides the label when the transport cursor is scrolled out of view.
zoomIn(amount)
Increases the zoom level by multiplying by amount.
Parameters:
| Name | Type | Description |
|---|---|---|
amount | number | multiplier (e.g. 1.25) |
zoomOut(amount)
Decreases the zoom level by dividing by amount.
Parameters:
| Name | Type | Description |
|---|---|---|
amount | number | divisor (e.g. 1.25) |
zoomToParagraph(paragraphIdx)
Zooms the waveform to the time range of the paragraph at the given index.
Parameters:
| Name | Type | Description |
|---|---|---|
paragraphIdx | number | index of the paragraph to zoom to |
zoomToRegion(regionIdx)
Zooms the waveform so the specified segment occupies ~50% of the visible width, then scrolls to center it. Uses two nested rAF calls to wait for WaveSurfer to finish re-rendering at the new zoom level before scrolling.
Parameters:
| Name | Type | Description |
|---|---|---|
regionIdx | number | segment index to zoom to |