Skip to content

Configuration

Saco Song edited this page Jul 31, 2026 · 8 revisions

Configuration Reference

简体中文 · Home

The user configuration is TOML at ${XDG_CONFIG_HOME:-$HOME/.config}/voice-input/config.toml. The installed public sample is ~/.local/share/voice-input/config.toml.

Inspect the effective deserialized configuration without credentials:

voice-input config
voice-input config --format json

After editing TOML, restart the daemon:

systemctl --user restart voice-input.service

The on-demand Quickshell Settings window exposes the supported configuration and saves a complete, validated configuration through Rust. Its Overview summarizes the local service and current configuration. Speech, Refinement, Output, Appearance, and Hotkey & state group everyday controls, while each relevant page exposes its own expandable Advanced section for technical tuning. Alibaba options appear inside Speech when that provider is selected. QML does not parse or write TOML.

Settings save model

voice-input settings

Settings loads the config through a dedicated voice-input settings-backend --stdio child using versioned NDJSON. The same child reports a narrowly allowlisted runtime summary for Overview; it never returns transcript text, output targets, arbitrary runtime errors, or credentials. Rust returns an opaque revision tied to the exact config source it read. Save includes that revision and every supported field; if another editor changed the source, Rust rejects the stale save and asks the user to reload instead of silently overwriting it.

Rust creates the config directory with mode 0700, writes config.toml with mode 0600, and atomically replaces the file. Save can also restart voice-input.service; restart failure is reported separately when persistence has already succeeded. Credential fields support keep or replace only. They are cleared after submission; QML/JavaScript memory clearing is best effort.

Top level and hotkey

Field Default Meaning
state_file "auto" auto uses the runtime state file. A custom path receives an additional copy. disabled suppresses that optional copy; the daemon still maintains $XDG_RUNTIME_DIR/voice-input/state.json for status/HUD.
hotkey.accelerator ", F9" Hyprland accelerator text used when generating the primary start/stop binding and when deciding output settle behavior. The daemon does not register a global shortcut itself.
hotkey.mode "toggle" hold or toggle. Determines the generated F9-style start/stop binding. In toggle mode, an accelerator containing a modifier forces at least 500 ms of pre-output settling.

The installed static Hyprland snippet also binds F8 to cancel and F10 to discard and restart, while leaving Omarchy's stock Super+Ctrl+X Voxtype shortcut unchanged. Use voice-input setup hyprland to generate bindings from the current config.

[audio]

Field Default Meaning
device "default" PipeWire target. default omits pw-record --target; any other value is passed as the target.
sample_rate 16000 Capture sample rate and WAV/ASR rate in Hz. Qwen receives this rate in session metadata.
max_duration_secs 300 Maximum recording length for both dedicated and shared pre-roll capture paths. Reaching the limit automatically stops capture and starts finalization instead of leaving the session recording.
partial_interval_ms 1500 Sleep interval for repeated local-CLI partial transcription. Realtime Qwen partials are event-driven.
pre_roll_enabled false Keeps pw-record open while the daemon runs and seeds a new session from a ring buffer. This has microphone-privacy implications.
pre_roll_ms 500 Requested pre-roll window. The ring also retains at least the 320 ms capture warm-up.

[asr]

Field Default Values / behavior
provider "local-cli" local-cli or alibaba-qwen-realtime.
backend_command "/usr/bin/voxtype" Executable for local final/partial ASR and remote fallback. It receives optional --engine, optional --model, --language CODE transcribe WAV.
engine "sensevoice" Local backend engine. An empty value omits --engine.
model "" Local backend model. Empty means backend default and omits --model.
language "simplified-chinese" english, simplified-chinese, traditional-chinese, japanese, or korean. ASR codes are en, zh, ja, and ko; Chinese variants then use OpenCC.
connect_timeout_ms 5000 Realtime TCP/WebSocket connection timeout (minimum 1,000 ms); also the final-pass HTTP connect timeout.
finalize_timeout_ms 8000 Deadline after requesting realtime finish (minimum 1,000 ms).
fallback_to_local true Allows Qwen failure, empty output, or an incomplete realtime audio stream to call the local backend with the complete recording. A successful realtime transcript can still be used after some worker errors, but never after realtime delivery backpressure made the remote stream incomplete.

backend_command defaults explicitly to /usr/bin/voxtype. Keep the absolute path to avoid invoking Voice Input recursively.

[asr.alibaba]

