-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Start with the canonical privacy-safe support report, then isolate the smallest failing layer: service → control/state → ASR → refinement → output → HUD.
voice-input diagnostics
voice-input diagnostics --format jsonDiagnostics schema 4 is the preferred support artifact. It contains allowlisted configuration choices, stage/failure categories, and aggregate counts/timings, but no transcript, endpoint, model, key, terminology, provider message, window metadata, or Agent source. Review it before sharing.
Do not paste voice-input status output into a report, with or without --extended. Status is for local UI integration and can contain the current or most recent transcript and tooltip text.
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 -bThe 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 metadata 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, failed during config/credential loading, or the CLI and service use differentXDG_RUNTIME_DIRvalues. -
Config parse error: run
voice-input config >/dev/null; compare enum spelling with Configuration. -
Binary/assets mismatch after update: rerun
make enable-service, then inspect the rendered unit paths. - Hyprland unavailable to the service: ensure the systemd user-manager environment has 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.
Settings requires Quickshell 0.3 or newer. Start with non-secret executable and asset checks:
/usr/bin/qs --version
test -x "$(command -v voice-input)"
test -d ~/.local/share/voice-input/quickshell-settings
pgrep -af 'qs.*voice-input/quickshell-settings'Running voice-input settings again should activate the existing window through Quickshell IPC. To see QML startup diagnostics, close Settings first and run its configuration in the foreground:
VOICE_INPUT_BIN="$(readlink -f "$(command -v voice-input)")" \
/usr/bin/qs --no-duplicate --path \
"$HOME/.local/share/voice-input/quickshell-settings"Settings QML communicates with a dedicated hidden Rust backend over versioned NDJSON. Each request has a 30-second timeout; each response line is capped at 2 MiB. QML accepts only the exact protocol schema, a matching positive safe request ID, and the method-specific payload shape. Wrong versions, unknown envelope fields, stale or unknown IDs, malformed JSON, oversized lines, and invalid method payloads are rejected rather than partially applied.
For troubleshooting only, verify the non-secret envelope:
printf '%s\n' \
'{"version":1,"id":1,"method":"settings.get","params":{}}' \
| voice-input settings-backend --stdio \
| jq '{version, id, ok, error: (.error.code // null)}'Expected output has version: 1, the same id, and ok: true. Do not send credential replacement requests from a shell.
If the hidden backend exits or violates the protocol, Settings automatically restarts it at 250 ms, 500 ms, 1 s, 2 s, 4 s, and 8 s, for at most six automatic retries. Only a valid response resets the failure count. After retries are exhausted, use Reload for an immediate manual retry; it does not silently create an unlimited restart loop.
For save failures, validate without printing config and check permissions:
voice-input config >/dev/null
stat -c '%a %n' "$HOME/.config/voice-input" \
"$HOME/.config/voice-input/config.toml"
systemctl --user status voice-input.serviceExpected modes are 700 for the directory and 600 for the file. A revision conflict means the exact source changed after Settings loaded it; reload and reapply the intended edit. If persistence succeeded but restart failed, the new file remains saved—diagnose the service separately.
The standard deployment uses a separate Quickshell service. Restarting only the daemon does not restart the HUD:
systemctl --user restart voice-input-hud.service
journalctl --user -u voice-input-hud.service -fCheck /usr/bin/qs, installed assets, and runtime metadata without printing transcript state:
test -x /usr/bin/qs
test -d ~/.local/share/voice-input/quickshell
stat "$XDG_RUNTIME_DIR/voice-input/state.json" \
"$XDG_RUNTIME_DIR/voice-input/waveform.sock"The HUD consumes two independent inputs:
-
state.jsondrives phase, text, timing, geometry, and focused-monitor placement. -
waveform.socksends NDJSONreset/waveformframes and reconnects after a disconnect.
The QML reader keeps the last valid state snapshot when a state file is malformed, oversized, or stale by updated_at_ms/revision. It similarly keeps the last valid waveform frame when a frame is malformed, oversized, from another/stale session, or has an old sequence. Valid waveform payloads require safe session/sequence integers, a nonzero waveform session ID, exactly 30 bars, exactly 12 spectrum values, and every normalized scalar/array value in [0,1]. A socket disconnect resets waveform display; an invalid frame does not replace the last valid frame.
If phase updates but bars remain flat, inspect microphone PCM and ASR speech activity. Qwen Realtime intentionally hides waveform when Server VAD does not mark voice active. If the HUD appears on the wrong display, reproduce focus changes and monitor hotplug while watching the HUD journal. Do not use extended status as a HUD diagnostic.
Remove stale sockets only while the daemon is stopped; startup normally removes and rebinds them:
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.serviceAt stop, a Qwen Realtime session with no server speech event waits for a 350 ms grace period. Expiry does not immediately cancel the session; it defers the empty-audio decision to normal finalization, where realtime/final ASR and configured recovery determine whether any transcript exists. A confirmed no-words result returns to idle without refinement or output.
Test local capture:
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 check audio.device, provider connectivity, turn/VAD controls, and the selected recovery mode. voice-input record cancel and an empty captured buffer return to idle without output by design.
Capture stops automatically at audio.max_duration_secs, 300 seconds by default. This is a normal stop: configured final ASR, local fallback, refinement, and output still run.
Qwen Realtime may reconstruct the streaming session once and replay all retained PCM after:
- a recoverable transport failure before finishing;
- eight seconds of transcript stall during server-confirmed active speech; or
- after text has already appeared, sustained pitch-correlated local speech with no server event for eight seconds.
The pitch-correlated path is not a simple RMS/noise trigger. Recording, elapsed time, and retained audio continue while the replacement catches up. The replacement transcript becomes authoritative after replay. A second failure, a post-finish failure, delivery overload, or worker interruption rejects incomplete remote text and uses the enabled full-audio final pass or local fallback. Diagnostics reports aggregate reconnect and recovery outcomes without transcript content.
If recovery is unavailable, enable final_pass_enabled or fallback_to_local as appropriate. Increasing the duration limit also increases retained PCM and potential full-audio upload size.
Start with:
voice-input diagnostics --format json
journalctl --user -u voice-input.service -fCheck:
-
provider = "alibaba-qwen-realtime"and a valid region-appropriate Alibaba credential; - endpoint region, model compatibility, DNS, TLS, and network access locally—do not paste endpoint/model values into a report;
- connect/finalize timeouts;
-
/usr/bin/voxtypewhenfallback_to_local = true; - final base URL/timeout when
final_pass_enabled = true.
An empty final-pass base URL is inferred only for recognized DashScope realtime hosts. Set it explicitly for a custom host. Review provider close reasons locally before sharing a journal; diagnostics is the support-safe summary.
Audio3 is experimental and requires both selecting Qwen-Audio-3 (experimental) and acknowledging/enabling its explicit gate. It is intentionally absent from the stable setup wizard.
Check these layers in order:
- Credential and region: Audio3 shares the encrypted Alibaba key. Keys are region-scoped; switching Beijing/Singapore may require replacing the key. Voice Input never probes another region or migrates a key.
- Endpoint mode: Regional uses the reviewed fixed Streaming/Native pair for the selected region. Custom uses both configured URLs exactly, including path, port, query, and any proxy behavior.
- Preset and controls: Standard is the default. Low-latency and Long-form resolve to different silence/semantic controls. In Custom, semantic punctuation and multi-threshold mode cannot both be enabled; optional thresholds must pass local validation.
-
Dynamic vocabulary: entries are sent to both Streaming and Native. Validate duplicate/count/term limits and weights (
1–5or50). Diagnostics reports only the entry count, never terms. - Native mode: Streaming only never uploads the complete recording. Adaptive runs Native for degraded/empty/interrupted/overloaded or not-explicitly-finished streaming, and normally for recordings of at least 30 seconds. A healthy, explicitly finished stream that actually sent Session Context is exempt from the duration-only rule. Always runs Native for every non-cancelled, nonempty recording. Native input is capped at 10 MiB.
-
Reconnect: before
finish-task, Streaming allows one replacement task, discards the old transcript, sends the identical start-time terminology in the newrun-task, and replays retained PCM. It never sendscontinue-task. A second or post-finish interruption falls through to Native/local recovery.
Use diagnostics first:
voice-input diagnostics --format jsonTo isolate the remote APIs with a non-sensitive prerecorded 16 kHz mono PCM16 WAV:
voice-input asr stream-test --file sample.wav # Audio3 WebSocket Streaming
voice-input asr test --file sample.wav # Audio3 Native full-audioBoth commands require Audio3 to be selected and explicitly enabled. They send the file to the resolved Regional route or exact Custom endpoint and may incur remote API charges. They do not start the daemon or paste output into another application.
test -x /usr/bin/voxtype
/usr/bin/voxtype --helpVoice Input proxies backend setup only through:
voice-input setup gpu [backend arguments...]
voice-input setup onnx [backend arguments...]Recognition invokes the configured executable with engine/model/language flags and transcribe <temporary-wav>. Confirm the selected engine/model in Voxtype itself. Never set backend_command = "voice-input"; that would recurse.
External backend execution has a timeout, simultaneous stdout/stderr draining, and output caps. A timeout terminates the process group; capped or failed output is reported with a sanitized error rather than provider output. Use diagnostics and inspect backend logs locally.
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 launch, recognition returns an error. If it exits nonzero or emits empty output, Voice Input retains the unconverted transcript. English, Japanese, and Korean bypass OpenCC.
voice-input llm test
voice-input diagnostics --format jsonConfirm enabled = true, a non-empty model, the correct API base locally, and an available openrouter-api-key. Do not include the endpoint or model in a shared report. The contextual attempt and any eligible transcript-only retry share one deadline. timeout_ms is clamped to 1–30 seconds; budgets of at least 10 seconds reserve the final five seconds for recovery.
Refinement preserves ASR text on every failure. Transport errors, recognized payload/context failures, invalid response structure, truncation, or contextual budget exhaustion may retry without context when budget remains. Authentication/rate-limit responses and provider-declared errors preserve the original immediately. Prompts edit only; they never answer or execute transcript commands, and session terminology is untrusted.
All text uses clipboard paste. Verify local tools:
command -v hyprctl wl-copy wl-paste
command -v xclip xdotool # XWayland only
voice-input diagnostics --format textCheck these cases:
- The target may not accept
shift+Insert; setpaste_keysorxwayland_paste_keysto a supported chord such asctrl+v. - Confirm Hyprland supports
dispatch sendshortcutand the active window accepts the configured key. - A clipboard manager or application may change ownership during the 220 ms restore delay.
- Backup stores one selected MIME payload and skips sensitive metadata MIME; unsupported formats may not restore completely.
- Wayland transient and restored payloads are marked sensitive only for compatible clipboard managers. X11 has no equivalent guarantee.
- A crash can leave the private clipboard-backup temporary file behind; inspect the temporary directory locally if restoration was interrupted.
- If modifiers are still held, raise
pre_type_delay_ms; toggle+modifier shortcuts already enforce at least 500 ms. - Legacy output mode fields do not alter the current clipboard-only delivery path.
Output helper processes have deadlines and output caps, and reported errors are sanitized.
List metadata only; do not decrypt a key into a shared terminal or report:
ls -l ~/.config/credstore.encrypted/
systemctl --user cat voice-input.serviceBlob names must exactly match alibaba-api-key and openrouter-api-key. Settings offers keep/replace only. After changing credentials:
systemctl --user restart voice-input.service
voice-input diagnostics --format textEncrypted credentials are supplied to the systemd-launched service. A manual daemon has no $CREDENTIALS_DIRECTORY unless launched in an appropriate credential context. Avoid plaintext TOML, environment variables, shell history, and issue logs.
Agent context is captured when recording starts, not when it stops. Restart Pi or reload its extension after installation:
ls -l ~/.pi/agent/extensions/voice-input-session-registry.ts
ls -l "$XDG_RUNTIME_DIR/voice-input/agent-sessions/"For Pi, verify the focused foreground process is Pi in Kitty and the validated registry/session is current. Codex does not use the extension; it needs exactly one eligible open CLI session JSONL under CODEX_HOME/sessions. Focus changes after start do not replace the frozen terminology source; stop-time focus only selects destination style/Agent Markdown.
Diagnostics reports only whether a nonempty Audio3 Session Context was sent, never terms, paths, or source text. See Agent Context for validation and failure behavior.
Use diagnostics as the primary and normally sufficient artifact:
voice-input diagnostics --format json > voice-input-diagnostics.jsonReview that file before attaching it. If maintainers request logs, collect only the smallest relevant service/time range, inspect every line, and remove user names, paths, endpoints, models, provider messages, and unexpected content. Never share voice-input status output, state.json, Pi/Codex JSONL, raw audio, credentials, clipboard backups, 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 前,请阅读安全与隐私。