Files
Meeting_Assistant/openspec/changes/archive/2025-12-22-add-audio-device-selector/design.md
egg e7a06e2b8f chore: Archive all pending OpenSpec proposals
Force archive the following proposals:
- add-audio-device-selector (complete)
- add-embedded-backend-packaging (19/26 tasks)
- add-flexible-deployment-options (20/21 tasks)

New specs created:
- audio-device-management (7 requirements)
- embedded-backend (8 requirements)

Updated specs:
- transcription (+2 requirements for model download progress)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 08:44:04 +08:00

146 lines
5.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design: add-audio-device-selector
## Architecture Overview
### Component Structure
```
meeting-detail.html
├── Audio Device Panel (新增)
│ ├── Device Selector (dropdown)
│ ├── Volume Meter (canvas/div bars)
│ ├── Test Controls
│ │ ├── Start Test Button
│ │ ├── Stop Test Button
│ │ └── Play Test Button
│ └── Status Indicator
└── Existing Recording Controls
└── Uses selected device from panel
```
### Data Flow
```
User selects device → Update localStorage → Update AudioContext
→ Start volume monitoring
→ Enable test recording
Test Recording Flow:
Start Test → getUserMedia(selected device) → MediaRecorder → Blob
Play Test → Audio element → Play blob URL
Main Recording Flow:
Start Recording → Read selected device from state
→ getUserMedia(selected device)
→ Existing transcription flow
```
## Technical Decisions
### TD-1: Volume Meter Implementation
**Options Considered:**
1. **Web Audio API AnalyserNode** - Real-time frequency/amplitude analysis
2. **MediaRecorder + periodic sampling** - Sample audio levels periodically
3. **CSS-only animation** - Fake animation without real audio data
**Decision:** Web Audio API AnalyserNode
- Provides accurate real-time audio level data
- Low latency visualization
- Standard browser API, well-supported in Electron
### TD-2: Device Preference Storage
**Options Considered:**
1. **localStorage** - Simple key-value storage
2. **config.json** - App configuration file
3. **Backend database** - Per-user settings
**Decision:** localStorage
- No backend changes required
- Immediate persistence
- Per-device settings (user may use different mics on different computers)
### TD-3: Test Recording Duration
**Decision:** 5 seconds fixed duration
- Long enough to verify audio quality
- Short enough to not waste time
- Auto-stop prevents forgotten recordings
### TD-4: UI Placement
**Options Considered:**
1. **Modal dialog** - Opens on demand
2. **Collapsible panel** - Always visible but can be collapsed
3. **Settings page** - Separate page for audio settings
**Decision:** Collapsible panel in meeting-detail page
- Quick access before recording
- No page navigation needed
- Can be collapsed when not needed
## UI Mockup
```
┌─────────────────────────────────────────────────────────┐
│ Audio Device Settings [▼] │
├─────────────────────────────────────────────────────────┤
│ Microphone: [▼ Realtek Microphone (Realtek Audio) ▼] │
│ │
│ Input Level: ████████░░░░░░░░░░░░ 45% │
│ │
│ [🎤 Test Recording] [▶️ Play Test] Status: Ready │
│ │
Click "Test Recording" to verify your microphone │
└─────────────────────────────────────────────────────────┘
```
## State Management
### Audio Device State
```javascript
const audioDeviceState = {
availableDevices: [], // Array of MediaDeviceInfo
selectedDeviceId: null, // Selected device ID or null for default
isMonitoring: false, // Volume meter active
currentLevel: 0, // Current audio level 0-100
testRecording: null, // Blob of test recording
testState: 'idle' // 'idle' | 'recording' | 'playing'
};
```
### localStorage Keys
- `audioDevice.selectedId` - Last selected device ID
- `audioDevice.lastUsedLabel` - Device label for display fallback
## Integration Points
### With Existing Recording
1. `startRecording()` will read `selectedDeviceId` from state
2. If no device selected, use current auto-selection logic
3. If selected device unavailable, show error and prompt reselection
### IPC Considerations
- No new IPC handlers needed
- All audio device operations happen in renderer process
- Uses existing `navigator.mediaDevices` API
## Error Handling
| Error | User Message | Recovery |
|-------|-------------|----------|
| No devices found | "未偵測到麥克風,請連接麥克風後重試" | Refresh device list |
| Device disconnected | "選擇的麥克風已斷開連接" | Auto-switch to default |
| Permission denied | "麥克風權限被拒絕,請在系統設定中允許" | Show permission guide |
| Device busy | "麥克風正被其他應用程式使用" | Retry button |
## Testing Strategy
### Manual Testing
1. Connect multiple microphones
2. Verify all appear in dropdown
3. Select each and verify volume meter responds
4. Record and play test audio for each
5. Unplug device during use and verify error handling
6. Restart app and verify saved preference loads
### Automated Testing (Future)
- Mock `navigator.mediaDevices` for unit tests
- Test device switching logic
- Test localStorage persistence