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>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user