Model or dataset
HaujetZhao/CapsWriter-Offline avatar
HaujetZhao/CapsWriter-Offline

CapsWriter-Offline: Hold CapsLock, Speak, and Text Appears on Windows

PC 端语音输入工具,离线识别,高准确率、低延迟,支持热词、LLM润色。按住CapsLock或鼠标侧键X2说话,松开自动上屏。

6,808 stars625 forksPythonMIT

At a glance

What is it?
CapsWriter-Offline is a Windows-only, fully offline dictation tool built on Sherpa-ONNX and FunASR. It is fast and configurable, but the platform boundary and the two-process setup are real constraints, not footnotes.
Who is it for?
Adopt CapsWriter-Offline if you dictate on Windows 10 or 11, want audio to stay on the machine, and are willing to edit config_server.py and config_client.py by hand. Do not adopt it if you need macOS or Linux, if you cannot keep start_client.exe running, or if you need to dictate into elevated applications without running the client as administrator.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem: Dictation That Never Leaves the Machine

Cloud dictation services assume a network round trip for every utterance. CapsWriter-Offline removes that assumption. The README states the tool is fully offline and built specifically for Windows, and the pitch is a physical one: hold CapsLock or mouse side button X2, speak, release, and the text is typed into whatever window has focus. The README also notes that trailing commas and periods are stripped by default, which is the kind of detail that only matters if you dictate prose all day.

The intended user is someone on a Windows 10 or 11 machine who cannot or will not send audio to a server. The README mentions confidential machines and a USB stick as a deployment story, and it says the software needs no installation. That is a narrower audience than a general transcription tool. It is for people who type into other applications and want the transcription to behave like a keyboard, not like a document editor.

Client, Server, and the Cost of Splitting Them

The architecture is a client/server pair. start_server.exe loads the recognition model and stays in the tray. start_client.exe captures the hotkey, records audio, sends it to the server, receives text, and types it. The README gives one concrete reason for the split: a Windows 7 machine cannot run the server models, but it can still run the client for input. That is a real compatibility argument, and it is the only one the README makes.

The trade-off is operational. Two processes must be alive for dictation to work. The FAQ addresses the most common failure directly: if pressing the key does nothing, check that the start_client.exe console window is still running. It also states that to type into a program running with administrator privileges, the client must also run as administrator. That is a Windows input-injection boundary, not a bug, and it affects anyone dictating into an elevated terminal or installer.

Audio does not vanish after transcription. The README says every recording is saved to local audio files under a year/month/assets path, and that a diary archive stores each utterance with its recognition result by date. For privacy-sensitive work this is a feature. For anyone dictating passwords or client names, it is a retention policy that exists whether or not you asked for it.

Four Engines and the Accuracy/Latency Trade

The README lists four engines with different accuracy and speed profiles. Paraformer is ONNX-only with no GPU acceleration. SenseVoice-Small is ONNX with GPU acceleration. Fun-ASR-Nano uses ONNX plus GGUF and supports GPU acceleration. Qwen3-ASR is the most accurate in the table and the slowest, also ONNX plus GGUF with GPU acceleration. The release notes add detail: v2.5 introduced the Qwen3-ASR-1.7B model, and v2.4 added DirectML acceleration for the Fun-ASR-Nano encoder.

The README also publishes a latency table for 20-second audio, measured on a CPU U9-285H and a GPU RTX5050. Paraformer and SenseVoice-Small both sit at 0.6s on CPU, with SenseVoice-Small dropping to 0.15s on GPU. Fun-ASR-Nano goes from 2.0s on CPU to 0.5s on GPU. Qwen3-ASR-1.7B goes from 4.0s on CPU to 1.0s on GPU. These are the project's own figures, not independent measurements, and the hardware is high-end. On older laptops the gaps will be wider.

The practical reading: if you want the lowest latency, SenseVoice-Small on a supported GPU is the fastest option in the table. If you want the highest accuracy and can tolerate roughly a second of delay on the reference GPU, Qwen3-ASR is the choice. The documentation does not publish word error rates, so accuracy is expressed only as a star rating. Treat those stars as relative ordering within this project, not as an absolute quality claim.

Hotwords, Regex Rules, and Phoneme Matching

The customization layer is where this project differs from a generic transcriber. Hotwords live in hot.txt. The README says matching is done by phoneme fuzzy matching, and that when similarity exceeds a threshold the recognized text is forcibly replaced. That mechanism matters for names and jargon that a general model will not know. It also means a badly chosen hotword can overwrite correct output, because the replacement is forced rather than suggested.

hot-rule.txt handles a different case: exact replacement using regular expressions or simple equals-sign rules. The distinction is worth understanding before you write entries. Fuzzy phoneme matching is for things the model hears wrong; regex rules are for things you want rewritten deterministically regardless of how they were heard.

