refactor: 使用 @picovoice/web-voice-processor 替换手写音频采集管线

- 引入 WebVoiceProcessor 处理 getUserMedia、AudioContext 生命周期和 WASM 重采样
- 删除自定义 AudioWorklet (audio-processor.ts) 和线性插值重采样器 (resample.ts)
- 改善音频采集稳定性:自动检测 AudioContext suspended/closed 状态并重建
- 更精确的错误提示:区分权限拒绝、设备未找到、设备异常
This commit is contained in:
2026-03-02 07:42:45 +08:00
parent 677ef35ff7
commit 669bfac722
6 changed files with 61 additions and 181 deletions

View File

@@ -84,17 +84,12 @@ web/
app-store.ts # Zustand store: connection, recording, preview, history, toast
hooks/
useWebSocket.ts # WS client hook: connect, reconnect, message dispatch
useRecorder.ts # Audio pipeline hook: getUserMedia, AudioWorklet, resample
useRecorder.ts # Audio pipeline hook: WebVoiceProcessor (16kHz Int16 PCM capture)
components/
StatusBadge.tsx # Connection status indicator
PreviewBox.tsx # Real-time transcription preview
MicButton.tsx # Push-to-talk button with animations
HistoryList.tsx # Transcription history with re-send
Toast.tsx # Auto-dismiss toast notifications
lib/
resample.ts # Linear interpolation resampler (native rate → 16kHz Int16)
workers/
audio-processor.ts # AudioWorklet: PCM capture, 200ms frame accumulation
```
## Code Style — Go
@@ -158,8 +153,8 @@ Per-connection loggers via `slog.With("remote", addr)`.
- Custom hooks for imperative APIs: `useWebSocket`, `useRecorder`
- Zustand `getState()` in hooks/callbacks to avoid stale closures
- Pointer Events for touch/mouse (not touch + mouse separately)
- AudioWorklet for audio capture (not MediaRecorder)
- `?worker&url` Vite import for AudioWorklet files
- @picovoice/web-voice-processor for audio capture (16kHz Int16 PCM, WASM resampling)
- WebVoiceProcessor handles getUserMedia, AudioContext lifecycle, cross-browser compat
- WebSocket: binary for audio frames, JSON text for control messages
- Tailwind CSS v4 with `@theme` design tokens; minimal custom CSS (keyframes only)