Summary
On Windows with an AMD Radeon iGPU, pressing the dictation shortcut (Ctrl+Alt+Z) kills the entire pi process on the first transcription. The terminal survives, but the pi session ends instantly with no error message, no notification, and no entry in ~/.pi/agent/crashes.json — it looks like pi "just closes".
Root cause is a native access violation in the transcribe.cpp Vulkan backend during inference, not a pi-voice logic error. Because it's a native SIGSEGV, no JS uncaughtException / process.exit handler can run, so pi has no chance to report anything. This issue is mostly about making that failure mode visible and recoverable.
Steps to reproduce
- Windows + AMD Radeon iGPU (Vega 8, driver 31.0.21925.1001 here; a Vega-era AMD driver in general).
- Install and configure pi-voice with a catalog model (Parakeet Unified EN 0.6B).
- Start pi, press
Ctrl+Alt+Z.
Result: pi exits immediately. Terminal is fine. No message.
Root cause (confirmed)
Reduced it outside pi entirely, using the same installed packages (transcribe-cpp@0.2.2, @transcribe-cpp/win32-x64-cpu-vulkan@0.2.2):
const model = await TranscribeModel.load(modelPath); // model.backend === "Vulkan0"
const session = model.createSession();
const stream = await session.stream({ timestamps: "none", language: "en" });
for (...) await stream.feed(frame); // or model.transcribe(pcm)
// → Segmentation fault (Windows exit code -1073741819 / 0xC0000005)
- Any compute crashes: streaming (
feed()/finalize()) and batch (transcribe()) both die.
- Audio content is irrelevant — 512 samples of silence reproduce it.
PvRecorder itself works; model load works; ffmpeg is installed and fine.
- It's a memory-corruption-style crash: sometimes dies mid-
feed(), sometimes in finalize().
This is the known upstream issue: handy-computer/transcribe.cpp#163, a ggml regression after the ggml v0.20.2 upgrade in transcribe.cpp v0.2.1+, affecting AMD GPUs. I added a second reproduction there.
Why it's bad UX in pi-voice specifically
- Losing the whole pi process on a dictation attempt is disproportionate and destroys the session/context.
- There is no signal at all about what happened. Users would reasonably suspect the keybinding or pi itself (I did).
~/.pi/agent/crashes.json is not written, because the process is killed by the OS before pi's crash handler can run — so pi's own crash tooling (/bug, crash resume hints) can't help here either.
Workaround
Forcing the CPU backend works reliably here:
set GGML_VK_VISIBLE_DEVICES=-1
ggml then registers no Vulkan device, and TranscribeModel.load() selects CPU. Verified with your exact flow: mic capture + streaming + finalize all pass, and a 7s TTS clip transcribes correctly in ~1.9s on a Ryzen 5 PRO 3500U.
Also works but is not persistent: passing { backend: "cpu" } to TranscribeModel.load().
Suggestions
Any of these would help; the first two are the important ones:
- Make the backend selectable in
/voice-settings (auto / cpu / vulkan / cuda / metal), persisted in pi-voice.json and passed through TranscribeCppBackend to TranscribeModel.load(). This gives users a supported escape hatch without patching installed files or setting global env vars.
- Document the
GGML_VK_VISIBLE_DEVICES=-1 workaround, and perhaps auto-fall back to CPU when a Win32/Vulkan load is followed by a crash (hard to detect, admittedly — but even a post-crash notice on next start would be better than silence).
- Optionally: since transcribe.cpp#163 has been open for AMD+Windows for a while, consider defaulting to CPU on
win32 when the only GPU backend is an AMD iGPU, or bundling the CPU-only provider package.
Happy to test a build or provide any additional traces.
Environment
- pi: 0.87.1
- pi-voice: 0.1.0 (npm), settings at
~/.pi/agent/pi-voice.json
- OS: Windows 10 IoT Enterprise LTSC 10.0.19044.7725
- CPU/GPU: AMD Ryzen 5 PRO 3500U / Radeon Vega 8 (driver 31.0.21925.1001)
- Node: 22.23.2
- Model:
parakeet-unified-en-0.6b (Q8_0)
Summary
On Windows with an AMD Radeon iGPU, pressing the dictation shortcut (
Ctrl+Alt+Z) kills the entirepiprocess on the first transcription. The terminal survives, but the pi session ends instantly with no error message, no notification, and no entry in~/.pi/agent/crashes.json— it looks like pi "just closes".Root cause is a native access violation in the
transcribe.cppVulkan backend during inference, not a pi-voice logic error. Because it's a native SIGSEGV, no JSuncaughtException/process.exithandler can run, so pi has no chance to report anything. This issue is mostly about making that failure mode visible and recoverable.Steps to reproduce
Ctrl+Alt+Z.Result: pi exits immediately. Terminal is fine. No message.
Root cause (confirmed)
Reduced it outside pi entirely, using the same installed packages (
transcribe-cpp@0.2.2,@transcribe-cpp/win32-x64-cpu-vulkan@0.2.2):feed()/finalize()) and batch (transcribe()) both die.PvRecorderitself works; model load works; ffmpeg is installed and fine.feed(), sometimes infinalize().This is the known upstream issue: handy-computer/transcribe.cpp#163, a ggml regression after the ggml v0.20.2 upgrade in transcribe.cpp v0.2.1+, affecting AMD GPUs. I added a second reproduction there.
Why it's bad UX in pi-voice specifically
~/.pi/agent/crashes.jsonis not written, because the process is killed by the OS before pi's crash handler can run — so pi's own crash tooling (/bug, crash resume hints) can't help here either.Workaround
Forcing the CPU backend works reliably here:
ggml then registers no Vulkan device, and
TranscribeModel.load()selects CPU. Verified with your exact flow: mic capture + streaming + finalize all pass, and a 7s TTS clip transcribes correctly in ~1.9s on a Ryzen 5 PRO 3500U.Also works but is not persistent: passing
{ backend: "cpu" }toTranscribeModel.load().Suggestions
Any of these would help; the first two are the important ones:
/voice-settings(auto / cpu / vulkan / cuda / metal), persisted inpi-voice.jsonand passed throughTranscribeCppBackendtoTranscribeModel.load(). This gives users a supported escape hatch without patching installed files or setting global env vars.GGML_VK_VISIBLE_DEVICES=-1workaround, and perhaps auto-fall back to CPU when a Win32/Vulkan load is followed by a crash (hard to detect, admittedly — but even a post-crash notice on next start would be better than silence).win32when the only GPU backend is an AMD iGPU, or bundling the CPU-only provider package.Happy to test a build or provide any additional traces.
Environment
~/.pi/agent/pi-voice.jsonparakeet-unified-en-0.6b(Q8_0)