本地语音转文字实战:faster-whisper 离线转录

为什么要在本地做语音转文字

想把会议录音、课程音频、播客变成文字稿?本地语音转文字正在成为开发者的新刚需。把音频上传到云端转写 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 五档尺寸。本地部署要在精度与资源间做取舍,下面这张表给你直观参考(数值为近似量级,实际随硬件浮动)。

模型参数量(近似)相对速度显存占用适用场景
tiny39M最快<1GB实时字幕、边缘设备
base74M快~1GB草稿级快速转录
small244M中~2GB通用中文转录(推荐起步)
medium769M慢~5GB高精度长音频
large1550M最慢~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 系统的语音入口——语音这座金矿,现在就在你自己的机器上。

上一篇 OpenTofu 实战:Terraform 开源分支的 IaC 新选择
下一篇 Kafka 再平衡风暴排查:消费组卡顿的根因与解决
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]