# Dictation and vocabulary

> Desktop dictation runs on your own OpenAI or Gemini key with hint vocabularies per project. Phones transcribe through HB Code services. The error classes tell you which layer failed.

Handbook / Bundled tools · Checked against the source on 2026-10-05 · https://www.hbcode.ai/docs/tools/dictation

## Set up dictation

**Only phone dictation goes through HB Code’s regional server**

Desktop dictation records in the desktop runtime and sends the audio with your API key and vocabulary straight to OpenAI or Gemini, and the transcript comes back into the composer. Over 25,000,000 bytes the desktop refuses before uploading to OpenAI. Phone dictation first borrows the desktop’s vocabulary prompt over the relay, then uploads the audio with its HB Code JWT to the regional server, which transcribes it with OpenAI under HB Code’s key and charges your credits. The server accepts up to 100 MiB, but its OpenAI call stops at 25 MiB.

- **Your key** (transcribe_with_provider): The desktop calls OpenAI or Gemini directly with the key saved under Settings → API Keys. HB Code’s servers see neither the audio nor the key.
- **HB Code’s key** (/api/audio/transcriptions): Phones upload with their HB Code JWT and ask for openai/gpt-4o-transcribe. The server refuses the upload without a positive credit balance and charges the transcription to your account.
- **Borrowed vocabulary** (system.voiceTranscriptionContext): Before uploading, the phone asks the desktop over the relay for its vocabulary prompt. Without an answer it uploads without one, and the server builds its own default prompt.

1. Open Settings → API Keys.
2. Save a personal OpenAI or Gemini API key.
3. Open Settings → Voice.
4. In the Voice Dictation card, select OpenAI or Gemini as the dictation service.
5. Click Save.
6. When the operating system asks for microphone access, allow it.

Dictation uses your own API key and is separate from the ChatGPT or Claude sign-in that runs the agent. The only accepted model IDs are gpt-4o-transcribe and gemini-flash-latest. Before the first recording the desktop sends a synthetic preflight WAV to the real provider endpoint and caches the result per provider and model for 15 minutes after a success and 5 minutes after a failure, or until you save settings again. OpenAI requests time out after 120 seconds.

Review Mode recordings go through the regional server to Gemini with POST /api/llm/video/analyze. On iPhone each capture’s narration is transcribed first. Review Mode in the iOS and Android media chapters has the details.

- [Dictation on iOS](https://www.hbcode.ai/docs/ios/media.md#dictation): Recording, retries, and the vocabulary prompt from the desktop.
- [Dictation on Android](https://www.hbcode.ai/docs/android/media.md#recording): The microphone foreground service and the upload.

## Add your words to the vocabulary

**OpenAI gives your vocabulary 265 of 1,000 bytes and cuts the project list first**

The OpenAI transcription prompt is limited to 1,000 bytes, drawn to scale. The escaped rules with their tags take 683 bytes, and a newline and the vocabulary tags take 52, so your vocabulary text gets the last 265 bytes. The global list comes first, so the project list is the part that gets cut. Gemini’s limit is 1,000,000 bytes: drawn at the same width, its full 1,836-byte rules are a thin line and the rest holds about a megabyte of vocabulary. A phone uses the same prompt when the desktop builds it for OpenAI.

- **Rules** (transcription_system_prompt): The compact rules for OpenAI take 622 bytes after XML escaping and 683 with their tags. The budget lets them use up to 720 bytes and keeps 280 for vocabulary.
- **Your vocabulary** (personal_vocabulary_kb): After the rules, a newline and 51 bytes of tags leave 265 bytes of text. The global list goes first, then the project list, both XML-escaped and cut at the limit, mid-word if need be. The split drawn here is an example.
- **Gemini** (transcription_prompt_max_bytes): Gemini gets the full rules, 1,836 bytes with tags, and room for about a megabyte of vocabulary, so nothing you are likely to type is cut.

Voice settings hold a global vocabulary and a per-project vocabulary. Put terms you use everywhere in the global list and repository-specific names in the project list. They travel as an XML-escaped spelling reference inside the transcription prompt with an explicit rule never to insert them. On OpenAI they get 265 bytes of text after the rules and tags, global list first.

## Error classes

| Visible problem | Check |
| --- | --- |
| Microphone unavailable | Make sure that the operating system gives HB Code access to the microphone. Dictation also needs a working audio input. |
| Provider not configured | Make sure that Settings → API Keys has a key for the dictation service. Make sure that Settings → Voice shows the saved dictation service. |
| Quota or rate limit | OpenAI only, classified from its 429 code and never from free text. Quota codes such as insufficient_quota, credit_balance_exhausted, and the spend or usage limits link to billing. Any other 429, such as rate_limit_exceeded or slow_down, is a rate limit that passes with time. A Gemini failure reads as a key problem and blocks Gemini dictation for 5 minutes, or until you save Voice settings. |
| Recording too large | The desktop refuses an OpenAI upload of more than 25,000,000 bytes. Record a shorter clip, or use Gemini. |
