3.9 KiB
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-turbovia 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
- Fn omlaag: opname start, overlay verschijnt.
- Fn omhoog: opname stopt.
- Samples gaan naar
Transcriber, daarna naarCleaner. TextInsertervoegt 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
DictationControllermet fakeTranscriber,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)
- Package plus menubalk-app; hotkey logt alleen "recording…".
- Opnemen naar een buffer.
- WhisperKit transcriberen.
- Tekst invoegen.
- Overlay-pill.
- Cleanup, instellingen en branding (aparte specs).
Open punten
Geen voor het skeleton. De definitieve naam en branding worden in een latere stap bepaald.