2026 实测:VPS 自托管 Whisper 语音转写——用 faster-whisper 在 CPU 小鸡上免去 API 账单

实测用 faster-whisper 加 int8 量化在便宜 CPU VPS 上自托管 Whisper 转写 API,含 Docker、批量脚本、中文识别与限速防封,零 GPU 跑通字幕与会议记录。

延伸阅读

更多相关攻略推荐:【10刀以内VPS系列 01】年付不到70块钱的便宜VPS,到底能用如何给 VPS 厂商做"信用评估":跑路、超售与售后风险排查手册43 亿个地址怎么就不够用了?IPv4 的设计缺陷与人类“续命”奇技【IP 地址 05】IPv6-Only VPS + Cloudfla512MB/1GB 小内存 VPS 优化实战:1 美元机器能跑什么

为什么要在 VPS 上自托管 Whisper

做字幕、会议记录、播客转写或者沉浸式翻译的人,几乎都逃不开一个痛点:云端的 Whisper API 按分钟计费,音频一多账单就蹭蹭涨。更麻烦的是,你的录音、访谈、内部会议音频都要上传到第三方的服务器,隐私和合规上总归不踏实。

好消息是,OpenAI 的 Whisper 模型本身是开源的,而社区里的 faster-whisper(由 SYSTRAN 维护,基于 CTranslate2 推理引擎)把它重写了一遍,在保持几乎相同识别准确率(WER)的前提下,速度提升约 4 倍,内存占用减半,并且原生支持纯 CPU 推理。到 2026 年,这已经是 CPU 上跑语音转写的“事实标准”方案。

换句话说,你不需要买显卡,租一台每月几美元的便宜 VPS 小鸡,就能跑起一个和 OpenAI Whisper API 接口完全兼容的转写服务。音频不离开你的机器,钱也不离开你的口袋。

算一笔账就清楚了:以一段 1 小时的播客为例,云端 Whisper API 按分钟计费大约要几元人民币,一个月做几十期节目,一年下来就是上千元的固定开销。而一台年付十几到二十几美元的特价 VPS,平摊到每天不到一毛钱,转写多少都不额外收费。对于做字幕组、知识付费、会议系统的个人和小团队,自托管几乎是一上线就回本的选择。更重要的是,音频数据全程留在你自己的机器里,不用担心录音外泄、账号被爬,也不用受云端接口的速率限制和突发涨价影响。

硬件与机型选择:便宜 CPU 小鸡够用吗

结论先行:够用,但有取舍。faster-whisper 的 int8 量化把模型权重压到 8 位整数,内存直接砍掉约 75%,CPU 上的推理速度也能提升 2 到 3 倍。下面这份对照表来自社区和我们的实测,给出不同模型在纯 CPU 上的大致表现:

  • tiny(约 75MB):最快,准确率一般,适合实时或草稿。
  • base(约 145MB):快,质量中等,适合对速度敏感的场景。
  • small(约 500MB):速度与准确率最平衡,CPU 小鸡的甜点机型
  • medium(约 1.5GB):更准但明显更慢,1 小时音频在小鸡上可能要十几分钟。
  • large-v3 / large-v3-turbo(约 3GB):最准,但内存和算力开销大,建议至少 4GB 内存起步。

对大多数做中文字幕和会议记录的朋友,small 模型 + int8 量化就是性价比之王。在我们的测试里,一段 5 分钟的中文访谈,在 Intel 系四核 CPU 上实时因子(处理时间除以音频时长)大约在 0.5 左右,也就是 5 分钟音频约 2 到 3 分钟转完,完全能接受。

机型方面,像 RackNerdCloudCone、Bandwagon(搬瓦工)、ColoCrossingVirtono 这些常年做特价机的商家,1GB 到 2GB 内存的年付小鸡只要十几到二十几美元。跑 small + int8 完全没问题;想上 medium 或 large 就把内存加到 4GB 以上。提醒一句:共享 CPU 的 VPS 长时间占满核心容易被商家判定为滥用,后面“限速”一节会专门讲怎么温柔地用。

还有一点容易被忽略:CPU 的指令集会影响 int8 的实际速度。Intel 第 10 代及以后、AMD Ryzen 3000 系列之后的处理器对 AVX2/VNNI 支持更好,跑 int8 明显比老服务器 CPU 快;如果手上是很老的核心,宁可选 small 也不要硬上 large,否则实时因子可能掉到 2 以上,体验会变成“听完一节才出字幕”。另外 ARM 架构的机器(比如部分 Virtono 或甲骨文ARM)也能跑,CTranslate2 对 ARM 有优化,只是镜像要确认是 multi-arch 或自己编一版,别直接拉只支持 amd64 的标签。

方案 A:一行 Docker 跑起 OpenAI 兼容转写 API

最省事的办法是用社区维护的 faster-whisper-server(项目已更名为 speaches)官方镜像。它直接提供 /v1/audio/transcriptions 接口,和 OpenAI 的 Whisper API 完全兼容,你现有的调用代码只要改个 base_url 就能切换。

先拉起服务(CPU 版):

docker run -d \
  --name whisper \
  -p 9000:8000 \
  -e WHISPER__MODEL=Systran/faster-whisper-small \
  -e WHISPER__COMPUTE_TYPE=int8 \
  -v $(pwd)/models:/root/.cache/huggingface \
  fedirz/faster-whisper-server:latest-cpu

第一次启动会去 Hugging Face 下载模型权重(small 约 500MB),耐心等一会儿。国内用户如果下载慢,可以先设置镜像源再启动:

export HF_ENDPOINT=https://hf-mirror.com
docker restart whisper

健康检查:

curl http://localhost:9000/health
# 返回 {"status":"ok"} 就说明活了

转写一段音频,直接复用 OpenAI 的调用方式:

curl http://localhost:9000/v1/audio/transcriptions \
  -F "file=@meeting.mp3" \
  -F "model=whisper-1" \
  -F "language=zh"

用 Python 的 OpenAI SDK 也一样,只把 base_url 指到你的 VPS:

from openai import OpenAI

client = OpenAI(api_key="cant-be-empty", base_url="http://你的VPS_IP:9000/v1/")
with open("meeting.mp3", "rb") as f:
    result = client.audio.transcriptions.create(model="whisper-1", file=f)
print(result.text)

注意:接口里写 whisper-1 只是占位,服务端会按你环境变量里配置的模型来跑;也可以在请求里用 model=Systran/faster-whisper-small 这类写法动态指定。中文一定要带 language=zh,能显著减少误识别和提速。

方案 B:直接用 faster-whisper 写批量转写脚本

如果你不想起常驻服务,只想把一堆录音批量转成文字或字幕,直接写个 Python 脚本更轻量。先装包:

pip install faster-whisper
# 提示:CPU 模式完全不依赖 PyTorch,别装 torch,避免版本冲突

一段最简单的批量转写:

from faster_whisper import WhisperModel
import glob, os

model = WhisperModel("small", device="cpu", compute_type="int8", cpu_threads=4)

os.makedirs("out", exist_ok=True)
for path in glob.glob("audio/*.mp3"):
    segments, info = model.transcribe(path, language="zh", beam_size=5)
    with open("out/" + os.path.basename(path) + ".txt", "w") as f:
        for seg in segments:
            line = "[%.2fs -> %.2fs] %s" % (seg.start, seg.end, seg.text)
            print(line)
            f.write(line + "\n")

想要 SRT 字幕?把每段的时间戳按字幕格式写出来即可,faster-whisper 默认就带 startend。需要逐字(word)级时间戳,调用时加 word_timestamps=True。建议把音频先统一转成 16kHz 单声道 WAV,能减少模型预处理时间。

中文识别实测与避坑

在普通话场景,faster-whisper 的 small 和 medium 表现相当稳,能正确识别“微信”“支付宝”“哔哩哔哩”这类专有名词。但有几个坑你必须知道:

  • 一定要显式指定 language=zh。自动检测偶尔会把带口音或中英混说的音频判错,强制中文又快又准。
  • 粤语和方言是短板。实测里 faster-whisper 经常把粤语误判成普通话书面语,丢掉“呢/唔到/嘅”这些特征字。如果你的主力是粤语或方言,建议改用 FunASR 的 SenseVoice,它在中文(含粤语)的字符错误率上比 Whisper 系低约 2.7 倍。英语和通用 99 语种的翻译任务上,faster-whisper 依然更强。
  • 安静环境比降噪软件更重要。内置的 Silero VAD 会过滤静音,但背景音乐太响会拖累准确率。转写前用 ffmpeg 把人声稍微提一点常有意想不到的提升。
  • 长音频拆段。超过 1 小时的录音建议按静音切片再并发处理,既省内存又方便定位。

限速与队列:保护小鸡不被打爆

“防被封”有两层意思。一层是自我保护:便宜 VPS 内存小、CPU 弱,如果同时丢进去十几个大文件,模型权重加上并发解码会直接把内存吃满,容器 OOM 被杀,转写全废。另一层是避免被商家判定滥用RackNerdCloudCone、Bandwagon、ColoCrossingVirtono 这类特价机大多是共享 CPU,长时间 100% 占满可能被限速甚至封机。

做法是用信号量(Semaphore)限制并发数,并给每个任务加冷却。下面这个本地 API 的限速封装很实用:

import asyncio, aiohttp

sem = asyncio.Semaphore(2)  # 同时最多 2 个转写任务

async def transcribe_one(path, url):
    async with sem:
        data = aiohttp.FormData()
        data.add_field("file", open(path, "rb"))
        data.add_field("language", "zh")
        async with aiohttp.ClientSession() as s:
            async with s.post(url + "/v1/audio/transcriptions", data=data) as r:
                return await r.text()

async def main(files):
    tasks = [transcribe_one(p, "http://localhost:9000") for p in files]
    return await asyncio.gather(*tasks)

# asyncio.run(main(["a.mp3", "b.mp3", "c.mp3"]))

再加上这几条经验:

  • 并发数控制在 1 到 2,medium/large 模型直接设为 1。
  • nicecpulimit 把转写进程优先级压低,别影响同机其他服务。
  • 批量任务放凌晨跑,避开高峰,对共享机型更友好。
  • 对外暴露 API 时务必加反向代理 + 认证,别把 9000 端口裸奔到公网。

进阶:字幕、会议记录与沉浸式翻译

跑通基础转写后,玩法就多了:

  • 视频字幕:用 ffmpeg 抽出音轨,转写后生成 SRT/VTT,再烧录回视频,一条龙全本地完成。
  • 会议记录:录音实时或会后转写,配合大模型做摘要和待办提取,数据不出内网。
  • 沉浸式翻译:把英文播客转成文字后接翻译,自己做双语字幕。
  • Open WebUI / 各类笔记工具:把 Whisper 的 base_url 指到你的 VPS,直接获得语音输入能力。

哪里买机器最划算?做这种轻量常驻服务,年付特价机最合适。RackNerdVirtono 的 1 到 2GB 内存机型常年有十几美元的年付CloudCone、Bandwagon、ColoCrossing 也经常放限时特价,挑离你近、网络稳的机房即可。音频类任务对带宽要求不高,普通线路完全够用。