Install Windows CUDA runtime for STT
This commit is contained in:
10
README.md
10
README.md
@@ -118,13 +118,7 @@ Discord 모드에서만 필수:
|
|||||||
- `DEBUG_TEXT_EVENTS`
|
- `DEBUG_TEXT_EVENTS`
|
||||||
- `true`면 transcript/reply를 콘솔에 같이 출력
|
- `true`면 transcript/reply를 콘솔에 같이 출력
|
||||||
|
|
||||||
Windows에서 STT 시작 시 `cublas64_12.dll` 같은 CUDA 오류가 나면:
|
Windows에서 GPU STT를 쓰려면 `LOCAL_STT_DEVICE=auto` 그대로 두고 `bun run setup:local-ai`를 다시 실행하세요. 현재 스크립트는 `faster-whisper`와 함께 CUDA 12용 `cuBLAS`, `cuDNN` 런타임 wheel도 같이 설치합니다. 그래도 `cublas64_12.dll` 또는 `cudnn` 오류가 남으면 시스템에 Visual C++ 런타임이 빠졌거나, 별도 CUDA 설치 경로가 PATH에 안 잡힌 경우입니다.
|
||||||
|
|
||||||
```env
|
|
||||||
LOCAL_STT_DEVICE=cpu
|
|
||||||
```
|
|
||||||
|
|
||||||
로 두면 바로 우회됩니다. 최신 코드는 `auto`일 때도 가능한 경우 CPU로 자동 fallback 합니다.
|
|
||||||
|
|
||||||
## 속도 우선 기본값
|
## 속도 우선 기본값
|
||||||
|
|
||||||
@@ -156,7 +150,7 @@ OLLAMA_MODEL=qwen3:1.7b
|
|||||||
- Windows는 TTS를 Python 모델 대신 시스템 기본 음성 엔진으로 처리합니다.
|
- Windows는 TTS를 Python 모델 대신 시스템 기본 음성 엔진으로 처리합니다.
|
||||||
- 출력 장치 직접 선택은 아직 미구현이라 시스템 기본 출력 장치로 재생됩니다.
|
- 출력 장치 직접 선택은 아직 미구현이라 시스템 기본 출력 장치로 재생됩니다.
|
||||||
- Python 탐지가 안 되면 `.env` 에 `LOCAL_AI_PYTHON=python` 또는 `LOCAL_AI_PYTHON=py -3` 를 넣으면 됩니다.
|
- Python 탐지가 안 되면 `.env` 에 `LOCAL_AI_PYTHON=python` 또는 `LOCAL_AI_PYTHON=py -3` 를 넣으면 됩니다.
|
||||||
- Windows의 `setup:local-ai`는 STT만 설치합니다.
|
- Windows의 `setup:local-ai`는 STT와 CUDA 런타임 wheel을 함께 설치합니다.
|
||||||
- Linux/macOS의 `setup:local-ai`는 Kokoro ONNX 모델 파일도 자동으로 내려받습니다.
|
- Linux/macOS의 `setup:local-ai`는 Kokoro ONNX 모델 파일도 자동으로 내려받습니다.
|
||||||
|
|
||||||
## 설계 메모
|
## 설계 메모
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import glob
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import site
|
||||||
import sys
|
import sys
|
||||||
|
import sysconfig
|
||||||
import tempfile
|
import tempfile
|
||||||
import traceback
|
import traceback
|
||||||
import wave
|
import wave
|
||||||
@@ -44,6 +48,71 @@ def resolve_device() -> str:
|
|||||||
return "cpu"
|
return "cpu"
|
||||||
|
|
||||||
|
|
||||||
|
def configure_windows_cuda_runtime() -> None:
|
||||||
|
if os.name != "nt":
|
||||||
|
return
|
||||||
|
|
||||||
|
candidate_dirs: list[str] = []
|
||||||
|
|
||||||
|
for key in ("CUDA_PATH", "CUDA_HOME"):
|
||||||
|
value = os.environ.get(key)
|
||||||
|
if value:
|
||||||
|
candidate_dirs.append(os.path.join(value, "bin"))
|
||||||
|
|
||||||
|
for key, value in os.environ.items():
|
||||||
|
if key.startswith("CUDA_PATH_V") and value:
|
||||||
|
candidate_dirs.append(os.path.join(value, "bin"))
|
||||||
|
|
||||||
|
candidate_dirs.extend(
|
||||||
|
sorted(glob.glob(r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin"), reverse=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
site_roots: list[str] = []
|
||||||
|
try:
|
||||||
|
site_roots.extend(site.getsitepackages())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
site_roots.append(site.getusersitepackages())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for key in ("purelib", "platlib"):
|
||||||
|
value = sysconfig.get_paths().get(key)
|
||||||
|
if value:
|
||||||
|
site_roots.append(value)
|
||||||
|
|
||||||
|
for root in site_roots:
|
||||||
|
nvidia_root = Path(root) / "nvidia"
|
||||||
|
if not nvidia_root.is_dir():
|
||||||
|
continue
|
||||||
|
|
||||||
|
for pattern in ("**/cublas64_12.dll", "**/cudnn*.dll", "**/cudart64*.dll"):
|
||||||
|
for dll_path in nvidia_root.glob(pattern):
|
||||||
|
candidate_dirs.append(str(dll_path.parent))
|
||||||
|
|
||||||
|
unique_dirs: list[str] = []
|
||||||
|
for candidate in candidate_dirs:
|
||||||
|
normalized = os.path.normpath(candidate)
|
||||||
|
if not os.path.isdir(normalized):
|
||||||
|
continue
|
||||||
|
if normalized in unique_dirs:
|
||||||
|
continue
|
||||||
|
unique_dirs.append(normalized)
|
||||||
|
|
||||||
|
for directory in unique_dirs:
|
||||||
|
try:
|
||||||
|
os.add_dll_directory(directory)
|
||||||
|
except (AttributeError, FileNotFoundError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if unique_dirs:
|
||||||
|
existing_path = os.environ.get("PATH", "")
|
||||||
|
os.environ["PATH"] = os.pathsep.join(unique_dirs + [existing_path])
|
||||||
|
log(f"configured CUDA DLL search paths: {', '.join(unique_dirs)}")
|
||||||
|
|
||||||
|
|
||||||
def resolve_compute_type(device: str) -> str:
|
def resolve_compute_type(device: str) -> str:
|
||||||
raw = os.environ.get("LOCAL_STT_COMPUTE_TYPE", "auto").strip().lower()
|
raw = os.environ.get("LOCAL_STT_COMPUTE_TYPE", "auto").strip().lower()
|
||||||
if raw and raw != "auto":
|
if raw and raw != "auto":
|
||||||
@@ -55,6 +124,7 @@ def resolve_compute_type(device: str) -> str:
|
|||||||
|
|
||||||
class SttWorker:
|
class SttWorker:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
configure_windows_cuda_runtime()
|
||||||
from faster_whisper import WhisperModel
|
from faster_whisper import WhisperModel
|
||||||
|
|
||||||
self.model_name = os.environ.get("LOCAL_STT_MODEL", "tiny").strip() or "tiny"
|
self.model_name = os.environ.get("LOCAL_STT_MODEL", "tiny").strip() or "tiny"
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
faster-whisper==1.2.1
|
faster-whisper==1.2.1
|
||||||
|
nvidia-cublas-cu12
|
||||||
|
nvidia-cudnn-cu12>=9,<10
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ async function main(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log("로컬 AI 의존성 설치를 시작합니다.");
|
console.log("로컬 AI 의존성 설치를 시작합니다.");
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
console.log("Windows GPU STT용 CUDA 런타임 패키지도 함께 확인합니다.");
|
||||||
|
}
|
||||||
await run(venvPython, ["-m", "pip", "install", "--upgrade", "pip", "setuptools", "wheel"], baseEnv);
|
await run(venvPython, ["-m", "pip", "install", "--upgrade", "pip", "setuptools", "wheel"], baseEnv);
|
||||||
await run(venvPython, ["-m", "pip", "install", "-r", requirementsPath], baseEnv);
|
await run(venvPython, ["-m", "pip", "install", "-r", requirementsPath], baseEnv);
|
||||||
if (process.platform !== "win32") {
|
if (process.platform !== "win32") {
|
||||||
|
|||||||
Reference in New Issue
Block a user