本地優先的 macOS 繁體中文語音輸入與會議轉錄工具。 Local-first Traditional Chinese dictation and meeting transcription for macOS.
Website · Setup · Recognition modes · Privacy
Hold a hotkey, speak, release, and Open Dictate inserts the transcribed sentence at your cursor. The core path runs locally with MLX Whisper on Apple Silicon, then applies deterministic glossary correction owned by the user.
按住快捷鍵、說話、放開,Open Dictate 會把轉錄後的文字插入目前游標位置。核心流程在 Apple Silicon 上本地執行 MLX Whisper,並套用使用者擁有的確定性詞庫校正。
Open Dictate is not only a Whisper wrapper. The long-term loop is:
Open Dictate 不只是 Whisper 包裝器。完整方向是這個閉環:
Speak / record
→ local transcription
→ deterministic correction
→ speaker-aware transcript
→ possible mishearing candidates
→ human review
→ personal glossary improves
→ next transcription gets better
Design rule: the system may flag and suggest, but it must not silently rewrite meaning.
設計原則:系統可以標記、可以建議,但不能靜默改寫意思。
| 功能 / Feature | 狀態 / Status |
|---|---|
| Push-to-talk dictation / 按住說話輸入 | Public seed |
| Local MLX Whisper daemon / 本地 Whisper 常駐 daemon | Public seed |
| Fast and accurate recognition modes / 快與準兩種辨識模式 | MVP: on by default since 0.7.1, see docs/RECOGNITION-MODES.md |
| Deterministic glossary correction / 確定性詞庫校正 | Public seed |
| Traditional Chinese punctuation / 繁中全形標點 | Public seed |
| Menubar teaching flow / 選單列教詞庫 | Public seed |
| Meeting transcript package / 會議逐字稿包 | Public seed: audio or JSON/JSONL segments |
| Local audio ASR for Meeting Mode / 會議模式本地音檔 ASR | Public seed: MLX Whisper adapter |
| Post-transcription QA / 轉錄後誤聽偵測 | MVP: review flags |
| Review-first glossary growth / 審核優先詞庫成長 | MVP: CLI queue |
| Anonymous speaker labels / 匿名說話者標籤 | MVP |
| Local speaker identity / 本機說話者身分 | Planned, sensitive optional layer |
Audio stays local by default. Dictation logs, meeting transcripts, review queues, personal glossaries, and speaker profiles belong to the user and should live under local paths such as ~/.open-dictate/.
音檔預設留在本機。語音輸入日誌、會議逐字稿、審核佇列、個人詞庫、說話者資料都屬於使用者,應放在 ~/.open-dictate/ 這類本機路徑。
Speaker embeddings and voiceprints are biometric data. Open Dictate's public repo only ships interfaces, schemas, and fictional examples. Real speaker profiles must stay local and must not be committed.
聲紋與說話者 embedding 是生物特徵資料。Open Dictate 的公開 repo 只提供介面、schema 與虛構範例;真實說話者資料必須留在本機,不能 commit。
Read: docs/PRIVACY.md
git clone https://github.com/frank890417/open-dictate.git
cd open-dictate
./install.sh # standalone install: .venv-dictate, starter glossaries, fast + accurate recognition modes (starts in fast)
./install.sh --plan # optional first: what it will install and download, changing nothingThe installer sets up both recognition modes and starts in fast (Qwen3-ASR 1.7B); the accurate mode (Whisper large-v3-turbo) is one menu click away. It downloads the models from Hugging Face (4.1 GB for both) and asks first: it prints the sizes and how long they take at 25, 100 and 500 Mbps, and waits for a yes (--yes when there is no terminal). ./install.sh --recognition accurate starts in accurate; ./install.sh --recognition off keeps a single Whisper model (1.6 GB). Model warm-up can take another minute; the installer shows progress and waits up to 180 seconds before printing diagnostics.
安裝程式會把快、準兩種辨識模式都裝好,並從快(Qwen3-ASR 1.7B)開始,準(Whisper large-v3-turbo)在選單列點一下就切過去。模型從 Hugging Face 下載(兩個共 4.1 GB),安裝程式會先問:列出大小與 25、100、500 Mbps 各要等多久,等你回答 y(沒有終端機時加 --yes)。./install.sh --recognition accurate 從準開始,./install.sh --recognition off 只留一個 Whisper 模型(1.6 GB)。模型載入可能再花約一分鐘。安裝器會顯示進度,最多等待 180 秒,逾時則印出診斷資訊。
First-time permissions / 第一次使用需要開權限:
- System Settings → Privacy & Security → enable OpenDictate for:
- Accessibility
- Input Monitoring
- Microphone
- If you use the
fnhotkey: Keyboard → “Press 🌐 key to” → Do Nothing. Disable Apple Dictation'sfnshortcut and quit other dictation apps that capture the same key. - Click any text field, hold
fn, speak, release.
Diagnostics and uninstall / 診斷與解除安裝:
./scripts/doctor.sh # read-only checks; does not install or start anything
./uninstall.sh # removes app + LaunchAgents, keeps ~/.open-dictate
./uninstall.sh --purge-data # prints manual data-removal guidance; never deletes user dataFull setup: docs/SETUP.md
- Push-to-talk:
fnor right Option. - 16 kHz mono PCM16 recording → Python daemon → corrected text insertion.
- Short-press and silence gates reduce accidental hallucinations.
- Repetition-loop guard (v0.5.3): Whisper degenerates into token loops at both
ends of the duration range — very short clips and long dictations — repeating one
character or phrase until the window ends. A deterministic tail pass removes the
runaway and falls back to
no_speechwhen the whole utterance is a loop. It is conservative by design: natural emphasis such as對對對對is left untouched. - Length-aware punctuation budget (v0.5.3): the optional LLM punctuation pass
rewrites the whole segment, so its cost grows with text length. A fixed timeout made
long dictations structurally impossible to complete. The budget is now
min(4.0 + chars × 0.025, 10.0)seconds. Note that length is not the only cause of timeouts — machine-wide contention is at least as common — so the timeout log line now prints characters, budget, elapsed time and machine load. - Robustness pass (v0.6.0): a background warm keeper stops cold-model requests from
cancelling the punctuation model load; only contextual pairs present in the sentence
are sent to the LLM; the daemon respects the shell deadline; ASR decode guards
(
sample_lenby duration, temperature capped at 0.4), a false-trigger gate, a subtitle-credit hallucination filter, a 200-token Whisper prompt with the style sentence at the end, and a fix for a regex that could block the daemon for minutes. Details: IO-CONTRACT §Daemon 0.6.0 robustness notes. - Punctuation fixes (v0.6.1): Whisper's small-form marks (
﹐﹑﹗﹖) are treated as pauses, not tone (comma mid-sentence, full stop at the end;﹖stays?only when the clause has a question word), and an enumeration comma right before a coordinating conjunction is removed or turned into a comma after the punctuation layer. Daemon-internal; wire protocol stays 1.0. - Fast and accurate recognition modes (v0.7.0; on by default in the installer since 0.7.1): the daemon keeps two models
loaded in a separate worker process and switch between them from the menu bar, the CLI or
the socket, without a restart. Fast is Qwen3-ASR 1.7B with its own punctuation; accurate is
Whisper (large-v3-turbo by default, large-v3 optional) with your glossary as the prompt. A
crash in the recognition worker (an MLX segfault) kills only the worker: it restarts by
itself and the daemon stays up. The
installer starts in fast and asks before it downloads the models;
./install.sh --recognition offkeeps the single-Whisper setup. Choices, downloads, licences and measured speed:docs/RECOGNITION-MODES.md. 快與準兩種辨識模式(v0.7.0,安裝程式從 0.7.1 起預設開啟):安裝程式從快開始,下載模型前會先問。./install.sh --recognition off維持單一 Whisper。選項、下載內容、授權與實測速度見上述文件。 - The punctuation model is loaded only when it is needed (v0.7.2): the optional LLM punctuation asks Ollama for
a 21 GB model; the daemon now does that only for a sentence that goes to the LLM (accurate mode,
llm_zh), never in fast mode.OPEN_DICTATE_PUNCT_WARM=1loads it at start as before,=0never. 標點用的 LLM 只在需要時才載入(v0.7.2):快速模式永遠不載入。OPEN_DICTATE_PUNCT_WARM=1恢復開機載入,=0永遠不暖。 - Text insertion uses Accessibility direct insertion when possible, then paste fallback.
- Optional microphone selection.
Meeting Mode creates a reviewable transcript package from longer conversations. It now accepts local audio files through an MLX Whisper adapter, or pre-transcribed JSON/JSONL segments for integrations and tests. The public-safe default still uses anonymous speaker labels; real speaker identity / diarization is not silently guessed and remains a planned optional local layer.
會議模式把長對話整理成可審核的逐字稿包。現在可直接吃本機音檔,透過 MLX Whisper adapter 轉成分段逐字稿;也仍支援 JSON/JSONL 分段輸入,方便整合與測試。公開安全預設仍是匿名說話者標籤;真實說話者身分 / diarization 不會偷偷猜,仍是之後的本機可選層。
python3 daemon/meeting_cli.py export-demo --out /tmp/open-dictate-demo
python3 daemon/meeting_cli.py transcribe examples/meeting-segments.example.json --out /tmp/open-dictate-meeting
python3 daemon/meeting_cli.py transcribe ~/Desktop/meeting.m4a --out /tmp/open-dictate-meeting-audio --language zh
# Mixed English/Chinese recordings can use: --language autoRead: docs/MEETING.md
Open Dictate can scan transcripts for possible mishearings and put candidates into a review queue. Accepted candidates update the user's local glossary; rejected candidates stay out.
Open Dictate 可以掃描逐字稿裡的疑似誤聽,把候選放進審核佇列。使用者接受後才寫入本機詞庫;拒絕的候選不會進入確定替換表。
python3 daemon/qa/mishear_detector.py examples/meeting-segments.example.json --json
python3 daemon/glossary/cli.py add "阿布西店" "Obsidian" --reason "near canonical term"
python3 daemon/glossary/cli.py candidatesRule: prefer missed corrections over wrong corrections.
規則:寧可漏改,不可錯改。
Read: docs/SELF-EVOLVING-GLOSSARY.md
The public-safe default is anonymous speaker labels:
公開安全預設是匿名說話者標籤:
SPEAKER_00
SPEAKER_01
Optional local speaker identity is planned. It must store profiles under local user-owned paths and treat voice embeddings as sensitive biometric data.
可選的本機說話者身分功能在路線圖中。它必須把資料存在使用者本機路徑,並把聲音 embedding 當成敏感生物特徵資料處理。
Read: docs/SPEAKER-ID.md
[Hotkey]
→ OpenDictate.app
→ /tmp/open-dictate.sock
→ dictated.py (MLX keep-warm)
→ deterministic lexicon correction
→ text insertion
→ ~/.open-dictate/dictation-log/
[Meeting audio or JSON/JSONL]
→ meeting_cli.py
→ local MLX Whisper audio ASR if needed
→ deterministic correction
→ anonymous speaker labels
→ QA flags
→ Markdown / JSONL / SRT / VTT
| Component | Path |
|---|---|
| Swift shell | OpenDictate/ |
| Dictation daemon | daemon/dictated.py |
| Recognition router, worker, remote server | daemon/asr_router.py, daemon/asr_worker.py, daemon/asr_server.py |
| Recognition benchmark | scripts/modes-bench.py |
| Installer's model check and download | scripts/install-recognition.py |
| Meeting CLI | daemon/meeting_cli.py |
| QA scanner | daemon/qa/mishear_detector.py |
| Review queue | daemon/glossary/ |
| Speaker layer | daemon/speaker/ |
| Starter glossaries | vendor/tools/td-subtitle/glossaries/ |
| Lexicon engine | vendor/tools/muse-lexicon/muse_lexicon.py |
| Dictation log | ~/.open-dictate/dictation-log/ |
Architecture and protocol: IO-CONTRACT.md
- Deterministic replacement only: glossary pairs may correct words; the system must not rewrite the sentence.
- Prefer missed corrections over wrong corrections.
- Traditional Chinese normalization is allowed; numeric meaning is not changed automatically.
- Audio stays local.
- UI must not steal focus from the current text field.
- Speaker profiles and voice embeddings are local-only sensitive data.
- Self-evolution is review-first, not silent self-mutation.
./build.sh
python3 -m unittest discover tests
python3 scripts/golden-bench.py --skip-daemon
python3 scripts/public-safety-scan.py
./scripts/smoke-test.shThe smoke test builds the app, runs deterministic tests, exports a meeting demo, checks helper scripts, and verifies the signed app bundle.
- Public-safe dictation seed.
- Bilingual README and privacy model.
- Meeting package MVP for JSON/JSONL segments.
- QA flags for possible mishearings and numbers.
- Review-first glossary queue CLI.
- Anonymous speaker label layer.
- Local audio ASR backend for Meeting Mode.
- Fast and accurate recognition modes, switchable without a restart (on by default in the installer since 0.7.1).
- Optional local speaker profile enrollment.
- Menubar UI for reviewing glossary candidates.
- Import/export for user-owned glossary packages.
- Remove runtime dependency on the source clone, developer Python, Swift, and Xcode Command Line Tools.
- Ship a self-contained beta
.appwith in-app permission onboarding, model download, diagnostics, and uninstall. - Release a Developer ID signed and Apple-notarized DMG with clean-Mac installation tests.
- Add signed in-app updates, rollback, and Stable/Beta release channels.
完整的 macOS 安裝與發布分階段規劃:docs/MACOS-DISTRIBUTION-ROADMAP.md
Detailed macOS packaging and distribution plan: docs/MACOS-DISTRIBUTION-ROADMAP.md
Open Dictate is an early public seed extracted from a private daily-use tool, then rebuilt as a public-safe no-history repository. The core dictation path works on Apple Silicon macOS. Meeting, QA, and speaker layers are intentionally conservative MVPs.
Open Dictate 目前是早期 public seed,從私人日用工具抽出後重新整理成公開安全、無歷史包袱的 repo。核心語音輸入路徑已可在 Apple Silicon macOS 上使用;會議、QA、說話者層目前是保守 MVP。
Issues and pull requests are welcome.
MIT. See LICENSE.