-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting.zh CN
建议从最小故障层开始检查: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 --extendedDaemon 应创建:
$XDG_RUNTIME_DIR/voice-input/control.sock
$XDG_RUNTIME_DIR/voice-input/state.json
$XDG_RUNTIME_DIR/voice-input/waveform.sock
检查文件 metadata,同时避免打印 state 内容:
stat "$XDG_RUNTIME_DIR/voice-input/control.sock" \
"$XDG_RUNTIME_DIR/voice-input/state.json" \
"$XDG_RUNTIME_DIR/voice-input/waveform.sock"常见原因:
-
failed to connect to daemon:daemon 已停止、在读取 config/credential 时 crash,或者 CLI 与 service 使用不同的XDG_RUNTIME_DIR。 -
Config parse error:运行
voice-input config,并根据 配置参考 检查 enum 拼写。 -
更新后二进制文件与 asset 不匹配:重新执行
make enable-service,然后检查生成的 unit path。如果 lockfile 增加了 dependency,Cargo 会按需下载。 - Service 无法访问 Hyprland:确保 systemd 用户管理器环境包含图形会话变量,再重启 daemon。
手动启动的 daemon 与 systemd daemon 不能竞争同一个 socket。启动其中一个之前应停止另一个。
Settings 需要 Quickshell 0.3 或更高版本。先执行不涉及 secret 的可执行文件与 asset 检查:
/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'再次运行 voice-input settings 时,程序应通过 Quickshell IPC 激活已有的普通窗口,而不是创建重复实例。如果没有现有实例,launcher 会使用 /usr/bin/qs --daemonize --no-duplicate --path …/quickshell-settings。如果需要在 terminal 中查看 QML 启动诊断,请先关闭 Settings 窗口,再以前台方式运行同一套配置:
VOICE_INPUT_BIN="$(readlink -f "$(command -v voice-input)")" \
/usr/bin/qs --no-duplicate --path \
"$HOME/.local/share/voice-input/quickshell-settings"QML 会启动一个专用的隐藏 backend。只有在故障排查或开发时,才应直接检查其 protocol envelope。以下命令需要 jq,并且不会显示配置或 credential 数据:
printf '%s\n' \
'{"version":1,"id":1,"method":"settings.get","params":{}}' \
| voice-input settings-backend --stdio \
| jq '{version, id, ok, error: (.error.code // null)}'预期输出包含 version: 1、相同的 id 和 ok: true。不要在 shell 中发送 credential replacement request;用户输入的 secret 应从 password field 经继承的 stdin 传递,避免进入 shell history。
保存失败时,可以在不打印配置的情况下验证配置,并检查权限:
voice-input config >/dev/null
stat -c '%a %n' "$HOME/.config/voice-input" \
"$HOME/.config/voice-input/config.toml"
systemctl --user status voice-input.service目录和文件的预期权限分别为 700 和 600。Revision conflict 表示 Settings 加载后,原始配置的精确内容又发生了变化;请重新加载,再重新应用需要的修改。如果 Settings 表示持久化成功但重启失败,新文件仍然已经保存。此时请分别使用 systemctl 和 journalctl 排查 voice-input.service。
标准部署使用独立的 Quickshell service。只重启 voice-input.service 不会重启 HUD:
systemctl --user restart voice-input-hud.service
journalctl --user -u voice-input-hud.service -f检查 /usr/bin/qs 和安装的 QML:
test -x /usr/bin/qs
ls -l ~/.local/share/voice-input/quickshell/随后分别检查 HUD 的两个输入:
-
state.json提供 phase/transcript。运行voice-input status --follow --format json --extended进行测试。 -
waveform.sock提供包含 30 根 bar 的 NDJSON frame。QML client 会在断开 400 ms 后重试。
如果 status 会变化但 HUD 不显示,请检查 Quickshell/QML、focused-monitor detection 和 voice-input-hud.service。如果 HUD phase 会变化但波形保持不动,请检查 waveform.sock、麦克风 PCM 和 Qwen 语音活动。Realtime Server VAD 没有标记 voice active 时,波形会有意保持隐藏。
常驻 Quickshell HUD 会从 snapshot 读取全部几何控制值。只查看这些不包含 transcript 的字段:
jq '{hud_enabled, hud_margin_bottom, hud_height,
hud_position, hud_offset_x, hud_offset_y}' \
"$XDG_RUNTIME_DIR/voice-input/state.json"hud_enabled 为 false 时,即使 voice-input-hud.service 继续常驻,surface 也会保持隐藏。Margin、height、position 和 offset 不再固定在 QML 中。
只应在 daemon 停止时删除 stale runtime socket。正常启动会自行删除并重新绑定 control 和 waveform socket:
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.service如果停止录音时,实时 session 在 350 ms 宽限期内仍未收到服务端语音事件或非空 transcript,程序会有意取消该 session。日志为:
voice-input realtime ASR: no speech detected; cancelling empty dictation
此时不会执行 final pass、LLM 请求或文本输出。
检查录音:
pw-record --raw --rate 16000 --channels 1 --format s16 /tmp/voice-input-test.raw
# 短暂说话,以 Ctrl+C 停止;确认文件非空,然后删除。
rm -f /tmp/voice-input-test.raw同时检查 audio.device、Qwen 连接、turn_mode、vad_threshold 和 silence_duration_ms。请根据 provider 接受的范围逐步调整 VAD 值。
当前取消判断发生在 manual-mode stop commit 之前。因此,如果 manual session 此前没有产生 transcription event,它可能会被视为静音。排查该问题时优先使用 server-vad。本地 CLI session 不走 realtime 无语音判断。
主动运行 voice-input record cancel 或捕获到空 audio buffer 时,也会按设计直接返回 idle 且不输出文本。
独立采集和共享 pre-roll 采集都会在达到 audio.max_duration_secs 后自动停止;该字段默认为 300 秒。Journal 会显示:
voice-input capture: reached configured 300-second limit; finishing automatically
程序会按正常停止流程继续执行 final ASR、本地 fallback、refinement 和文本输出。增大该值之前,请考虑内存中的 PCM buffer 和 final-pass upload 也会随录音时长增加。
实时音频使用容量受限的非阻塞 queue。如果网络处理速度跟不上,音频采集和波形传输会继续,HUD 会显示 Realtime transcript delayed — audio will recover when stopped,journal 则会报告 audio queue 无法跟上。停止录音后,Voice Input 会拒绝不完整的远程 transcript,并通过 final ASR 或本地 fallback 处理完整录音。如果两条恢复路径都未启用,最终处理会报告没有可用的全音频恢复方式;需要可靠处理长录音时,请启用 final_pass_enabled 或 fallback_to_local。
录音时查看 daemon journal:
journalctl --user -u voice-input.service -f检查:
-
provider = "alibaba-qwen-realtime",并且存在有效的alibaba-api-keycredential; - endpoint region、model ID,以及网络、DNS 和 TLS;
- connect/finalize timeout;
- 启用
fallback_to_local = true时是否存在/usr/bin/voxtype; - 启用
final_pass_enabled = true时的 final model、base URL 和 timeout。
只有 realtime host 为已知的 dashscope.aliyuncs.com、dashscope-intl.aliyuncs.com 或 dashscope-us.aliyuncs.com 时,程序才能从空的 final-pass base URL 推导地址。自定义 host 需要明确填写。
部分 worker 报错后,程序仍可能使用已经生成的 realtime partial/final text。Final pass 失败时,会先退回 realtime final text,再根据配置调用本地 CLI。Queue backpressure 属于不同情况:它可以确定远程 service 收到的音频不完整,因此程序会拒绝其 transcript,只允许使用全音频恢复路径。
test -x /usr/bin/voxtype
/usr/bin/voxtype --helpVoice Input 只通过以下 CLI 形式代理 backend setup:
voice-input setup gpu [backend arguments...]
voice-input setup onnx [backend arguments...]执行识别时,程序会把 engine/model/language flag 和 transcribe <temporary-wav> 传给配置的可执行文件。请在 Voxtype 自身配置中确认选定的 engine/model 已安装。不要设置 backend_command = "voice-input",否则会递归调用本程序。
本地和远程中文最终文本都会调用:
opencc -c t2s # simplified-chinese
opencc -c s2t # traditional-chinese检查命令:
command -v opencc
printf '測試\n' | opencc -c t2s如果无法启动 opencc,识别会返回错误。如果程序可以启动,但退出码非零或输出为空,Voice Input 会保留未转换的 transcript。English、Japanese 和 Korean 不调用 OpenCC。
voice-input llm test
journalctl --user -u voice-input.service -f确认 enabled = true、model 非空、api_base_url 正确,并且存在 openrouter-api-key。带上下文的请求和符合条件的无上下文重试共用一个 deadline。timeout_ms 默认为 15 秒,并限制在 1–30 秒。预算至少为 10 秒时,带上下文的请求会留下最后五秒,以便执行纯 transcript 恢复。
Refinement 在所有失败情况下都会保留 ASR 文本。如果至少还剩一秒,transport error(包括 timeout)、可识别的 payload/context error、无效 response structure、truncation 或带上下文请求的预算耗尽都可以触发纯 transcript 重试。Authentication、rate limit 等不可重试 HTTP response 以及 provider 明确返回的 error 会立即保留原始 ASR 文本。
文本超过 120 个字符后,即使 mode = "type" 也会自动使用 paste。XWayland 默认同样优先 paste。
检查实际路径和工具:
command -v wtype wl-copy wl-paste
command -v xclip xdotool # 仅 XWayland
journalctl --user -u voice-input.service -b | grep 'voice-input output:'日志会显示 target、mode 和 driver,但不会打印文本。请检查:
-
mode = "clipboard"只执行复制,不发送粘贴按键。 - 目标应用可能不接受
shift+Insert;可把paste_keys或xwayland_paste_keys改为应用支持的组合,例如ctrl+v。 - Clipboard manager 或应用可能在 220 ms 恢复等待期间改变 owner。
- 不支持的 clipboard MIME type 或备份失败可能导致无法完整恢复。
- 如果 modifier 尚未释放,可以增加
pre_type_delay_ms;toggle+modifier 快捷键已经强制至少等待 500 ms。 - 可以暂时设置
prefer_paste_for_xwayland = false,用来测试 XWayland 的直接输入;部分 client 可能无法正确处理wtype输入。
运行 voice-input status --format json --extended,检查最近一次解析得到的 output_target、output_mode 和 output_driver;目标对应的 JSON field 名为 output_target_resolved。
只列出 metadata,不要在共享 terminal 或 report 中解密 key:
ls -l ~/.config/credstore.encrypted/
systemctl --user cat voice-input.service
journalctl --user -u voice-input.service -bBlob 名必须恰好为 alibaba-api-key 和 openrouter-api-key。Settings 只提供保留或替换:password field 留空会保留现有 blob,输入非空值则替换 blob,并在提交后清空该字段。Test LLM 会优先使用刚输入的 LLM key;没有输入时则使用加密 credential store 中的值。修改 credential 后执行:
systemctl --user restart voice-input.service只有 systemd 启动的 service 会收到加密 credential。手动运行的 voice-input daemon 没有 $CREDENTIALS_DIRECTORY,除非它运行在适当的 credential context 中;它可以使用文档说明的环境变量 fallback,同时需要承担相应的暴露风险。
如果 Settings 无法加密或解密,请确认系统存在 systemd-creds,并且用户级 systemd credential 机制可以工作。不要把 key 写入公开 TOML 示例或 issue log。
重启 Pi 或 reload extension。已安装的 TypeScript file 不会自动加载到现有 Pi process:
ls -l ~/.pi/agent/extensions/voice-input-session-registry.ts
ls -l "$XDG_RUNTIME_DIR/voice-input/agent-sessions/"重启 Pi 后仍没有 registry 时,请检查 Pi extension loading。存在 registry 时,请确认 Pi 是 Kitty window 中当前 focused foreground process,并且 Kitty endpoint 恰好为 /tmp/kitty-<kitty-pid>。完整验证流程见 Agent 上下文。
Codex 不使用该 extension;它必须在 CODEX_HOME/sessions 下恰好打开一个符合条件的 CLI session JSONL。
使用结构化 timing line,不要直接导出 state 或 session file:
journalctl --user -u voice-input.service -b \
| grep -E 'first partial|session finished|voice-input refinement:|voice-input output:'这些 line 通常只包含 elapsed time、计数、outcome 和 driver,不包含 transcript/context。Provider/backend error 仍可能带有外部诊断内容。分享前请阅读并脱敏;不要附加 state.json、Pi/Codex JSONL、原始音频、credential 或未经检查的完整 journal。
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 前,请阅读安全与隐私。