- Implement real-time streaming preview using Parakeet EOU (160ms chunks)
- Add batch transcription on completion for accurate final result
- Prefer Whisper large-v3-turbo (2.7% WER) over Parakeet (6.05% WER) when available
- Remove audio preprocessing that hurts ASR accuracy (gain control, noise reduction)
- Add streaming audio callback support in Recorder and CoreAudioRecorder
- Raw audio passthrough - SDK handles resampling internally
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New low-level recorder targeting devices directly. Includes device switching during recording, enhanced logging (transport type, format, buffer), and log export feature.
Move API keys from UserDefaults to secure Keychain storage. Add KeychainService and APIKeyManager for centralized key management. Enable iCloud Keychain sync for cross-device sharing between macOS and iOS.
Migrates vocabulary words and word replacements from UserDefaults to SwiftData for better data management and persistence.
Changes:
- Create VocabularyWord and WordReplacement SwiftData models
- Add dual ModelConfiguration setup (default.store for transcripts, dictionary.store for dictionary data)
- Implement DictionaryMigrationService for one-time UserDefaults→SwiftData migration
- Rename "Correct Spellings" to "Vocabulary" for clearer terminology
- Update all dictionary views to use @Query instead of manager classes
- Update all services to fetch from SwiftData using FetchDescriptor
- Enhance word replacement duplicate detection (now checks during add AND edit)
- Update import/export services to work with SwiftData
- Preserve all existing functionality with improved data integrity
Technical details:
- Separate store files: default.store (transcripts) + dictionary.store (vocabulary + replacements)
- Migration flag: "HasMigratedDictionaryToSwiftData_v2"
- All CRUD operations properly implemented with duplicate detection
- Create centralized registry for managing transcription services
- Replace duplicate switch statements across 4 manager classes
- Consolidate service initialization into single registry pattern
- Add cleanup method to registry for resource management
- Ensure fresh service registry on each transcription request
The screen capture service was selecting the first layer-0 window, which
during recording was VoiceInk's own status indicator overlay. This caused
OCR to always return 'No text detected' since the overlay has no readable
content.
Changes:
- Filter out windows owned by VoiceInk's process
- Prioritize windows belonging to NSWorkspace.frontmostApplication
- Refactor WindowCandidate struct to class scope
The screen capture service was selecting the first layer-0 window, which
during recording was VoiceInk's own status indicator overlay. This caused
OCR to always return 'No text detected' since the overlay has no readable
content.
Changes:
- Filter out windows owned by VoiceInk's process
- Prioritize windows belonging to NSWorkspace.frontmostApplication
- Filter out tiny windows (<120x120) to avoid tooltips/overlays
- Move CGWindowListCopyWindowInfo off main thread for better UI responsiveness
- Refactor WindowCandidate struct to class scope