There is also a number ITN layer. The README gives the example of converting a spoken Chinese approximation of fifteen or sixteen into the numeric range 15~16, and says various complex numeric formats are supported. The tray menu exposes hotword addition, copying the last result, and clearing LLM memory, so you do not have to edit files for every small change.

LLM Roles and the Network Question

The README describes preset LLM roles for polishing and for a small assistant. The trigger is positional: when the beginning of a recognition result matches a role name, the text is handed to that role for processing. This is a clever way to avoid a settings dialog, but it means a role name spoken at the start of a sentence will be consumed as a command rather than transcribed.

The README does not state that the LLM role feature is local. It describes the rest of the tool as fully offline, and separately describes LLM roles as a feature. If an LLM role is configured to call a remote model, that utterance leaves the machine. The supplied material does not resolve this, so anyone whose reason for choosing this tool is confidentiality should verify the role configuration in config_server.py before enabling it. This is the single largest gap in the documentation as presented.

Getting It Running: Files, Folders, and Config Keys

The quick start is short. Install the VC++ runtime. Install ffmpeg and put it on PATH if you want file transcription. Download the software from the latest release and the models from the separate models release, then extract the model archive into the matching folder inside models. Run start_server.exe, then start_client.exe. Both minimize to the tray. Then hold CapsLock or mouse side button X2 and speak.

Configuration is by editing two files in the root directory: config_server.py and config_client.py. The README says all settings live there and that they can be edited directly. There is no settings GUI described. Hotwords go in hot.txt, rules in hot-rule.txt. Recordings and their transcripts accumulate under a year/month/assets path.

For file transcription, the README says you drop an audio or video file onto the client executable and get .srt subtitles, .txt text, and .json with timestamps. To start automatically, the FAQ says to open the startup folder with Win+R and shell:startup, then place shortcuts to both executables there. The FAQ also notes the console windows can be hidden from the tray menu.

Where It Does Not Fit, and What to Use Instead

The platform boundary is explicit. The README says only Windows 10 and 11 64-bit are guaranteed. Linux is untested and unpackaged. macOS is described as unsupported because the underlying keyboard library dropped macOS support and because of system restrictions. If you work across macOS and Windows, this tool covers half your machines.

The README itself names two alternatives: LazyTyper and a project called 闪电说. Both are described as having offline engines, supporting Windows, Linux and macOS, and offering graphical interfaces. The difference in approach is the interface and the platform reach. CapsWriter-Offline is a tray-resident pair of console processes configured through Python files; those alternatives are described as GUI applications with cross-platform support. If editing a Python config file to change a hotkey is unacceptable, that difference decides the choice before accuracy or latency enter the conversation.

There is also a hardware floor. The README's own latency table was produced on a U9-285H CPU and an RTX5050 GPU. The README does not publish figures for older hardware, but the Windows 7 client-only note implies the server side has real requirements. Running the largest model on a machine without GPU acceleration is the case where the latency advantage over a cloud service narrows or disappears.

Licence, Maintenance, and What Updates Cost You

The project is MIT licensed, which permits commercial and private use with the usual attribution requirement. The README does not discuss model licences separately. Since the models come from Sherpa-ONNX and FunASR ecosystems and are distributed through a separate models release, anyone shipping this inside a product should check the licence of the specific model they select rather than assuming MIT covers the weights. That is a question for your own review, not legal advice from this article.

Maintenance cost is mostly model management. Releases are frequent enough to matter: v2.4 in February 2026, v2.5 in May 2026, v2.6 in May 2026, with the last push in August 2026. The v2.5 notes added a new model, which means an upgrade can require downloading a new model archive and placing it in the right folder under models. The README does not describe an automatic updater. Upgrading is a manual download and extract.

The dependency surface is small and mostly external to the repository: the VC++ runtime, ffmpeg for file transcription, and the model files. The Python configuration files are the part most likely to conflict with a future release, since they are edited in place and the README gives no migration path. Keeping a copy of your config_server.py and config_client.py before replacing the executables is the cheap precaution.

Editorial conclusion

Adopt CapsWriter-Offline if you dictate on Windows 10 or 11, want audio to stay on the machine, and are willing to edit config_server.py and config_client.py by hand. Do not adopt it if you need macOS or Linux, if you cannot keep start_client.exe running, or if you need to dictate into elevated applications without running the client as administrator. Before committing, verify three things: that the model folder under models matches the engine you selected, that ffmpeg is on PATH if you want file transcription, and that your microphone produces usable audio in the dated assets folder after a first recording.

Official sources

  1. HaujetZhao/CapsWriter-Offline on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Community notes

Community notes