把会议录音、播客、访谈整理成文字,是件很费时间的事。在线转写服务按分钟收费,一小时录音几块到几十块不等;涉及内部会议的音频,上传到别人服务器上也不放心;要处理几十个文件的时候,还得一个个传。
自建一套 Whisper 服务,这些都不是问题 —— 批量丢文件进去、结果自己拿、不花钱、音频不出服务器。
这篇讲清楚三件事:哪个实现该用、模型怎么选、怎么部署成一个能用的服务。
"Whisper" 这个名字下其实有三套不同的东西:
| openai-whisper | faster-whisper | whisper.cpp | |
|---|---|---|---|
| 语言 | Python(官方原版) | Python + CTranslate2 | C++ |
| 速度 | 基准 | 约 4 倍 | 最快(RTF 0.136) |
| 精度 | 高 | 高(WER 3.12%) | 量化后明显下降(WER 26.92%) |
| 内存 | 高 | 低 | 最低 |
| 时间戳粒度 | 句级 | 词级 | 句级 |
| 说话人分离 | ❌ | ✅(配 WhisperX) | ❌ |
| 适合 | 不推荐 | 有 GPU 的服务器 | CPU / ARM / Mac |
结论很直接:
- 服务器上有 NVIDIA 显卡 → faster-whisper,速度和精度的最佳平衡
- 只有 CPU → whisper.cpp,能跑但精度有损失;或者用 faster-whisper 的小模型硬扛
- 官方的 openai-whisper 不用考虑,它被 faster-whisper 全面超越了
下面讲的部署方案基于 faster-whisper,这是目前的主流选择。
Whisper 有多个尺寸的模型,不是越大越好 —— 得看你的硬件和场景。
| 模型 | 下载体积 | 大概需要显存 | 速度 | 中文效果 |
|---|---|---|---|---|
| tiny | ~75MB | <1GB | 极快 | 差,不建议 |
| base | ~150MB | ~1GB | 很快 | 一般,能听出大意 |
| small | ~500MB | ~2GB | 快 | 日常够用,性价比最高 |
| medium | ~1.5GB | ~5GB | 中 | 好 |
| large-v3 | ~3GB | ~6GB | 慢 | 最好 |
给几个实际建议:
- 中文内容用 medium 起步。 small 对中文的标点和专有名词处理明显不如 medium
- 英文内容 small 就够,甚至 base 也能接受
- 字幕场景建议 large-v3,因为错字会直接暴露给观众
- 批量处理大量文件:先用 small 快速过一遍,只对不满意的部分用大模型重跑
模型下载后缓存在本地,切换模型不会重新下载。但每个模型都会占硬盘,全下下来大概 6GB。
Whisper 不是必须有 GPU。 CPU 也能跑,只是慢:
- CPU(4 核现代处理器)+ small 模型:大约 1-3 倍实时,即 1 小时音频要跑 20-60 分钟
- GPU(GTX 1660 级别)+ small 模型:大约 10-20 倍实时,1 小时音频 3-6 分钟
GPU 大概快 5-10 倍,如果是要经常处理长音频,这个差距很关键。
| 场景 | 建议配置 |
|---|---|
| 偶尔转写、短音频 | 2 核 4G,CPU + small |
| 经常用、长音频、批量 | GPU 机器,6GB+ 显存 + large-v3 |
| 实时转写(会议直播) | GPU,至少 8GB 显存 |
注意内存。 就算用 GPU,音频解码和预处理也在内存里跑。CPU 版跑 small 模型建议 4GB 内存起步,并发处理要给到 8GB。模型选择参考 GPU VPS 推荐里按用途分的建议。
硬盘按模型体积算。 只留 small + medium 两个模型,5GB 磁盘绰绰有余;想把所有模型都备着,留 15GB。
用 Speaches(这个项目以前叫 faster-whisper-server),它把 faster-whisper 包装成了一个 OpenAI 兼容的 HTTP 服务。
好处是接口和 OpenAI 的语音 API 一模一样 —— 任何支持 OpenAI 语音转写的软件,改一下 base URL 就能直接用你的服务,包括 Open WebUI、LibreChat 这些。
docker-compose.yml(CPU 版):
services:
speaches:
image: ghcr.io/speaches-ai/speaches:latest-cpu
container_name: speaches
restart: unless-stopped
ports:
- "127.0.0.1:8969:8000"
environment:
- API_KEY=换成一串长随机字符
- PRELOAD_MODELS=["Systran/faster-whisper-small"]
- WHISPER__TTL=-1
volumes:
- ./hf-cache:/home/ubuntu/.cache/huggingface/hub
有 NVIDIA 显卡的话,换镜像并加上 GPU 声明:
image: ghcr.io/speaches-ai/speaches:latest-cuda
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
显卡驱动和容器工具包的安装步骤,ComfyUI 那篇里有完整流程,两者是一样的。
几个关键点:
API_KEY 一定要设。 这个变量为空时,接口是完全公开的 —— 任何人发现你的地址都能拿它跑转写,烧的是你的 CPU/GPU。设好之后所有 /v1 路由都需要带 Authorization: Bearer 你的密钥。
PRELOAD_MODELS 让你指定的模型在容器启动时就加载好。 不设的话模型是"按需加载"(第一次请求时才下载并加载),第一次调用会等很久。
WHISPER__TTL=-1 让模型常驻内存,不会被闲置卸载。代价是内存一直被占着。机器内存紧张的话就把这行去掉,让它自动卸载。
模型缓存必须挂出来。 否则每次重建容器都要重新下载几百 MB 到几 GB 的模型。
启动:
docker compose up -d
docker compose logs -f
第一次启动要有耐心 —— 镜像要下载,模型也要下载。看到 Application startup complete 就好了。
最快验证方式是 curl:
curl -s http://127.0.0.1:8969/v1/audio/transcriptions \
-H "Authorization: Bearer 你的API_KEY" \
-F "[email protected]" \
-F "model=Systran/faster-whisper-small" \
-F "language=zh"
返回的是 JSON。指定 language=zh 能明显提升中文准确率 —— 不指定的话模型要先猜语言,猜错了整段都废了。
要批量处理,写个脚本:
import os, requests
API = "http://127.0.0.1:8969/v1/audio/transcriptions"
KEY = "你的API_KEY"
HEADERS = {"Authorization": f"Bearer {KEY}"}
for name in os.listdir("audios"):
if not name.endswith((".mp3", ".wav", ".m4a", ".flac")):
continue
with open(f"audios/{name}", "rb") as f:
r = requests.post(
API,
headers=HEADERS,
files={"file": f},
data={
"model": "Systran/faster-whisper-small",
"language": "zh",
"response_format": "srt",
},
timeout=3600,
)
out = os.path.splitext(name)[0] + ".srt"
with open(out, "w", encoding="utf-8") as f:
f.write(r.text)
print("完成:", out)
response_format 可以选 json、text、srt、vtt、verbose_json。做字幕直接用 srt,不用自己拼时间轴。
超时别忘了设。 长音频的转写请求可能跑十几分钟,HTTP 客户端默认超时会直接掐断。
给视频配字幕的话,先抽出音轨再转写,比直接传视频快得多:
ffmpeg -i video.mp4 -vn -ac 1 -ar 16000 -c:a libmp3lame -b:a 64k audio.mp3
这条命令做了三件事:丢掉视频流(-vn)、转成单声道(-ac 1)、重采样到 16kHz(-ar 16000)。
为什么要 16kHz 单声道? 因为 Whisper 内部就是按 16kHz 单声道处理的。提前转好能大幅减小文件体积、加快上传,而且不会损失任何识别精度 —— 反正它也要降采样。一个 1GB 的视频,音轨抽出来可能只有 20MB。
生成 SRT 之后,用播放器插件或者 ffmpeg 把字幕烧进视频:
ffmpeg -i video.mp4 -vf subtitles=audio.srt -c:a copy output.mp4
如果你已经按站内这篇搭过 Open WebUI,可以把 Whisper 接上去,实现"按住说话"的语音输入。
在 Open WebUI 的环境变量里加:
AUDIO_STT_ENGINE=openai
AUDIO_STT_OPENAI_API_BASE_URL=http://speaches:8000/v1
AUDIO_STT_OPENAI_API_KEY=你的API_KEY
AUDIO_STT_MODEL=Systran/faster-whisper-small
注意 API_BASE_URL 填的是容器内网地址(两个容器在同一 Docker 网络时用服务名),不是宿主机的 127.0.0.1:8969。
同样的思路可以接到任何支持自定义 OpenAI 端点的应用上。
先说结论:Whisper 的中文识别水平已经相当可用,但别期待零错误。
几种常见问题和对策:
繁简混杂。 Whisper 有时会输出繁体字,尤其是训练数据里繁体占比较高的内容。用 OpenCC 转一道就能统一:
pip install opencc-python-reimplemented
# 代码里用 OpenCC('t2s').convert(text) 转简体
专有名词错得离谱。 人名、产品名、行业术语,模型没见过就会按发音硬猜。可以用 prompt 参数喂一份词汇表:
-F "prompt=本次会议讨论:Kubernetes、PostgreSQL、张伟、李娜"
这会作为上下文引导模型,对固定领域的批量转写很有效。
标点符号不合格。 中文的引号、书名号经常被输出成英文标点或者干脆丢失。这个是模型层面的问题,只能靠后处理脚本补。
背景音乐和人声重叠 会让识别质量断崖式下跌。会议录音里多人抢话的部分,正确率会明显下降 —— 需要区分说话人的话,得上 WhisperX(基于 faster-whisper,加了说话人分离)。
写了这么多,也得说清楚什么时候自建是多余的。
偶尔转写几个文件 → 用云 API 更划算。OpenAI 的语音转写按分钟计费,一小时音频大约几毛到一块多美元,一年转不了几十小时的话,租服务器的钱够你用很久。而且不用维护、不用等模型下载。
只在本地桌面用 → 装个客户端就行。Mac 上有 MacWhisper,跨平台的有 Buzz,都是把模型跑在自己电脑上,拖进去就出字幕,没有任何部署成本。只有当你要在手机、平板、或者别的设备上访问,或者要批量自动化处理时,服务器才有意义。
要做直播实时字幕 → 自建的实时链路比专用服务麻烦得多。Speaches 提供了 WebSocket 实时转写端点,但客户端得自己写;而且实时场景对延迟敏感,GPU 占用是持续的。
自建真正划算的场景是这三个:批量处理(几十上百个文件)、自动化流水线(接进现有工作流)、数据敏感(音频不能出内网)。
跑起来之后,如果嫌慢,有几个地方可以优化。
用 VAD 切掉静音。 长音频里静音和背景噪声经常占到两到三成,这些片段模型也要老老实实跑一遍。faster-whisper 内置了 VAD 过滤,也可以通过参数开启。开启后不只是快,还能减少"静音段生成幻觉文字"的问题 —— 那是最让人头疼的输出污染。
调整计算精度。 faster-whisper 支持几种 compute_type:
| 设置 | 用在哪 | 效果 |
|---|---|---|
float16 | GPU | 最快,精度几乎无损 |
int8_float16 | GPU 显存紧张 | 省显存,精度略降 |
int8 | CPU | 明显省内存,CPU 上速度也更好 |
显存不够装 large-v3 的时候,int8_float16 能让你在 4GB 显存上跑起来。
长音频先切分再并发。 一个 3 小时的录音跑一次很慢,用 ffmpeg 按静音点切成 10 分钟一段,然后并发提交几个请求,总耗时会短很多。注意并发数别超过你的 CPU 核数或者 GPU 能承受的量。
别用超大模型做粗筛。 一百个文件要处理,先用 small 全部跑一遍,挑出质量明显不行的几个再用 large-v3 重跑。这比全部用大模型快一个数量级。
第一次请求特别慢:模型在下载。看容器日志的进度,或者提前用 PRELOAD_MODELS 加载。
报 404 model not found:模型名字写错了。用 curl http://127.0.0.1:8969/v1/models -H "Authorization: Bearer 密钥" 看有哪些可用,或者用 POST /v1/models/{模型名} 动态添加。
GPU 没被用上:容器里跑 nvidia-smi 确认能看到显卡。看不到就是容器工具包没配好,参考 ComfyUI 那篇的验证步骤。
转写结果全是重复词:典型的模型幻觉,常见于静音段或者纯音乐片段。升级到更大的模型能缓解,或者先用 ffmpeg 做静音检测切掉空段。
内存被吃满:WHISPER__TTL=-1 会让模型常驻,大模型 + 小内存机器很容易 OOM。去掉这行,或者换小模型。
想限制并发:同时来几个请求会把 CPU/GPU 打满。放在反代后面用限流控制,别让接口无限并发。
自建 Whisper 最大的价值不是省钱,而是能批量、能自动化、音频不出自己的服务器。一旦跑起来,你可以把它接进任何工作流 —— 播客自动出文字稿、会议录音自动归档、视频批量配字幕。
选型上记住两条:有显卡就用 faster-whisper,没显卡就用 whisper.cpp;中文内容别用小于 small 的模型。
延伸阅读:
