-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Start with the smallest failing layer: service → control/state → ASR → refinement → output → HUD.
systemctl --user status voice-input.service voice-input-hud.service
systemctl --user cat voice-input.service voice-input-hud.service
journalctl --user -u voice-input.service -u voice-input-hud.service -b
voice-input status --format json --extendedThe daemon should create:
$XDG_RUNTIME_DIR/voice-input/control.sock
$XDG_RUNTIME_DIR/voice-input/state.json
$XDG_RUNTIME_DIR/voice-input/waveform.sock
Check them without printing state contents:
stat "$XDG_RUNTIME_DIR/voice-input/control.sock" \
"$XDG_RUNTIME_DIR/voice-input/state.json" \
"$XDG_RUNTIME_DIR/voice-input/waveform.sock"Common causes:
-
failed to connect to daemon: the daemon is stopped, crashed during config/credential loading, or the CLI and service use differentXDG_RUNTIME_DIRvalues. -
Config parse error: run
voice-input config; compare enum spelling with Configuration. -
Binary/assets mismatch after update: rerun
cargo fetch --locked && make enable-service, then inspect the rendered unit paths. - Hyprland unavailable to the service: make sure the systemd user-manager environment contains the graphical session variables, then restart the daemon.
A manually launched daemon and the systemd daemon must not compete for the same socket. Stop one before starting the other.
The standard deployment uses a separate Quickshell service. Restarting only voice-input.service does not restart the HUD:
systemctl --user restart voice-input-hud.service
journalctl --user -u voice-input-hud.service -fCheck /usr/bin/qs and the installed QML:
test -x /usr/bin/qs
ls -l ~/.local/share/voice-input/quickshell/Then distinguish the two HUD inputs:
-
state.jsonchanges phase/transcript. Test withvoice-input status --follow --format json --extended. -
waveform.sockcarries 30-bar NDJSON frames. The QML client retries after 400 ms.
If status changes but no HUD appears, focus on Quickshell/QML, focused-monitor detection, and voice-input-hud.service. If the HUD phase changes but bars remain flat, focus on waveform.sock, microphone PCM, and Qwen speech activity. The waveform is intentionally hidden when realtime Server VAD does not mark voice active.
The standard daemon unit sets VOICE_INPUT_EXTERNAL_HUD=1. Setting [hud].enabled = true will not spawn the Python fallback while that environment variable is present. Conversely, disabling [hud].enabled does not stop the separate Quickshell unit.
Remove stale runtime sockets only while the daemon is stopped; startup normally removes/rebinds its own control and waveform sockets:
systemctl --user stop voice-input.service
rm -f "$XDG_RUNTIME_DIR/voice-input/control.sock" \
"$XDG_RUNTIME_DIR/voice-input/waveform.sock"
systemctl --user start voice-input.serviceRealtime sessions deliberately cancel when no server speech event or non-empty transcript arrives within a 350 ms grace period at stop. The log says:
voice-input realtime ASR: no speech detected; cancelling empty dictation
No final pass, LLM request, or output occurs in this case.
Check:
pw-record --raw --rate 16000 --channels 1 --format s16 /tmp/voice-input-test.raw
# Speak briefly, stop with Ctrl+C, confirm the file is non-empty, then delete it.
rm -f /tmp/voice-input-test.rawAlso verify audio.device, Qwen connectivity, turn_mode, vad_threshold, and silence_duration_ms. Adjust VAD values incrementally according to the provider's accepted range.
The current cancellation gate runs before a manual-mode stop commit. A manual session that has produced no prior transcription event can therefore be treated as silent. Prefer server-vad when diagnosing this behavior. Local CLI sessions do not use the realtime no-speech gate.
voice-input record cancel and an empty captured buffer also return to idle without output by design.
Follow the daemon journal while recording:
journalctl --user -u voice-input.service -fCheck:
-
provider = "alibaba-qwen-realtime"and a validalibaba-api-keycredential; - endpoint region, model ID, and network/DNS/TLS access;
- connect/finalize timeouts;
-
/usr/bin/voxtypeiffallback_to_local = true; - final model/base URL/timeout if
final_pass_enabled = true.
An empty final-pass base URL is inferred only for known dashscope.aliyuncs.com, dashscope-intl.aliyuncs.com, and dashscope-us.aliyuncs.com realtime hosts. Set it explicitly for a custom host.
Realtime partial text can still be used after some worker errors. A failed final pass first falls back to realtime final text, then to local CLI when enabled.
test -x /usr/bin/voxtype
/usr/bin/voxtype --helpVoice Input supports backend setup only through these CLI forms, which proxy to the configured backend:
voice-input setup gpu [backend arguments...]
voice-input setup onnx [backend arguments...]For recognition, it invokes the configured executable with engine/model/language flags and transcribe <temporary-wav>. Confirm the selected engine/model is installed in Voxtype itself. Never set backend_command = "voice-input"; that would recurse into this program.
Both local and remote Chinese final text invoke:
opencc -c t2s # simplified-chinese
opencc -c s2t # traditional-chineseCheck availability:
command -v opencc
printf '測試\n' | opencc -c t2sIf opencc cannot be launched, recognition returns an error. If it launches but exits nonzero or emits empty output, Voice Input retains the unconverted transcript. English, Japanese, and Korean bypass OpenCC.
voice-input llm test
journalctl --user -u voice-input.service -fConfirm enabled = true, a non-empty model, the correct api_base_url, and openrouter-api-key. The contextual attempt and any eligible no-context retry share one deadline. timeout_ms is clamped to 1–5 seconds, so increasing it above 5000 cannot extend processing.
Refinement deliberately keeps ASR text on all failures. Context-free retry is limited to recognized payload/context errors or invalid response structure; rate limits, authentication failures, transport errors, truncation, and timeout do not retry.
Text over 120 characters automatically uses paste even when mode = "type". XWayland also prefers paste by default.
Verify the route and tools:
command -v wtype wl-copy wl-paste
command -v xclip xdotool # XWayland only
journalctl --user -u voice-input.service -b | grep 'voice-input output:'The logs identify target, mode, and driver without printing text. Check these cases:
-
mode = "clipboard"copies only; it never sends a paste chord. - The target application may not accept
shift+Insert; setpaste_keysorxwayland_paste_keysto its supported chord, such asctrl+v. - A clipboard manager or application may change ownership during the 220 ms restore delay.
- Unsupported clipboard MIME types or a failed backup can prevent complete restoration.
- If modifier keys are still held, raise
pre_type_delay_ms; toggle+modifier shortcuts already enforce at least 500 ms. - To test direct typing for XWayland, temporarily set
prefer_paste_for_xwayland = false, understanding that some clients garble directwtypeinput.
Use voice-input status --format json --extended to inspect the last resolved output_target, output_mode, and output_driver (the JSON field is output_target_resolved).
List metadata only; do not decrypt a key into a shared terminal or report:
ls -l ~/.config/credstore.encrypted/
systemctl --user cat voice-input.service
journalctl --user -u voice-input.service -bThe blob names must exactly match alibaba-api-key and openrouter-api-key. Settings leaves a blank password field unchanged. After editing credentials:
systemctl --user restart voice-input.serviceEncrypted credentials are supplied only to the systemd-launched service. A manual voice-input daemon has no $CREDENTIALS_DIRECTORY unless launched in an appropriate credential context; it can use the documented environment fallback, with the associated exposure risk.
If Settings cannot encrypt/decrypt, verify systemd-creds exists and the user's systemd credential mechanism works. Do not place keys into public TOML examples or issue logs.
Restart Pi or reload its extensions. The installed TypeScript file is not loaded retroactively into an existing Pi process:
ls -l ~/.pi/agent/extensions/voice-input-session-registry.ts
ls -l "$XDG_RUNTIME_DIR/voice-input/agent-sessions/"If no registry appears after Pi restart, inspect Pi extension loading. If a registry exists, verify that Pi is the focused foreground process in a Kitty window and that the Kitty endpoint is exactly /tmp/kitty-<kitty-pid>. See Agent Context for the full validation chain.
Codex does not use this extension; it must have exactly one eligible CLI session JSONL open under CODEX_HOME/sessions.
Use the structured timing lines instead of dumping state or session files:
journalctl --user -u voice-input.service -b \
| grep -E 'first partial|session finished|voice-input refinement:|voice-input output:'These lines normally contain elapsed times, counts, outcomes, and drivers rather than transcript/context. Provider/backend errors can still contain external diagnostics. Read and redact the output before sharing; never attach state.json, Pi/Codex JSONL, raw audio, credentials, or a complete unreviewed journal.
See also: Security and Privacy · Development
English Home · 简体中文首页 · Source repository · MIT License
Voice Input is an independent community project. HUD and Settings require Quickshell 0.3+. Review Security and Privacy before enabling remote ASR, LLM refinement, pre-roll, agent context, or replacing credentials in Settings.
Voice Input 是独立的社区项目。HUD 和 Settings 需要 Quickshell 0.3 或更高版本。启用远程 ASR、LLM refinement、pre-roll、Agent 上下文,或者在 Settings 中替换 credential 前,请阅读安全与隐私。