Add push-to-talk dictation design spec
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# Push-to-talk dictatie-app voor macOS — ontwerp
|
||||
|
||||
Datum: 2026-10-01 · Status: concept ter review · Werktitel: `Sst`
|
||||
|
||||
## Doel
|
||||
|
||||
Een systeembrede dictatie-app, vergelijkbaar met Wispr Flow. De gebruiker houdt **Fn** ingedrukt, spreekt, laat los, en de transcriptie verschijnt op de cursor in elke app. Alles draait lokaal op de Mac. Nederlands en Engels mogen door elkaar gebruikt worden.
|
||||
|
||||
## Buiten scope (v1)
|
||||
|
||||
- AI-cleanup (vulwoorden, zelfcorrecties, toon per app). Alleen de naad (`Cleaner`) wordt voorbereid.
|
||||
- Streaming-transcriptie tijdens het praten.
|
||||
- Mac App Store-distributie, accounts, sync, cloud.
|
||||
- Branding. Die volgt als aparte stap na de werkende kern.
|
||||
|
||||
## Doelomgeving
|
||||
|
||||
Apple M4 Pro, 24 GB RAM, macOS 27, Xcode 27, Swift 6.4. Alleen Apple Silicon.
|
||||
|
||||
## Aannames
|
||||
|
||||
- Persoonlijk gebruik, niet-gesandboxed. De Mac App Store-sandbox verbiedt globale key-taps en gesimuleerd plakken.
|
||||
- Niets verlaat de Mac. Audio wordt niet bewaard.
|
||||
- Spraakmodel: Whisper `large-v3-turbo` via WhisperKit, met automatische taalherkenning.
|
||||
|
||||
## Architectuur
|
||||
|
||||
Een macOS-menubalk-app (SwiftUI `MenuBarExtra`). De logica staat in een Swift Package (testbaar met `swift test`). De Xcode-app is een dunne schil eromheen.
|
||||
|
||||
| Unit | Taak | Afhankelijk van |
|
||||
|---|---|---|
|
||||
| `HotkeyMonitor` | Detecteert Fn omlaag/omhoog via `CGEventTap`; stuurt `pressed`/`released` events | Input Monitoring |
|
||||
| `AudioRecorder` | `AVAudioEngine` neemt op naar een 16 kHz mono Float-buffer; start bij `pressed`, stopt bij `released` | Microfoon |
|
||||
| `Transcriber` (protocol) | `transcribe(samples) async throws -> String`; eerste implementatie `WhisperKitTranscriber` | WhisperKit |
|
||||
| `Cleaner` (protocol) | `clean(text, context) async throws -> String`; v1 `PassthroughCleaner` | n.v.t. |
|
||||
| `TextInserter` | Zet tekst op het klembord, simuleert ⌘V, herstelt het klembord | Accessibility |
|
||||
| `DictationController` | Statemachine `idle → recording → transcribing → inserting → idle`; enige component dat de andere kent | bovenstaande |
|
||||
| `OverlayPanel` | Floating `NSPanel` met pilletje: opname, golfvorm, bezig | SwiftUI |
|
||||
| `MenuBarExtra` | Status, instellingen, model-download, rechten-check | n.v.t. |
|
||||
|
||||
Ontwerpprincipes: elke unit heeft één taak en een duidelijke interface. `Transcriber` en `Cleaner` zijn protocollen, zodat modellen (bijvoorbeeld Parakeet of een LLM) later verwisselbaar zijn. Tests gebruiken fakes voor de protocollen.
|
||||
|
||||
## Dataflow
|
||||
|
||||
1. Fn omlaag: opname start, overlay verschijnt.
|
||||
2. Fn omhoog: opname stopt.
|
||||
3. Samples gaan naar `Transcriber`, daarna naar `Cleaner`.
|
||||
4. `TextInserter` voegt de tekst in; overlay verdwijnt.
|
||||
|
||||
Het model wordt bij het opstarten geladen en blijft warm in het geheugen.
|
||||
|
||||
## Foutafhandeling
|
||||
|
||||
- Opname korter dan ~0,3 s: negeren (per ongeluk aangetikt).
|
||||
- Rechten ontbreken: menubalk toont wat ontbreekt, met knop naar de juiste Systeeminstellingen.
|
||||
- Model nog niet gedownload: eerste start toont voortgang; dictatie is dan uitgeschakeld.
|
||||
- Invoegen mislukt: tekst blijft op het klembord, overlay meldt dit.
|
||||
- Stilte of lege transcriptie: niets invoegen.
|
||||
- Transcriptiefout: overlay toont een korte foutmelding; de controller keert terug naar `idle`.
|
||||
|
||||
## Vereiste rechten
|
||||
|
||||
Microfoon, Accessibility (plakken simuleren), Input Monitoring (Fn-toets).
|
||||
|
||||
## Testen
|
||||
|
||||
- Unit-tests voor `DictationController` met fake `Transcriber`, `Cleaner`, `TextInserter` (toestandsovergangen, korte opnames, foutpaden).
|
||||
- Unit-test voor het klembord-herstel in `TextInserter` (injecteerbare pasteboard).
|
||||
- Handmatige rooktest van de hele keten in TextEdit, Notes en een browser: Nederlands, Engels en gemengd.
|
||||
|
||||
## Bouwvolgorde (skeleton eerst)
|
||||
|
||||
1. Package plus menubalk-app; hotkey logt alleen "recording…".
|
||||
2. Opnemen naar een buffer.
|
||||
3. WhisperKit transcriberen.
|
||||
4. Tekst invoegen.
|
||||
5. Overlay-pill.
|
||||
6. Cleanup, instellingen en branding (aparte specs).
|
||||
|
||||
## Open punten
|
||||
|
||||
Geen voor het skeleton. De definitieve naam en branding worden in een latere stap bepaald.
|
||||
Reference in New Issue
Block a user