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>
146 lines
5.3 KiB
Markdown
146 lines
5.3 KiB
Markdown
# 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
|