Skip to content

Repository files navigation

私有高质量全局语音输入(FunASR + Windows)

这套方案把「录音 -> GPU FunASR -> CPU fallback -> 当前输入框」串起来。Windows 客户端只需要一个快捷键,Codex、Terminal、Joplin、浏览器、VS Code、ChatGPT 等所有可粘贴文本的程序都能使用。

1. 本机网关(CPU fallback)

cd ~/ASR
cp .env.example .env
openssl rand -hex 32                 # 将输出填入 .env 的 ASR_API_TOKEN
docker compose up -d --build
curl http://127.0.0.1:45679/v1/health

健康检查中的 ok=true 表示 HTTP 服务正常;ready=true 表示模型已经加载。首次模型下载前 ready 可能是 false,这是正常的。

如果 Docker Hub 在当前网络不可达,可执行 bash deploy/build-with-mirror.sh 使用镜像代理拉取基础镜像,再执行 docker compose up -d。脚本只处理基础镜像,Python 包仍从 PyPI 下载。

若 Docker/PyPI/ModelScope 网速很慢,.env 中的 ASR_PROXY 会同时用于镜像构建和容器运行。Linux Docker 通过 host.docker.internal:host-gateway 访问宿主机代理;默认示例为 http://host.docker.internal:7890。代理程序必须监听宿主机网卡(不能只监听 127.0.0.1),并允许局域网客户端访问。修改后执行 docker compose build --no-cache && docker compose up -d;模型会缓存到 models volume。

网关默认只绑定 127.0.0.1:45679,推荐由 Nginx/Caddy 提供公网 HTTPS。若端口已被占用,在 .env 设置其他高位 ASR_PORT,并让反代指向对应端口。若暂时不用反代、需要直接通过公网 IP 访问,显式设置 ASR_BIND=0.0.0.0,同时用防火墙限制来源。

首次识别会下载模型并缓存于 Docker volume。默认语言是 zh,适合中文为主、夹杂 English/代码术语的口语;识别结果会统一转换为简体中文,并默认保守移除明显的重复填充音(如“呃呃”“嗯嗯”),英文、数字和代码标识符会保留。CPU fallback 默认使用 faster-whisper(small),避免在无 GPU 的中转机上等待 FunASR 的额外模型源;GPU 服务默认使用 FunASR SenseVoiceSmall。CPU 镜像会从 PyTorch CPU wheel 源明确安装 PyTorch;GPU 镜像安装 CUDA 版 PyTorch,不会被 CPU wheel 覆盖。Windows 客户端发送 WAV,因此默认镜像不安装体积很大的 FFmpeg;若要直接上传 MP3/M4A,请自行在 Dockerfile 的 apt 安装行加入 ffmpeg。如需本机也使用 FunASR,可在 .env 设置 ASR_ENGINE=funasr;auto 仍会在 FunASR 初始化失败时切换 faster-whisper。

ASR_INFERENCE_TIMEOUT 控制单次模型初始化/推理的最长秒数,默认 300;模型源不可达时返回 503,而不会阻塞整个 HTTP 服务。

ASR_GPU_URL 填 GPU 服务器的内网地址,例如 http://10.66.0.2:45680。网关会强制绕过 HTTP 代理直接访问该私网地址。GPU 不可达时网关自动在本机 CPU 推理;传 no_fallback=true 会在 GPU 失败时直接返回 502。GPU Compose 默认只绑定 127.0.0.1;部署时在 GPU 机的 .env 将 ASR_GPU_BIND 设置为其局域网或 WireGuard IP,并用主机防火墙限制来源。

2. NVIDIA GPU 服务器

GPU 机安装 NVIDIA 驱动、Docker 和 nvidia-container-toolkit,确认 docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi 成功。将 gpu-server/.env.example 复制为 gpu-server/.env,设置与网关相同的 token:

cd ~/ASR/gpu-server
cp .env.example .env
docker compose up -d --build
curl http://127.0.0.1:8080/v1/health

可通过可信局域网或 WireGuard 直连 GPU 服务,不需要额外反向代理;不要把 GPU 端口映射到公网。在 GPU 机的 .env 设置 ASR_GPU_BIND=<GPU_PRIVATE_IP> 和高位 ASR_GPU_PORT,在网关 .env 设置 ASR_GPU_URL=http://<GPU_PRIVATE_IP>:<GPU_PORT>。多 GPU 机器用从 0 开始的 ASR_GPU_DEVICE_ID 固定一张 GPU,避免 Compose 自动选择到正在运行其他任务的设备。

3. WireGuard 边界

使用 WireGuard 时,在 GPU 机防火墙只允许网关 WireGuard 地址访问 GPU 服务端口;公网只开放 WireGuard UDP 端口(通常 51820)。使用可信局域网直连时,应只绑定内网 IP,并按需限制网关来源。不要把 ASR token 放在 URL 中。生产环境可在网关前加 Caddy/Nginx HTTPS 和限流。

Windows 客户端的 ASR_URL 应设置为实际网关的 HTTPS 地址,例如 https://asr.example.com。使用 Caddy 时可从 deploy/Caddyfile.example 开始配置;使用 Nginx 时将反向代理上游指向 .env 中 ASR_BIND:ASR_PORT 对应的地址。

4. Windows 全局输入

安装 Python 3.11,安装客户端:

cd $env:USERPROFILE\ASR\windows-client
py -3.11 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env

.env 只用于首次启动默认值:设置 ASR_URL=https://asr.example.com,ASR_TOKEN 与服务一致。首次模型下载期间可保持 ASR_REQUEST_TIMEOUT=900,正常使用后可改成 180。随后:

python asr_client.py

启动后会显示设置窗口,可修改服务地址、Token、语言、热词、请求超时和三组全局快捷键。快捷键不能手工输入:点击对应的“录制”,直接按下希望使用的按键或组合键,识别后再点击“保存设置”即可即时生效。录制期间按键会被拦截,不会输入到当前窗口;按 Esc 可取消。支持单独使用 F1 到 F12,也支持 Ctrl、Alt、Shift、Windows 与功能键的组合。三项不能设置成相同的快捷键;新快捷键注册失败时客户端会继续使用原快捷键。

勾选或取消“启用二次润色”会立即保存,并作用于下一次请求;其他字段点击“保存设置”后生效。配置默认保存在 %LOCALAPPDATA%\\ASR\\config.json,.env 只提供首次运行的默认快捷键和其他默认值,不会覆盖已经保存的 GUI 配置。

先点击要输入文字的目标输入框,再按录音快捷键开始录音,再按一次结束;也可以使用窗口中的录音按钮。录音快捷键默认为 Ctrl+Alt+Space。识别结果会通过剪贴板 Ctrl+V 粘贴到仍然获得焦点的输入框。二次润色快捷键默认为 Ctrl+Alt+P,可在不打开窗口的情况下切换二次润色,并同步更新勾选状态和本地配置。正在处理的请求继续使用发出时的设置,修改后的状态从下一次请求生效。关闭窗口会将客户端收入系统托盘。首次使用需在 Windows 隐私设置允许麦克风;若目标程序以管理员身份运行,请也以管理员身份运行客户端(Windows 的全局键盘钩子限制)。

客户端会把每次录音、请求成功、HTTP 错误、网络错误和注入异常写入 %LOCALAPPDATA%\\ASR\\asr-client.log(JSON Lines,不记录 token 和音频)。成功记录中的 route 为 gpu 或 cpu;GPU 不通后回退时会有 fallback_reason。服务端超时会记录 HTTP 503,GPU 强制失败(no_fallback=true)会记录 HTTP 502。

要开机自动运行,在激活虚拟环境并安装依赖后执行:

.\install-startup.ps1

它会在当前用户的 Startup 文件夹创建快捷方式;删除该快捷方式即可停用。

Windows 客户端打包与新功能

在 Windows PowerShell 中执行 windows-client\build.ps1,脚本会创建独立的构建环境并在 windows-client\dist\PrivateASR.exe 生成单文件便携版。目标电脑不需要安装 Python;复制这个 EXE 后直接运行,在设置窗口填写服务地址和令牌即可。执行 install-startup.ps1 可把已构建的 EXE 加入当前用户的开机启动。

录音、二次润色和撤销快捷键均可在设置窗口通过“录制”识别并保存;留空、格式错误或彼此重复时不会保存。默认分别为 Ctrl+Alt+Space、Ctrl+Alt+P 和 Ctrl+Alt+Backspace。撤销快捷键会向当前获得焦点的程序发送一次 Ctrl+Z,因此应在刚完成语音输入且焦点仍在原输入框时使用。

关闭设置窗口只会把客户端收入系统托盘,托盘菜单可以重新打开窗口、切换录音或彻底退出;设置窗口中的“退出程序”也会完整关闭客户端。“启动后直接进入托盘”可在设置中启用。录音开始、录音结束、识别结果、错误与撤销状态会显示在屏幕右下角,并自动消失。

客户端采用单实例运行:重复双击 EXE 时会提示已有客户端在系统托盘中运行并退出,避免同一全局快捷键被多个进程同时响应、重复录音和重复输入。

API

POST /v1/transcribe,multipart 字段 file,请求头 X-ASR-Token,可选 query language=zh|en|auto、hotwords=...、correct=true|false。返回 {"text":"...", "route":"gpu|cpu", "engine":"funasr", "correction":"applied|disabled|failed|unconfigured|skipped"}。

需要自动标点、术语修正或长文本整体润色时,可在网关 .env 设置 ASR_CORRECTOR_URL、ASR_CORRECTOR_MODELS(逗号分隔的模型列表)和可选的 ASR_CORRECTOR_KEY。服务首次请求或到达 ASR_CORRECTOR_PROBE_INTERVAL(默认 300 秒)时并发探测列表,记住最快成功的模型;其他请求只调用该模型,若它失败则立即重新探测,减少长期请求量。全部失败时保留原文。旧配置 ASR_CORRECTOR_MODEL 仍兼容,也支持逗号分隔列表,并在未设置 ASR_CORRECTOR_MODELS 时使用。ASR_CORRECTOR_PROMPT 直接以环境变量为准,可自定义二次润色的 system prompt;留空时才使用代码内置默认提示词。它调用兼容 OpenAI Chat Completions 的服务;ASR_CORRECTOR_TIMEOUT 控制润色调用的最长等待秒数,默认 60。本地模型地址若同时解析到不可用的 IPv6,可设置 ASR_CORRECTOR_FORCE_IPV4=true。留空或请求传 correct=false 时,仍会执行本地填充词清理、空白规范化和繁转简,但不会进行语义改写。ASR_REMOVE_FILLERS=false 可关闭本地填充词清理。

排查

docker compose logs -f asr
curl http://127.0.0.1:45679/v1/health

若模型下载失败,先在可联网环境启动一次并保留 models volume;若 GPU route 失败,检查 curl http://<GPU_PRIVATE_IP>:<GPU_PORT>/v1/health、路由和防火墙,使用 WireGuard 时还需检查 AllowedIPs。网关会自动回落 CPU。

License

This project is licensed under the MIT License.

About

过去程序员希望手能一直放在键盘上,不需要碰鼠标。希望未来手能一直握住麦克风,不碰键盘。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages