本地 GPU 语音输入法部署手册
用本地显卡跑 whisper 模型,Windows/Linux 装客户端,快捷键说话 → GPU 转文字 → 自动输入到光标处,当输入法用。全程本地推理,语音不出内网。
关联概念: [[概念/编程]] | [[概念/运维]] | [[概念/开源]]
架构总览
┌─ GPU 机器(Linux/WSL,跑模型当服务器)─┐ ┌─ 客户端机器(Windows/Linux/macOS)──┐
│ whisper (openai 原版) + FastAPI │ │ turbo-whisper (knowall-ai) │
│ POST /v1/audio/transcriptions │HTTP │ 全局热键录语音 → POST → 自动输入 │
│ OpenAI 兼容,监听 0.0.0.0:8000 │◄────►│ 配置 api_url 指向服务端 IP/域名 │
└─────────────────────────────────────────┘ └─────────────────────────────────────┘
- 服务端:whisper 模型常驻 GPU,FastAPI 暴露 OpenAI 兼容的
/v1/audio/transcriptions - 客户端:turbo-whisper(MIT,Python/PyQt6),全局快捷键录音,转好的文字自动输入到当前光标位置(模拟键盘),同时复制剪贴板
- 同机部署(WSL + Windows):WSL2 默认 localhost 转发,Windows 客户端直接填
http://localhost:8000即可,无需知道 WSL IP。跨机器部署填http://<服务端IP>:8000
为什么这套组合
- whisper large-v3 中文识别效果好,GPU 上 10-25x 实时速度
- OpenAI 兼容 API 是事实标准:客户端以后想换云端(豆包/OpenAI/GROQ)只改
api_url - 服务端实现可替换:Speaches(原 fedirz/faster-whisper-server)、whisper-asr-webservice (Docker)、WhisperLiveKit 都兼容同一个客户端
一、前置检查(先做,避免装错)
1. GPU 检测
WSL 里 nvidia-smi 可能不在 PATH,三个位置都试:
if nvidia-smi >/dev/null 2>&1; then nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv
elif /usr/lib/wsl/lib/nvidia-smi >/dev/null 2>&1; then /usr/lib/wsl/lib/nvidia-smi --query-gpu=name,memory.total --format=csv
elif /mnt/c/Windows/System32/nvidia-smi.exe >/dev/null 2>&1; then /mnt/c/Windows/System32/nvidia-smi.exe --query-gpu=name,memory.total --format=csv
else echo "NO GPU"; fi
没有 GPU 也能跑(CPU 慢,用 small 模型),但语音输入法体验差,不建议。
2. 检查已有 whisper 环境(很多机器已有,避免重复装)
ls ~/trading-venv/bin/whisper 2>/dev/null && echo "已有 trading-venv"
~/trading-venv/bin/python -c "import whisper, fastapi, uvicorn; print('whisper+fastapi+uvicorn OK')" 2>&1
# 模型缓存(whisper 下载到 ~/.cache/whisper/*.pt)
ls -la ~/.cache/whisper/ 2>/dev/null
3. 模型选择(中文必须 large-v3;小模型中文错字多)
⚠️ 缓存里 .pt 文件不完整时 whisper 会静默重新下载完整版(large-v3 完整 = 2.88GB)。下载源 openaipublic.azureedge.net,国内约 7-8MB/s,需 7-8 分钟,耐心等。
显存参考(fp16):
| 模型 | VRAM | 中文效果 | 建议 |
|---|---|---|---|
| small | ~2GB | 较差 | CPU 机器 |
| medium | ~5GB | 中等 | 4-6GB 卡 |
| large-v3 | ~10GB | 好 | 8GB+ 卡首选 |
二、服务端安装(GPU 机器 = Linux/WSL)
Step 1: 环境准备
无 whisper 环境时(有就跳过):
python3 -m venv ~/whisper-server
~/whisper-server/bin/pip install --upgrade pip -q
~/whisper-server/bin/pip install -q openai-whisper fastapi "uvicorn[standard]" python-multipart
# 国内镜像:-i https://pypi.tuna.tsinghua.edu.cn/simple
已有 ~/trading-venv(含 whisper+fastapi+uvicorn+torch cu128)的直接复用,不用建新 venv。
Step 2: 写服务端脚本 ~/whisper-server/server.py
#!/usr/bin/env python3
"""OpenAI 兼容的 Whisper 转录服务 — 供 turbo-whisper 客户端调用。
POST /v1/audio/transcriptions (multipart: file, model, language)
返回 {"text": "..."}
"""
import os
import tempfile
from fastapi import FastAPI, UploadFile, File, Form
import whisper
app = FastAPI(title="Whisper Local Server")
print("Loading whisper large-v3 on GPU...", flush=True)
model = whisper.load_model("large-v3", device="cuda")
print("Model loaded.", flush=True)
@app.post("/v1/audio/transcriptions")
async def transcribe(
file: UploadFile = File(...),
model_name: str = Form(default="large-v3"),
language: str = Form(default=None),
):
data = await file.read()
# ⚠️ whisper.load_audio 只接受文件路径(内部调 ffmpeg 子进程),
# 传 BytesIO 会 TypeError: expected str, bytes or os.PathLike, not BytesIO
suffix = os.path.splitext(file.filename or "audio.wav")[1] or ".wav"
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
tmp.write(data)
tmp_path = tmp.name
try:
audio = whisper.load_audio(tmp_path)
result = model.transcribe(
audio,
language=language if language and language != "auto" else None,
fp16=True,
)
return {"text": result["text"].strip()}
finally:
os.unlink(tmp_path)
@app.get("/health")
async def health():
return {"status": "ok", "model": "large-v3", "device": "cuda"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Step 3: 启动(后台常驻)
# 手动启动(终端方式,Ctrl+C 停止)
~/trading-venv/bin/python ~/whisper-server/server.py
# 开机自启(systemd 用户级服务)
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/whisper-server.service << 'EOF'
[Unit]
Description=Whisper transcription server
After=network.target
[Service]
ExecStart=/home/mgter/trading-venv/bin/python /home/mgter/whisper-server/server.py
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload && systemctl --user enable --now whisper-server
启动时间:模型加载到 GPU 约 40-60 秒(large-v3),加载完才监听端口。启动后等 1 分钟再测。
Step 4: 验证服务端
# 健康检查
curl -s http://localhost:8000/health
# 期望: {"status":"ok","model":"large-v3","device":"cuda"}
# 转录验证(随便一个 wav 文件)
curl -s -X POST http://localhost:8000/v1/audio/transcriptions \
-F "file=@/path/to/test.wav" -F "model=large-v3" -F "language=zh"
# 期望: {"text":"识别出的文字"}
三、客户端安装(Windows 举例;Linux/macOS 同思路)
Step 1: 环境检查
python --version # 需 3.10+
git --version
Step 2: 克隆 + venv + 依赖
cd /mnt/c/Users/<用户名> # WSL 侧操作 Windows 文件
git clone https://github.com/knowall-ai/turbo-whisper.git
cd turbo-whisper
python -m venv .venv
.venv/Scripts/python.exe -m pip install --upgrade pip
# 依赖:PyQt6 numpy httpx pynput pyautogui pyaudio
# 国内:-i https://pypi.tuna.tsinghua.edu.cn/simple
.venv/Scripts/python.exe -m pip install -e . -i https://pypi.tuna.tsinghua.edu.cn/simple
- ⚠️ 必须
pip install -e .(只装 requirements 会ModuleNotFoundError: turbo_whisper) - ✅ pyaudio 现在有官方 win_amd64 wheel(cp313 直接装成功),不再需要 pipwin
- pyproject.toml 的
scripts: turbo-whisper = turbo_whisper.main:main,入口是pythonw -m turbo_whisper.main
Step 3: 配置 %APPDATA%\turbo-whisper\config.json
(WSL 路径:/mnt/c/Users/<用户名>/AppData/Roaming/turbo-whisper/config.json)
{
"api_url": "http://localhost:8000/v1/audio/transcriptions",
"api_key": "",
"hotkey": ["alt", "space"],
"sample_rate": 16000,
"channels": 1,
"chunk_size": 1024,
"input_device_index": null,
"input_device_name": "",
"waveform_color": "#84cc16",
"background_color": "#1a1a2e",
"window_width": 520,
"window_height": 260,
"auto_paste": true,
"copy_to_clipboard": true,
"language": "zh",
"history": [],
"history_max": 20
}
关键字段:
api_url:同机 WSL 填http://localhost:8000/v1/audio/transcriptions(WSL2 localhost 转发默认开);跨机器填http://<服务端IP>:8000/v1/audio/transcriptionsapi_key:自建服务可为空字符串;云端服务填对应 keyhotkey:Windows 上别用 Ctrl+Shift+Space(易和输入法/系统快捷键冲突),实测["alt","space"]稳定language:"zh"(whisper 自动加标点,中文效果好)
Step 4: 启动客户端(Windows)
# 无窗口后台启动
Start-Process -FilePath "C:\Users\<用户名>\turbo-whisper\.venv\Scripts\pythonw.exe" `
-ArgumentList "-m","turbo_whisper.main" -WorkingDirectory "C:\Users\<用户名>\turbo-whisper"
验证在跑(turbo-whisper 会监听本地 7878 端口):
Get-NetTCPConnection -State Listen | Where-Object LocalPort -eq 7878
# LocalAddress 127.0.0.1 LocalPort 7878 OwningProcess <pid> = 活着
改配置后要重启进程(Stop-Process -Name pythonw -Force 再 Start-Process)。
Step 5: 使用
- 打开任意可输入文字的窗口(记事本/微信/浏览器/终端)
- 按
Alt+Space(出现波形小球 = 录音中),说话 - 再按
Alt+Space停止 → 文字自动输入光标处 + 复制剪贴板 - 说话自然一点(整句转写,非流式;一个字一个字蹦效果差)
四、性能验证(每台机器跑一次,记录基线)
1. 服务端性能脚本
~/trading-venv/bin/python << 'EOF'
import whisper, time, torch, numpy as np
# 1. GPU 显存
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}, VRAM: {torch.cuda.get_device_properties(0).total_memory/1e9:.1f}GB")
# 2. 模型加载耗时
t0 = time.time()
model = whisper.load_model("large-v3", device="cuda")
print(f"模型加载: {time.time()-t0:.1f}s")
# 3. 转写延迟(用真实语音文件最准;无文件则合成音频测管线)
sr = 16000
t = np.linspace(0, 1.0, sr)
audio = (0.3*np.sin(2*np.pi*440*t) + 0.1*np.random.randn(sr)).astype(np.float32)
t0 = time.time()
r = model.transcribe(audio, language="zh", fp16=True)
print(f"1s音频转写: {time.time()-t0:.2f}s | 输出: {r['text'][:30]}")
EOF
2. 端到端验证(Windows 侧,最真实)
用 Windows 系统 TTS 合成中文语音 → POST 到服务端 → 核对识别文本:
# 1. 合成测试音频
Add-Type -AssemblyName System.Speech
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
$synth.SetOutputToWaveFile("C:\Users\<用户名>\test_voice.wav")
$synth.Speak("你好,这是语音输入测试")
$synth.Dispose()
# 2. 从 Windows 侧调服务(测 WSL localhost 转发 + 转录全链路)
curl.exe -s -X POST http://localhost:8000/v1/audio/transcriptions `
-F "file=@C:\Users\<用户名>\test_voice.wav" -F "model=large-v3" -F "language=zh"
# 期望: {"text":"你好,这是语音输入测试。"} ← 文本匹配即全链路通
3. 参考基线(RTX 5070 12GB 实测 2026-08)
| 指标 | 实测值 |
|---|---|
| large-v3 模型下载(国内) | 7-8 min(2.88GB,~7MB/s) |
| large-v3 加载到 GPU | ~50s |
| medium 加载到 GPU | ~7s |
| 1s 中文音频转写 | <1s(GPU) |
| 端到端(Win TTS→WSL 转录→返回) | 数秒内 |
| 服务端常驻显存 | ~10GB (large-v3 fp16) |
五、排障表
| 症状 | 原因 | 解决 |
|---|---|---|
500 Internal Server Error + TypeError: expected str... not BytesIO |
whisper.load_audio 不接受内存对象 |
先落盘临时文件再 load(见 server.py 模板) |
| 客户端按快捷键没反应 | 服务端没起 / 端口不对 | curl localhost:8000/health;服务端启动要等 1 分钟(模型加载) |
| Windows curl 通但客户端不行 | 配置 api_url 路径少了 /v1/audio/transcriptions |
补全完整路径 |
| 快捷键和输入法打架 | Ctrl+Shift+Space 冲突 | 换 ["alt","space"] |
| 中文识别一堆错字 | 用了 small/medium | 换 large-v3 |
ModuleNotFoundError: turbo_whisper |
没做 editable install | pip install -e . |
| PyAudio 装不上(旧教程说用 pipwin) | 旧信息 | 直接 pip install pyaudio,cp313+ 有官方 wheel |
| WSL 里服务端起了但 Windows 连不上 localhost:8000 | WSL2 转发异常 | wsl --shutdown 重启 WSL;确认服务监听 0.0.0.0 而非 127.0.0.1 |
| Linux 客户端(Wayland)自动输入失效 | Wayland 安全限制 | 装 wtype 或 dotool;X11 无此问题 |
| 服务重启后模型重新下载 | 缓存不完整被覆盖 | 确认 ~/.cache/whisper/*.pt 大小(large-v3=2.88GB,不是 756MB) |
六、扩展玩法
- 换云端服务:
api_url改https://api.openai.com/v1/audio/transcriptions+ 填 key;豆包/GROQ/SiliconFlow 同理(OpenAI 兼容) - 换服务端实现(客户端不用改):Speaches(Docker)、whisper-asr-webservice(Docker)、WhisperLiveKit(流式延迟最低)
- 多客户端:同一个服务端可挂多个客户端(家里 Windows + 公司 Linux 都指向它)
- AI CLI 工具联动:turbo-whisper 支持 Claude Code 集成(
claude_integration+ post-response hook),语音给 Claude Code 下指令 - 音频存档:turbo-whisper
history字段记录历史,可回放
部署清单(本机已部署)
- ✅ 服务端:
~/whisper-server/server.py,whisper large-v3 + GPU,监听 8000 - ✅ 客户端:
C:\Users\37036\turbo-whisper(Windows,pythonw 后台运行,监听 7878) - ✅ 配置:
%APPDATA%\turbo-whisper\config.json→http://localhost:8000 - ✅ 端到端验证:Windows TTS 合成"你好,这是语音输入测试" → 识别返回正确
浙公网安备 33010602011771号