本文由 Claude Code (DeepSeek v4) 代写,suyiiyii 审阅。写作风格参照 tw93。
前言
年初在 pc-5950x 上搭了个 Whisper HTTP 服务,本来以为半天能搞定的事情,结果一路折腾了六个月。中间换了 7 个模型,写过异步队列,修过 Windows GPU 驱动 bug,拼过 speaker diarization,最后搞出了一套多模型 pipeline + benchmark 体系。
我又把当时的运维记录、benchmark 数据和现在的线上服务一起过了一遍,把整个过程系统化梳理了一下。以下不是什么最佳实践,只是半年踩坑下来的一些记录和判断。
六个阶段的演进
整个过程可以分成六个阶段,每个阶段其实都在解决上一阶段暴露出来的问题。
| 阶段 | 时间 | 核心问题 | 关键决策 |
|---|---|---|---|
| 1. 单模型起服务 | 2 月底 | Whisper 中文不够好 | 加部署 Qwen3-ASR-1.7B |
| 2. 稳定性 | 4 月 | 服务频繁挂掉 | 修 WDDM TDR + 监控自动重启 |
| 3. 转写质量 | 5 月初 | 长音频只出 20% 文字 | 异步队列 + 缩小分块 |
| 4. 模型选型 | 5 月中 | 速度和质量的 tradeoff | 6 模型对比,选 Fun-ASR-Nano |
| 5. 后处理实验 | 5 月底 | 专有名词仍有差距 | LLM 后处理 + speaker 尝试 |
| 6. 云 + 本地混合 | 5 月底至今 | 长音频时间戳 + speaker 不准 | StepAudio 2.5 主线 + CAM++/pyannote ensemble |
说白了,每一步都不是主动规划的,而是被问题推着走的。
模型选型的几个关键判断
折腾了 7 个模型之后,发现 ASR 这边其实就两类架构,各有各的问题。
两类架构的本质区别
| 纯声学模型 | LLM 骨架模型 | |
|---|---|---|
| 代表 | SenseVoice-Small (234M)、Paraformer-large (220M) | Qwen3-ASR (1.7B)、Fun-ASR-Nano (800M) |
| 推理方式 | 非自回归,一次前向出全文 | 自回归,逐 token 生成 |
| 速度 | RTF 0.01x,14 分钟音频 8 秒搞定 | RTF 0.15-1.0x,14 分钟音频 1.5-14 分钟 |
| 专有名词 | chatgpt.com → chGBT 点 com |
chatgpt.com → ChatGPT.com |
| 长音频表现 | 稳定,不退化 | 大多数会退化或崩溃 |
核心矛盾:纯声学模型快但专有名词很差,LLM 骨架模型专有名词好但慢且长音频不稳定。目前没有一个"全都要"的方案。
长音频退化是选型的决定性因素
实测数据(11.7 分钟中文音频):
| 模型 | 输出字数 | 字/秒 | 退化情况 |
|---|---|---|---|
| —— | :—: | :—: | —— |
| Fun-ASR-Nano | 2,477 | 3.5 | 无退化 |
| Qwen3-ASR-1.7B | 841 | 1.2(后半段) | 退化 3x |
| GLM-ASR-Nano | 85 | — | 完全崩溃 |
Qwen3-ASR 在短音频上是我用过最好的本地模型,但长音频后半段基本上在划水。Fun-ASR-Nano 是唯一一个长音频不退化、专有名词也还行的选择。不过它的 VAD 模块有 bug(funasr 1.3.1 的 KeyError: 0),得手动修一下源码。
最终选择
| 场景 | 方案 | 理由 |
|---|---|---|
| 生产主线 | StepAudio 2.5(云端) | 0.15 元/小时,质量和速度都最好 |
| 本地 backup | Fun-ASR-Nano(8002) | 离线可用,质量接近商用 |
| 实验 | Qwen3-ASR(8003) | 专有名词好,短音频可用 |
| Speaker | CAM++ + pyannote ensemble | gate 通过率 5/5 |
Windows 上跑 GPU 服务的几个坑
这部分其实是耗时最长的。Windows 当服务器用,有三个问题绕不开。
WDDM TDR
Windows 的 GPU 保护机制:GPU 操作超过 2 秒没响应 → 直接杀进程。日志来不及写,就是 0 字节。
修法:
|
|
从 2 秒改到 10 秒。不是根治,但触发频率大幅降低。
进程持久化
Windows 计划任务 + PowerShell 脚本的组合能用,但问题很多。后台进程的 GPU 资源访问权限受限,进程优先级也低。后来换到 WSL2 + systemd 管理,体验好了不少。
消费级 GPU 的限制
RTX 2060 SUPER 不支持持久化模式,每次进程重启都要重新初始化 GPU 驱动。这个没办法解决,是硬件限制。
Benchmark 体系建设
没有 benchmark 之前,模型选型基本靠感觉。后来设计了 5 段覆盖不同场景的测试集:
| 样本 | 时长 | 内容类型 | 难度 |
|---|---|---|---|
| —— | —— | —— | :—: |
| 差评君 | 11.3min | 单人讲解,科技类 | 低 |
| 罗福莉访谈 | 30min | 双人对话,AI 技术 | 中 |
| 姚顺宇访谈 | 60min | 双人对话,AI 训练 | 中 |
| 团山北路 | 27.9min | 三人自然对话 | 高 |
| 暂停实验室 | 16.7min | 单人播客,心理类 | 低 |
以豆包 ASR 输出作为近似基准,用文本相似度做客观对比。当前 8006 服务(StepAudio 2.5 + speaker ensemble)的 benchmark 结果:
| 样本 | 文本相似度 | 速度 | Speaker |
|---|---|---|---|
| —— | :—: | :—: | —— |
| 差评君 | 0.9696 | 9.10x | stable / 1 人 |
| 罗福莉 | 0.9260 | 7.32x | stable / 2 人 |
| 姚顺宇 | 0.9500 | 7.47x | stable / 2 人 |
| 团山北路 | 0.8999 | 9.99x | stable / 3 人 |
| 暂停实验室 | 0.9856 | 8.36x | stable / 1 人 |
团山北路分数最低,但不是模型的问题——这段是三人自然对话,豆包偏书面整理,StepAudio 偏口语保留,风格不同导致相似度低。speaker 方面,豆包给了 8 个人,但实际只有 3 人在说话,这也印证了 speaker 不能直接用 ASR 自带的结果。
当前架构
|
|
设计原则按优先级排:
- 语义真实性 — 不做 LLM 改写、不做 ITN、保留语气词和口语表达
- 经济性 — 主线 0.15 元/小时,低于 0.25 元/小时的心理预算
- 说话人识别 — 默认关闭,需要时开启,gate 不通过就不输出
- 效率 — 纯 ASR 7-10x,开 speaker 仍高于 2x
后续
- speaker memory 现在只是匿名 cluster label,需要升级到真实声纹 embedding
- 团山北路的 speaker 时间轴需要人工听音频复核
- 长音频边界 chunk 的合并策略还可以优化
划重点
- ASR 模型分纯声学和 LLM 骨架两类,前者快但专有名词差,后者相反,目前没有全都要的方案
- 长音频退化是选型的决定性因素——短音频跑得好的模型,不一定能撑住 30 分钟以上
- Windows 跑 GPU 服务,WDDM TDR 是第一个要解决的问题
- Fun-ASR-Nano 是目前最好的本地方案,StepAudio 2.5 是性价比最高的云端方案
- 没有 benchmark 之前,模型选型基本靠感觉;有了 benchmark,讨论才有共同基础
- Speaker diarization 要加 gate——不稳定就不输出,比输出错误结果好
- 用 Notion 写文章 + Elog 同步 + CF Pages 自动部署,改个 status 就能触发上线
- 本地 ASR 能做到商用 API 90-98% 的文本相似度,专有名词差距在缩小
- 0.15 元/小时的云端 ASR + 本地 backup 的组合,目前用起来最舒服
- 这套东西从"搭个 HTTP 服务"膨胀到多模型 pipeline,本质是被问题推着走的,不是提前设计的
参考:FunASR 团队、StepFun、豆包 ASR、pyannote、CAM++。如果你有更好的 ASR 实践经验,也欢迎一起交流。