为什么要在本地做语音转文字
想把会议录音、课程音频、播客变成文字稿?本地语音转文字正在成为开发者的新刚需。把音频上传到云端转写 API,虽然省事,却要付出费用、等待排队,还要把敏感内容交给第三方。借助 OpenAI 开源的 Whisper 模型与社区优化的 faster-whisper 推理引擎,你完全可以在自己的服务器或笔记本上完成高质量转录,数据不出本机,按量零成本。本文从安装到批量字幕,再到封装成 API 服务,手把手带你跑通一整套离线转录流水线。
Whisper 与 faster-whisper 是什么关系
Whisper 是 OpenAI 在 2022 年开源的自动语音识别(ASR)模型,支持 99 种语言,对中文、英语等多语种混合场景表现稳健。官方原始实现基于 PyTorch,推理速度一般。faster-whisper 则用 CTranslate2 推理引擎重构,采用 INT8 量化与算子融合,在保持精度的同时把速度提升 4 倍以上、显存占用大幅下降。简单说:模型还是那个 Whisper,但”跑”的方式更高效。这也是它成为本地语音转文字首选方案的原因。
环境准备与安装
faster-whisper 已发布到 PyPI,一条命令即可安装。若有 NVIDIA 显卡,会自动使用 GPU 加速;纯 CPU 也能跑,只是稍慢。建议 Python 3.10+。
# 新建虚拟环境(可选但推荐)
python -m venv venv && source venv/bin/activate
# 安装 faster-whisper
pip install faster-whisper
# 验证安装
python -c "import faster_whisper; print(faster_whisper.__version__)"
首次运行会自动从 Hugging Face 下载所选模型权重(约几十 MB 到数 GB,取决于模型尺寸)。服务器若能直连 HF 则无需额外配置;内网环境可设置 HF_ENDPOINT 镜像源加速下载。
实战一:单文件转录
最简单的用法只需几行代码。指定模型尺寸、运行设备与量化类型后调用 transcribe,即可拿到分段结果与语言检测结果。
from faster_whisper import WhisperModel
# device: "cpu" 或 "cuda";compute_type: "int8"/"int8_float16"/"float16"
model = WhisperModel("base", device="cpu", compute_type="int8")
segments, info = model.transcribe("meeting.mp3", beam_size=5, language="zh")
print(f"检测语言: {info.language},置信度: {info.language_probability:.2f}")
for seg in segments:
print(f"[{seg.start:.1f}s -> {seg.end:.1f}s] {seg.text}")
language=”zh” 可强制中文识别,避免模型在短音频上误判语种;对已知语种的批量任务,显式指定能稳定提速。若想自动检测,去掉该参数即可。
实战二:批量转录并生成字幕文件
真实场景往往是一堆录音要处理。下面脚本遍历目录,把每个音频转成 SRT 字幕,方便直接压进视频或导入剪辑软件。
import os
from faster_whisper import WhisperModel
model = WhisperModel("small", device="cpu", compute_type="int8")
def fmt_ts(t: float) -> str:
h, m = int(t // 3600), int((t % 3600) // 60)
s, ms = int(t % 60), int((t % 1) * 1000)
return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"
def write_srt(segments, path: str):
with open(path, "w", encoding="utf-8") as f:
for i, seg in enumerate(segments, 1):
f.write(f"{i}\n{fmt_ts(seg.start)} --> {fmt_ts(seg.end)}\n{seg.text.strip()}\n\n")
os.makedirs("subs", exist_ok=True)
for name in os.listdir("audios"):
if name.lower().endswith((".mp3", ".wav", ".m4a", ".flac")):
segs, _ = model.transcribe(f"audios/{name}", beam_size=5, language="zh")
write_srt(segs, f"subs/{name}.srt")
print(f"已完成: {name}")
small 模型在中文场景的准确率已相当可用,配合 beam_size=5 的集束搜索,能显著减少同音字错误。若还要 VTT 格式,只需把时间轴分隔符从逗号改成点号即可。
实战三:封装成 FastAPI 转录服务
把模型常驻内存,对外提供 HTTP 接口,其他系统就能随时调用本地语音转文字能力,而不必每次重启进程。下面用 FastAPI 实现文件上传即转录。
from fastapi import FastAPI, File, UploadFile
from faster_whisper import WhisperModel
app = FastAPI()
# 进程启动时加载一次,避免重复开销
model = WhisperModel("base", device="cpu", compute_type="int8")
@app.post("/transcribe")
async def transcribe(audio: UploadFile = File(...)):
tmp = f"/tmp/{audio.filename}"
with open(tmp, "wb") as f:
f.write(await audio.read())
segments, info = model.transcribe(tmp, beam_size=5)
text = "".join(s.text for s in segments)
return {"language": info.language, "text": text}
# 启动:uvicorn app:app --host 0.0.0.0 --port 8000
生产环境记得加鉴权中间件与并发限制——大模型推理是 CPU/GPU 密集操作,裸奔接口容易被打满。也可以把模型换到 GPU 实例,并把 compute_type 设为 float16 进一步提升吞吐。
模型怎么选:速度、精度与资源的权衡
Whisper 提供从 tiny 到 large 五档尺寸。本地部署要在精度与资源间做取舍,下面这张表给你直观参考(数值为近似量级,实际随硬件浮动)。
| 模型 | 参数量(近似) | 相对速度 | 显存占用 | 适用场景 |
|---|---|---|---|---|
| tiny | 39M | 最快 | <1GB | 实时字幕、边缘设备 |
| base | 74M | 快 | ~1GB | 草稿级快速转录 |
| small | 244M | 中 | ~2GB | 通用中文转录(推荐起步) |
| medium | 769M | 慢 | ~5GB | 高精度长音频 |
| large | 1550M | 最慢 | ~10GB | 追求最佳准确率 |
经验法则:先用 small 跑通流程,若同音字、专有名词错误多,再升到 medium;边缘设备或实时场景则降到 base/tiny。量化选 int8 几乎不损精度却能省一半显存。
本地方案与云端 API 怎么选
云端转写 API 胜在开箱即用、无需运维,适合偶发、低敏的小批量需求;而当你每天要处理大量录音、或内容涉及商业机密、个人隐私时,本地方案的边际成本趋近于零、且数据完全自控。它的思路与本地大模型量化部署一脉相承——把推理能力搬回自有硬件。若后续要做更高并发的语音或文本推理,也可以参考vLLM / SGLang / Ollama 推理引擎的部署思路横向扩展。
几个常见踩坑
中文识别串字:短音频务必指定 language=”zh”,否则容易误判为日、韩语。长音频卡顿:超过 1 小时的录音建议先按静音切分再逐段转录,降低内存峰值。首次下载慢:提前触发一次权重下载,或在离线环境手动放置模型目录。CPU 太慢:开启 int8 量化、调小 beam_size,或迁移到带 GPU 的实例。更多多模态能力(图像、音频、视频理解)也可看多模态大模型应用实战。
工程化:多文件并发与资源控制
当录音数量增多,串行转录会拖慢整体产出。faster-whisper 的推理核心运行在 C++ 底层,会释放 GIL,因此用线程池并发处理多个文件能真实吃满多核 CPU,而不是像普通 Python 那样空转。下面示例用 ThreadPoolExecutor 把目录里的音频并行转写。
from concurrent.futures import ThreadPoolExecutor
from faster_whisper import WhisperModel
model = WhisperModel("small", device="cpu", compute_type="int8", cpu_threads=4)
def job(name):
segs, _ = model.transcribe(f"audios/{name}", beam_size=5, language="zh")
return name, "".join(s.text for s in segs)
files = [n for n in os.listdir("audios") if n.endswith((".mp3",".wav",".m4a"))]
with ThreadPoolExecutor(max_workers=3) as ex:
for name, text in ex.map(job, files):
print(f"{name}: {len(text)} 字")
cpu_threads 控制单模型使用的线程数,max_workers 控制并发文件数,两者乘积不要超过物理核心数,否则反而会因争抢而变慢。GPU 场景下并发收益有限,建议改用进程级队列或批处理。
后处理:让专有名词与标点更准
通用模型对行业术语、人名、产品名容易写错。实用的做法是转录后做一层轻量后处理:用自定义词典做精确替换,或把高频专有名词喂回二次校正。下面是一段不依赖外部服务的替换示例。
GLOSSARY = {"阿里云": "阿里云", "kubernetes": "Kubernetes", " whisper": " Whisper"}
def post_fix(text: str) -> str:
for wrong, right in GLOSSARY.items():
text = text.replace(wrong, right)
return text
# 在写出字幕或返回接口前调用
clean = post_fix(raw_text)
若对准确率要求极高,可在 transcribe 后接一个更小的纠错模型,或用规则把数字、单位统一格式化。这一步虽小,却是本地语音转文字真正达到”可用”与”好用”的分水岭。
小结
本地语音转文字并不神秘:装好 faster-whisper,选对模型尺寸,写几十行代码就能搭起离线转录流水线,既能批量出字幕,也能封装成内部 API。它把 Whisper 的开放能力真正落到了可控、低成本的工程实践上。下一步,你可以把它接入会议录音自动纪要、播客文稿生成,或作为 RAG 系统的语音入口——语音这座金矿,现在就在你自己的机器上。