Field Default Meaning
endpoint "wss://dashscope.aliyuncs.com/api-ws/v1/realtime" Realtime WebSocket endpoint. The model query parameter is appended if absent.
model "qwen3-asr-flash-realtime-2026-02-10" Realtime Qwen model ID.
turn_mode "server-vad" server-vad sends VAD settings; manual disables server turn detection and commits on stop.
vad_threshold 0.2 Server VAD threshold passed unchanged to Qwen.
silence_duration_ms 400 Server VAD silence duration passed to Qwen.
final_pass_enabled false Re-recognizes the complete WAV through the compatible HTTP chat-completions endpoint.
final_pass_base_url "" Base URL without /chat/completions. Empty derives the compatible-mode URL for known China, international, or US DashScope realtime hosts. Custom realtime hosts require an explicit value.
final_pass_model "qwen3-asr-flash-2026-02-10" Full-audio final model ID.
final_pass_timeout_ms 20000 Overall HTTP request timeout for the final pass.
final_pass_enable_itn false Sends Alibaba asr_options.enable_itn; ITN means inverse text normalization.

The Alibaba key is not a public TOML field in assets/config.toml. Store credential ID alibaba-api-key as described in Security and Privacy.

[output]

Field Default Meaning
mode "type" type: direct wtype; clipboard: copy only; paste: copy, send a paste chord, then restore. Text over 120 characters changes effective type to paste.
fallback_to_clipboard true If direct wtype fails, attempt the paste path. It does not affect an explicitly selected clipboard/paste mode.
type_delay_ms 0 Passed to wtype -d as per-character delay.
pre_type_delay_ms 140 Delay before output. Passed to wtype -s for direct typing; used as a sleep before clipboard actions. Toggle+modifier shortcuts raise it to at least 500 ms.
paste_keys "shift+Insert" Wayland paste chord. Components are split on +; modifiers are held/released through wtype.
prefer_paste_for_xwayland true Changes effective type to paste for an XWayland target.
xwayland_paste_keys "shift+Insert" XWayland chord sent to xdotool; empty falls back to paste_keys.

Paste backup/restoration is best effort when no readable clipboard content exists. clipboard mode intentionally leaves the recognized text in the clipboard and sends no paste chord.

[ime]

Field Default Meaning
manage_fcitx5 true Enables the Fcitx5 guard.
force_ascii_before_output true If both flags are true and fcitx5-remote reports state 2, run fcitx5-remote -c before output and -o afterward.

[llm]

Field Default Meaning
enabled false Enables conservative transcript refinement. Failure always keeps the ASR text.
api_base_url "https://api.openai.com/v1" OpenAI-compatible base URL; /chat/completions is appended.
model "" Required model ID when enabled.
timeout_ms 15000 Shared refinement budget, clamped to 1,000–30,000 ms. Contextual and transcript-only attempts share it; budgets of at least 10,000 ms reserve the final 5,000 ms for transcript-only recovery.
provider_sort "" If non-empty and the URL host is openrouter.ai or a subdomain, sends provider.sort. Ignored for other hosts.
agent_context_enabled false Enables terminology context from the Pi/Codex session focused when dictation ends. It has no effect when LLM refinement is disabled.
agent_context_max_chars 6000 Context character cap; runtime clamps it to 500–12,000 and keeps both the head and tail when truncating.

The LLM credential uses ID openrouter-api-key, including when api_base_url points to another OpenAI-compatible provider. No key appears in voice-input config output.

[hud]

Field Default Meaning
enabled true Controls whether the resident Quickshell HUD surface is shown. The voice-input-hud.service process may remain running while the surface is disabled.
margin_bottom 72 Bottom margin used by the Quickshell HUD, in logical pixels.
height 56 Base/minimum capsule height used by the Quickshell HUD, in logical pixels.
position "bottom-center" bottom-center, bottom-left, or bottom-right; reflected in state and honored by Quickshell.
offset_x 0 Horizontal offset in logical pixels. Positive moves right.
offset_y 0 Vertical offset added to the bottom margin. Positive moves upward.
nudge_step 24 Default amount for voice-input hud move …; runtime forces at least 1.

The daemon includes hud_enabled, hud_margin_bottom, hud_height, hud_position, hud_offset_x, and hud_offset_y in every HUD snapshot. Quickshell honors all six values.

Move commands update TOML and runtime state immediately:

voice-input hud move left
voice-input hud move up 10
voice-input hud position bottom-right
voice-input hud center   # bottom-center and x=0; preserves y
voice-input hud reset    # bottom-center and x=y=0

Credentials and environment fallback

At daemon startup, each secret resolves in this order:

  1. systemd credential from $CREDENTIALS_DIRECTORY (alibaba-api-key or openrouter-api-key);
  2. VOICE_INPUT_ALIBABA_API_KEY or VOICE_INPUT_OPENROUTER_API_KEY;
  3. a legacy in-memory TOML value, if present in an older config.

Use encrypted systemd credentials for the supplied service. Environment variables are mainly useful for a manually launched daemon and may be exposed to same-user process inspection.

Settings credential replacement and Test LLM requests send entered secrets only over inherited stdin. Keys are never included in config, process arguments, environment variables, logs, or backend responses. Test LLM can use either a just-entered key or the existing encrypted-store credential.

See also: Security and Privacy · Troubleshooting

Clone this wiki locally