Description Context
Speech preview uses AnalyserNode.getByteTimeDomainData + per-frame conversion to Float32Array for waveform bars.
UI updates occur at ~60fps via onVisualizationUpdate and Waveform rAF loop.
Evidence
src/lib/audio/AudioEngine.ts → getBarLevels() converts Uint8Array to Float32Array every call.
src/App.tsx → onVisualizationUpdate calls appStore.setBarLevels(audioEngine.getBarLevels()) every tick.
src/components/Waveform.tsx draws every rAF, even when not recording.
Impact
Continuous preview work adds CPU even when transcription is idle; can be a top driver during capture.
Actions
Throttle preview updates to <=20–30fps (separate from inference tick).
Skip getByteTimeDomainData when isRecording is false or widget is hidden.
Consider downsampling the analyser buffer (e.g., 256 → 64) or reusing a single Float32Array without per-frame allocations.
Optionally compute preview in AudioWorklet and send only min/max to UI.
Acceptance
Preview CPU drops measurably with recording active but model idle.
Trace shows reduced main-thread activity during capture when only preview is running.
Reactions are currently unavailable
You can’t perform that action at this time.
Context
AnalyserNode.getByteTimeDomainData+ per-frame conversion to Float32Array for waveform bars.onVisualizationUpdateandWaveformrAF loop.Evidence
src/lib/audio/AudioEngine.ts→getBarLevels()convertsUint8ArraytoFloat32Arrayevery call.src/App.tsx→onVisualizationUpdatecallsappStore.setBarLevels(audioEngine.getBarLevels())every tick.src/components/Waveform.tsxdraws every rAF, even when not recording.Impact
Actions
getByteTimeDomainDatawhenisRecordingis false or widget is hidden.Acceptance