Command-Line Interface (CLI)
Knowii Voice AI gives you two command-line tools, and they do very different jobs:
transcribeis the real CLI. It runs fully headless, turns audio and video files into subtitles or text, and manages your transcription models. No window, no clicking, no waiting.knowii-voice-aiis the desktop app itself. Its flags let you drive a running app from a script or a keybinding, and change how it starts up.
The first one is what most readers want, so it goes first.
The Transcribe CLI Tutorial walks you through your first file, start to finish, in about ten minutes. This page is the reference you come back to afterwards.
The transcribe CLI
transcribe turns the audio that never passes through your microphone (meeting recordings, interviews, podcasts, old videos) into subtitles or text. Point it at files, get text back.
It decodes media in-process (mp4, mkv, mov, m4a, mp3, wav, ogg, opus, flac, and more), so there is no ffmpeg to install. It runs the same transcription engines as the desktop app, on your machine, offline. And because it is a normal command-line program, it composes with everything else you already use: shell loops, cron jobs, Makefiles, scripts.
transcribe never launches or interferes with a running Knowii Voice AI window. It does its work and exits, so it is safe to use while the desktop app is open. Models downloaded with transcribe models download show up in the app, and models downloaded in the app are available to the CLI.
Where to find it
transcribe is installed with Knowii Voice AI, in the same folder as the main executable:
| Platform | Location |
|---|---|
| Windows | %LOCALAPPDATA%\Programs\knowii-voice-ai\transcribe.exe |
| macOS | /Applications/Knowii Voice AI.app/Contents/MacOS/transcribe |
| Linux (deb / RPM) | /usr/bin/transcribe, already on your PATH |
| Linux (AppImage) | Run it through the AppImage (see below) |
The AppImage packs everything, transcribe included, into a single file, so the CLI is not on your PATH. Put transcribe right after the AppImage and you get the CLI, with no window:
./Knowii-Voice-AI.AppImage transcribe --version
./Knowii-Voice-AI.AppImage transcribe file talk.mp4 --model parakeet-tdt-0.6b-v3
Everything after transcribe goes to the CLI unchanged, and so do piped input, output, the exit code and Ctrl+C. It is exactly the transcribe described on this page, and safe to run while the app is open.
To type plain transcribe from anywhere, save this small script as ~/.local/bin/transcribe (or any folder on your PATH), with the real path of your AppImage, and make it executable with chmod +x ~/.local/bin/transcribe:
#!/bin/sh
exec "$HOME/Applications/Knowii-Voice-AI.AppImage" transcribe "$@"
Other tools, Knowii Video AI included, can then call transcribe like any other program. Do not copy the transcribe file out of the AppImage: it needs the libraries packed next to it, and fails to start on its own.
On Windows, call transcribe.exe directly (see the table above). Starting the app with transcribe first is not supported there.
Check that it works:
transcribe --help
If your shell cannot find the command, that folder is not on your PATH. Either call it by its full path, or add the folder to your PATH so you can type transcribe from anywhere. On macOS, an alias does the job too:
alias transcribe="/Applications/Knowii\ Voice\ AI.app/Contents/MacOS/transcribe"
Your first transcription
Two commands. Download a model, then use it:
transcribe models download whisper-large-v3
transcribe file talk.mp4 --model whisper-large-v3
That writes talk.srt next to talk.mp4. Open the video in any player and your subtitles are there.
Already downloaded a model inside the app? Skip the first command. The CLI and the app share the same models.
Transcribe files
transcribe file <FILE>... --model <NAME_OR_PATH> [OPTIONS]
| Option | Description | Default |
|---|---|---|
<FILE>... | One or more audio/video files. Use - to read one stream from stdin. | (required) |
-m, --model | A model id (e.g. whisper-large-v3) or a path to a model file/directory | (required) |
--engine | Engine for raw paths: parakeet, omnilingual (folders), transcribe-cpp | by file type |
-l, --language | Language code (e.g. en, fr) or auto to detect (see below) | auto |
-f, --format | Output format: srt, vtt, txt, json, or md | srt |
-o, --output | Output directory, a single output file, or - for stdout | next to each input |
--translate | Translate to English (multilingual Whisper models only) | off |
--initial-prompt <TEXT> | Bias vocabulary/style (Whisper models only) | (none) |
--use-app-dictionary | Also use your app dictionary, as dictation does (see below) | off |
--settings <PATH> | With --use-app-dictionary: read another settings file | the app's own |
--int8 | Trade a little accuracy for more speed and lower memory, where supported | off |
--no-preprocess | Skip preprocessing (peak-normalize; silence-trim for txt) | off |
--timestamp-granularity | Timing detail: auto, token, word, or segment (see below) | auto |
--models-dir <DIR> | Where to look up models by id | app data directory |
When --model is an id, it is resolved against your downloaded models. When it is a raw path, a .gguf file (Whisper, Parakeet, Moonshine) is loaded on the transcribe-cpp engine automatically; a model folder defaults to parakeet, so pass --engine omnilingual for an Omnilingual folder.
Long files. Whisper reads a file of any length in one pass. The other families (Parakeet, Moonshine, Omnilingual) work on short stretches of audio, so the CLI splits longer files for them the way the app does: in pieces of about 30 seconds, cut at pauses in the speech so words are never split in half, then stitched back together. Timestamps in every output format stay on the file's own timeline, so a subtitle file or a JSON transcript reads the same whether the file was split or not. Files shorter than a piece are transcribed in one go, as before.
Examples:
# Subtitle a video - writes "talk.srt" next to it
transcribe file talk.mp4 --model whisper-large-v3
# Several files at once, into a folder, as WebVTT
transcribe file *.mp4 --model whisper-medium --format vtt --output ./subs/
# Force English and print plain text to the terminal
transcribe file interview.m4a --model whisper-large-v3 --language en --format txt --output -
# Translate a French recording into English subtitles
transcribe file entretien.mp3 --model whisper-large-v3 --translate
# Feed a jargon-heavy recording some vocabulary up front
transcribe file standup.m4a --model whisper-large-v3 --initial-prompt "Kubernetes, Grafana, Prometheus, OTEL"
# Use the custom words and initial prompt you set up in the app
transcribe file standup.m4a --model whisper-large-v3 --use-app-dictionary
# Pipe audio in from stdin
cat note.ogg | transcribe file - --model whisper-medium --format txt
# A faster model, in its lower-memory mode
transcribe file clip.mkv --model parakeet-tdt-0.6b-v3 --int8
Choosing the language. --language fr is used as is by the models that can be told a language (Whisper, for the languages it knows). A model that does not know that language, or cannot be told one at all, says so on the terminal (for example "this model doesn't support 'fr'; the language was detected automatically instead") and carries on. The transcript is still written; with -f json, its language field says which language was actually used.
Reading from stdin. With -, the audio is copied to a temporary file of its own, so several transcribe file - runs can work side by side. The copy is deleted when the run ends: when it succeeds, when it fails, and when you stop it with Ctrl+C or it is asked to stop (exit code 130 for Ctrl+C, 143 for a termination request).
File names often contain spaces. Always quote them: transcribe file "My Recording.mp4" --model whisper-large-v3.
Output formats
| Format | What you get | Use it for |
|---|---|---|
srt | Numbered subtitle blocks with timestamps | Video players, YouTube, editing software |
vtt | WebVTT subtitles | Web video, HTML5 players |
txt | Plain text, no timestamps | Notes, search, feeding text into another tool |
json | Structured segments with timings | Scripts and further processing |
md | A Markdown note: # <file name>, then the transcript as paragraphs, no timestamps | Obsidian and other note apps — a new paragraph wherever the speaker paused for 1.5 s or more |
Word-level timings and the JSON contract
--timestamp-granularity decides how fine the timings are. auto (the default) keeps each model family's usual behaviour, so scripts written before this option existed keep working unchanged. word gives one entry per word — and with -f json it also fills the words list — while segment gives sentence-sized blocks. The parakeet and transcribe-cpp engines honour all of them; the other engines keep their native segments and print a note.
transcribe file talk.mp4 -m parakeet-tdt-0.6b-v3 -f json --timestamp-granularity word -o -
The JSON is versioned so a tool built on it can check what it is reading:
{
"contract_version": 3,
"language": "en",
"text": "And so, my fellow Americans, ask not…",
"segments": [
{
"start": 0.24,
"end": 10.88,
"start_ms": 240,
"end_ms": 10880,
"text": "And so, my fellow Americans, ask not…"
}
],
"words": [
{ "index": 0, "start_ms": 240, "end_ms": 560, "segment": 0, "text": "And" },
{ "index": 1, "start_ms": 560, "end_ms": 1040, "segment": 0, "text": "so," }
]
}
contract_versionis3. It changes whenever the shape changes in a way that could break a consumer.languageis the language the transcript was made in: the one you asked for with--languagewhen the model used it, otherwise the one the model detected, ornullwhen the model does not report one: Parakeet and Moonshine with--language auto, and the Parakeet folder models and Omnilingual always. With--translate, it is the language that was spoken, not English. When a long file is split into pieces and they report different languages, the language with the most text overall wins, and a tie goes to the earliest piece.- Coming from version 2? Version 3 only adds
language; every other field is exactly as before. A tool that reads version 2 only needs to accept3as well. - Times are in whole milliseconds (
start_ms/end_ms); the older floatstart/endseconds on segments stay for compatibility. - Each word has a stable
indexwithin the transcript and thesegmentit belongs to. wordsisnull— not an empty list — when you did not ask forwordgranularity or the model cannot time words. Null means "not available"; an empty list[]means the model could time words and nobody spoke (a silent file).- Pauses and silent stretches never cost you the word timings: a long file split into pieces keeps its
wordseven when one piece was silent, and theindexnumbers run on without a gap. - Long files transcribed in pieces (see Long files above) come back as one transcript: segment and word times are already shifted to the file's timeline and each word's
segmentpoints into the merged list, so nothing has to be re-aligned on your side.
Your app dictionary
The words you taught the app in Settings > Transcription (custom words, word replacements, phonetic replacements, the correction threshold and your initial prompt) are your dictionary. The CLI can read it, and it only ever reads it: it never changes your settings file, even when that file looks damaged. The running app stays in charge of it.
Use it in a file transcription. Add --use-app-dictionary and the model gets the same hint dictation gives it: your initial prompt, then your custom words. If you also pass --initial-prompt, your text comes first and the dictionary follows, separated by a space.
transcribe file standup.m4a --model whisper-large-v3 --use-app-dictionary
transcribe file standup.m4a --model whisper-large-v3 --initial-prompt "Weekly standup." --use-app-dictionary
- Only Whisper models take this hint, just as in the app. With another model the option is accepted, and the CLI prints a note that the dictionary was not used.
- The dictionary does not rewrite the output. Word replacements and fuzzy corrections are not applied to the subtitles, text or JSON, so every word and its timing stay exactly as the model heard them. A tool that wants those fixes applies them itself, word by word, from
transcribe dictionary --json.
See it, or hand it to another tool:
transcribe dictionary # a readable listing
transcribe dictionary --json # for scripts and other apps
{
"contract_version": 1,
"custom_words": ["Knowii", "Obsidian"],
"word_replacements": [{ "from": "no we", "to": "Knowii" }],
"phonetic_replacements": [{ "from": "эн восемь эн", "to": "N8N" }],
"threshold": 0.18,
"initial_prompt": "Technical dictation."
}
contract_versionis1. It changes whenever the shape changes in a way that could break a consumer.- Entries keep the order they have in the app; values are exactly as saved.
thresholdis the custom-word correction threshold (the app's default is0.18).
Which settings file. By default, the app's own, in its data folder: ~/.local/share/knowii-voice-ai/settings.json on Linux, %APPDATA%\knowii-voice-ai\settings.json on Windows, ~/Library/Application Support/knowii-voice-ai/settings.json on macOS. Pass --settings <PATH> to read another one, such as a copy.
When one setting is damaged. If a single dictionary setting cannot be read (say, a word replacement with no replacement text), the CLI does what the app does: it uses the default for that one setting, keeps all the others, and prints a note naming it. That is not an error: the exit code stays 0.
Exit codes.
| Code | Meaning |
|---|---|
0 | The dictionary was read, even if a single setting was reset to its default (see above). Also when there is no settings file yet: the dictionary is simply empty. |
3 | The settings file could not be used at all: it cannot be read, is not valid JSON, does not have the expected shape, is a broken link or not a regular file, or is larger than 64 MiB. The dictionary is treated as empty and a warning names the file and the problem. With file, the transcription still runs, without the dictionary. |
1 | Any other error, as for every transcribe command. |
Model families
Models come in four families. Whisper and Moonshine are single .gguf files; Parakeet and Omnilingual are folders unless you use the GPU Parakeet .gguf. --engine only matters when you point --model at a raw folder:
| Family | What it gives you |
|---|---|
whisper | Timestamped segments and the widest language support. Best for subtitles. |
parakeet | Much faster than Whisper. Supports --int8 for more speed and less memory. |
moonshine | Fastest of all. English plus several other languages. Longer files are split at pauses. |
omnilingual | Widest language coverage (1,600+). Supports --int8. |
When --model is a known model id (e.g. whisper-large-v3), the family is detected automatically, so you rarely need this flag.
Manage models
transcribe models lists, downloads, and removes transcription models from the terminal, using the same catalog and the same folder as the app. Changes are shared in both directions.
List what is available:
transcribe models list
Models directory: /home/you/.local/share/knowii-voice-ai/models
ID ENGINE SIZE DL NAME
parakeet-tdt-0.6b-v3 Parakeet 785M - Parakeet V3
whisper-tiny Whisper 74M - Whisper - Tiny
whisper-large-v3 Whisper 2952M ✓ Whisper - Large V3
...
The DL column shows ✓ for models you already have. Add --downloaded to list only those, --json for machine-readable output, or --models-dir <DIR> to inspect another location.
Download a model:
transcribe models download whisper-large-v3
The download streams to disk with a progress indicator and is written atomically, so it is safe to run while the app is open. If the model is already there, nothing happens.
Remove a model:
transcribe models remove whisper-large-v3
Use the ID column from transcribe models list. Whisper ids also accept a short form: large-v3 resolves to whisper-large-v3.
Shell completions
Tab completion for subcommands, flags, and model ids:
transcribe completions bash
transcribe completions zsh > ~/.zsh/completions/_transcribe
transcribe completions fish > ~/.config/fish/completions/transcribe.fish
Controlling the desktop app
The knowii-voice-ai executable takes flags of its own. These have nothing to do with file transcription. They exist so you can drive the app from somewhere other than its keyboard shortcut, and change how it starts.
AI-powered voice transcription application
Usage: knowii-voice-ai [OPTIONS]
Options:
--log-level <LEVEL> Set the log level (trace, debug, info, warn, error, off) [default: info]
--toggle-transcription Start or stop a transcription in the running instance
--toggle-capture Start or stop an Obsidian capture in the running instance
--preset <KEY> With --toggle-capture: the preset to capture with, by key (default: the active preset)
--cancel Abort the running instance's current recording or transcription
--start-hidden Start with the main window hidden (tray only)
--no-tray Start without creating a system tray icon
-h, --help Print help
One more: knowii-voice-ai transcribe … runs the transcribe CLI instead of the app, with everything after transcribe passed on unchanged. It is how the AppImage gives you the CLI (see Where to find it). It is not in the list above because it is not a flag of the app: it never opens a window or talks to a running app. Linux and macOS only.
Control a running app
Knowii Voice AI only ever runs once. Launch it again while it is already open and the new command hands its instructions to the running app, then exits. That is what makes these flags work:
| Flag | What it does |
|---|---|
--toggle-transcription | Starts recording. Run it again to stop recording, transcribe, and paste, just like the shortcut. |
--toggle-capture | Starts an Obsidian capture. Run it again to stop, transcribe, and save the note, like the capture shortcut. Works even when no capture shortcut is set. Add --preset <key> to capture with a given preset: --toggle-capture --preset task. (Coming in the next release.) |
--cancel | Throws away whatever is in progress and returns to idle. Does nothing if nothing is running. |
This gives you a second way to trigger dictation, alongside your keyboard shortcut. It is handy for a panel or status-bar button (Waybar, Polybar, a dock, a stream deck), a desktop keybinding set in your window manager, or a script that dictates as part of a longer sequence.
# Start recording (or stop it and transcribe, if already recording)
knowii-voice-ai --toggle-transcription
# Discard the current recording or transcription
knowii-voice-ai --cancel
Hyprland keybindings (~/.config/hypr/hyprland.conf):
bind = SUPER, D, exec, knowii-voice-ai --toggle-transcription
bind = SUPER SHIFT, D, exec, knowii-voice-ai --cancel
A Waybar button (~/.config/waybar/config):
"custom/dictate": {
"format": "🎙",
"tooltip": "Dictate with Knowii Voice AI",
"on-click": "knowii-voice-ai --toggle-transcription",
"on-click-right": "knowii-voice-ai --cancel"
}
Running the app with --toggle-transcription or --cancel will not pop the Knowii Voice AI window in front of what you are doing. Otherwise every press of your panel button would interrupt you. Launching it with no flags at all still brings the window forward, as before.
--toggle-transcription always works as a toggle, even with Push-to-talk enabled in the settings. A command has no key to hold down, so there is nothing to release. Your keyboard shortcut keeps behaving exactly as you configured it.
If Knowii Voice AI is not running yet, these flags simply start the app normally, without recording. Recording during startup would only capture the few seconds the app needs to load its model, so your first words would be lost. Start the app, then trigger it again.
Change how the app starts
These flags apply to the launch itself. They have no effect if the app is already running (you will see a note about it in the logs).
| Flag | What it does |
|---|---|
--start-hidden | Starts with the main window hidden, straight to the tray. Same as Start hidden, but only for this launch. |
--no-tray | Starts without a system tray icon, for desktops where you would rather not have one. |
# Start quietly in the tray, e.g. from a session autostart script
knowii-voice-ai --start-hidden
# Start with no tray icon at all
knowii-voice-ai --no-tray
--no-tray, closing the window minimizes itWithout a tray icon there would be no way to bring the window back, so closing it minimizes the window instead of hiding it. You can always find it again in your task switcher. For the same reason, combining --no-tray with a hidden start is not possible: the window is shown, so the app never becomes unreachable.
Logging
--log-level controls how much detail the app writes to its logs. Use it when something misbehaves and you want to see why.
knowii-voice-ai --log-level debug
| Level | What it gives you | When to use it |
|---|---|---|
trace | Internal state dumps, every audio buffer, full timing | Deep debugging. Creates huge files. |
debug | Detailed diagnostics, state transitions, shortcut events | Troubleshooting and bug reports |
info | Startup, model loading, recording, transcription | Normal operation (default) |
warn | Warnings only | Quiet monitoring |
error | Errors only | Minimal logging |
off | Nothing | Not recommended |
When reporting a problem, start the app with --log-level debug, reproduce the issue, then attach the log files. You can also read the most recent logs without leaving the app, under Settings → Advanced.
Where the log files live, and which ones to send, is covered in Application Data and on the Support page.
Related Documentation
- Transcribe CLI Tutorial: your first file, step by step
- Transcription Settings: models and engines in the app
- Debug Settings: in-app debugging options
- Application Data: where models, history, and logs are stored
- Support: get help with issues
Need Help?
- Check the FAQ for common problems
- Email support@knowii.net with your log files
- Visit the Knowii Community for community support