2026-08-14_本地GPU语音输入法部署手册

本地 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同机 WSLhttp://localhost:8000/v1/audio/transcriptions(WSL2 localhost 转发默认开);跨机器http://<服务端IP>:8000/v1/audio/transcriptions
  • api_key:自建服务可为空字符串;云端服务填对应 key
  • hotkeyWindows 上别用 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 -ForceStart-Process)。

Step 5: 使用

  1. 打开任意可输入文字的窗口(记事本/微信/浏览器/终端)
  2. Alt+Space(出现波形小球 = 录音中),说话
  3. 再按 Alt+Space 停止 → 文字自动输入光标处 + 复制剪贴板
  4. 说话自然一点(整句转写,非流式;一个字一个字蹦效果差)

四、性能验证(每台机器跑一次,记录基线)

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 安全限制 wtypedotool;X11 无此问题
服务重启后模型重新下载 缓存不完整被覆盖 确认 ~/.cache/whisper/*.pt 大小(large-v3=2.88GB,不是 756MB)

六、扩展玩法

  • 换云端服务api_urlhttps://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.jsonhttp://localhost:8000
  • ✅ 端到端验证:Windows TTS 合成"你好,这是语音输入测试" → 识别返回正确
posted on 2026-08-14 00:29  风惊庭前叶  阅读(9)  评论(0)    收藏  举报