From bb91674a84b22058da2bd5bebe2c0cd1b576d018 Mon Sep 17 00:00:00 2001 From: Idris Gadi Date: Tue, 1 Sep 2026 19:03:22 +0530 Subject: [PATCH 01/12] feat(whisper): verify GPU backends and add Vulkan fallback --- LOCAL_WHISPER_SETUP.md | 9 +- src/components/TranscriptionModelPicker.tsx | 18 ++-- src/helpers/gpuBinaryManager.js | 15 +++- src/helpers/ipcHandlers.js | 6 +- src/helpers/whisper.js | 12 +-- src/helpers/whisperCudaManager.js | 6 ++ src/helpers/whisperServer.js | 90 ++++++++++++++----- src/locales/de/translation.json | 6 ++ src/locales/en/translation.json | 6 ++ src/locales/es/translation.json | 6 ++ src/locales/fr/translation.json | 6 ++ src/locales/it/translation.json | 6 ++ src/locales/ja/translation.json | 6 ++ src/locales/pt/translation.json | 6 ++ src/locales/ru/translation.json | 6 ++ src/locales/zh-CN/translation.json | 6 ++ src/locales/zh-TW/translation.json | 6 ++ test/helpers/gpuBinaryManager.test.js | 65 +++++++++++--- .../whisperCudaRequestFallback.test.js | 47 +++++++++- test/helpers/whisperGpuResolve.test.js | 41 ++++++++- test/helpers/whisperServerGpuGuard.test.js | 46 +++++----- 21 files changed, 334 insertions(+), 81 deletions(-) diff --git a/LOCAL_WHISPER_SETUP.md b/LOCAL_WHISPER_SETUP.md index 6545a0fef7..97fae87bab 100644 --- a/LOCAL_WHISPER_SETUP.md +++ b/LOCAL_WHISPER_SETUP.md @@ -28,10 +28,11 @@ The first transcription will download the model automatically. Local Whisper can run on your GPU for much faster transcription: - **macOS**: Metal acceleration is built in — no setup needed on Apple Silicon -- **NVIDIA (Windows/Linux)**: one-click CUDA runtime download from the GPU card in the transcription model picker -- **AMD / Intel (Windows/Linux)**: one-click Vulkan runtime download from the same GPU card — covers Radeon and Arc/integrated GPUs +- **NVIDIA (Windows/Linux)**: CUDA acceleration; Linux requires a current compatible NVIDIA driver, but not the CUDA Toolkit +- **AMD / Intel (Windows/Linux)**: Vulkan acceleration for Radeon, Arc, and integrated GPUs +- **NVIDIA alternative**: Vulkan is also supported and is used automatically when its runtime is installed and CUDA fails -The GPU runtime is downloaded on demand with SHA-256-verified checksums. If the GPU server crashes or fails to start (unsupported GPU, out of VRAM), OpenWhispr automatically falls back to CPU transcription and shows a notice — dictation keeps working. +GPU runtimes are downloaded on demand with SHA-256-verified checksums. If one fails, OpenWhispr uses the next available backend and finally CPU, so dictation keeps working. ## How It Works @@ -45,7 +46,7 @@ OpenWhispr uses whisper.cpp, a high-performance C++ implementation of OpenAI's W - **Disk Space**: 75MB–3GB depending on model - **RAM**: 1GB–10GB depending on model -- **No additional dependencies required** - whisper.cpp is bundled in packaged builds +- **GPU driver**: required for GPU acceleration; the CUDA Toolkit is not required ## Running From Source diff --git a/src/components/TranscriptionModelPicker.tsx b/src/components/TranscriptionModelPicker.tsx index 6473d02cdf..fbf0d6d7cb 100644 --- a/src/components/TranscriptionModelPicker.tsx +++ b/src/components/TranscriptionModelPicker.tsx @@ -412,6 +412,7 @@ export default function TranscriptionModelPicker({ const [gpuActivating, setGpuActivating] = useState(false); // Live truth from the running server; "active" is never inferred from a download const [gpuActive, setGpuActive] = useState(false); + const gpuBackendName = gpuBackend === "cuda" ? "CUDA" : "Vulkan"; useEffect(() => { if (selectedLocalProvider !== internalLocalProvider) { @@ -709,7 +710,11 @@ export default function TranscriptionModelPicker({ ?.whisperServerStatus?.() .then((status) => { setGpuActive(!!status?.gpuAccelerated); - if (status?.gpuAccelerated) setGpuActivating(false); + if (status?.gpuAccelerated && status.gpuBackend) { + setGpuBackend(status.gpuBackend); + setGpuActivating(false); + setGpuFailed(false); + } }) .catch(() => {}); }; @@ -1349,21 +1354,21 @@ export default function TranscriptionModelPicker({ <> - {t("gpu.activating")} + {t("gpu.activatingBackend", { backend: gpuBackendName })} ) : gpuActive ? ( <> - {t("gpu.active")} + {t("gpu.activeBackend", { backend: gpuBackendName })} ) : ( <> - {t("gpu.ready")} + {t("gpu.readyBackend", { backend: gpuBackendName })} )} @@ -1385,6 +1390,9 @@ export default function TranscriptionModelPicker({

{t("gpu.transcriptionBanner")}

+

+ {t(gpuBackend === "cuda" ? "gpu.cudaDescription" : "gpu.vulkanDescription")} +