What you’re building
The UX contract that makes dictation feel instant: show partials immediately as provisional text (greyed, never committed), then replace them with finals as they land. The user sees words forming while they speak, and the text field only ever keeps stable output.The PyAI stack for this build
That is the whole stack. Everything else (the hotkey, the cursor insertion, the
text field) is your app.
Build order
1
Get a key with hear:stream
An instant sandbox key works for building. Production keys
are created in the console.
2
Open the streaming socket
Connect to
wss://api.pyai.com/v1/audio/transcriptions/stream and pass the
key as the pyai-key.<API_KEY> subprotocol (browsers cannot set headers on
a WebSocket). The full wire protocol, including query params and close
codes, is in the streaming STT guide.3
Capture mic audio as PCM16 frames
Use an AudioWorklet in the browser (or the native mic API on desktop) and
stream 16 kHz PCM16 chunks of about 20 ms each as binary frames.
4
Render partials greyed, commit finals
Each partial replaces the previous provisional text at the cursor; each
final locks in. This one rule is most of what makes dictation feel
professional instead of jittery.
5
Add the dictation polish
Push-to-talk vs. always-on, a
{"type":"commit"} flush when the user
pauses or releases the key, filler-word handling, and auto-punctuation
preferences. These are app-level decisions; the guide above covers the
commit semantics.