ASR 半年复盘:从 Whisper 到多模型 Pipeline 的工程实践

本文由 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.comchGBT 点 com chatgpt.comChatGPT.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 字节。

修法:

1
reg add 'HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers' /v TdrDelay /t REG_DWORD /d 10 /f

从 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 自带的结果。

当前架构

1
2
3
4
5
6
客户端  Caddy (99 ECS, Basic Auth + TLS)
            Tailscale
               WSL2 (pc-5950x)
                 ├── 8006: StepAudio 2.5 (主线~0.15 /小时)
                 ├── 8002: Fun-ASR-Nano (backup, 离线可用)
                 └── Speaker: CAM++ + pyannote ensemble (gate 通过才输出)

设计原则按优先级排:

  1. 语义真实性 — 不做 LLM 改写、不做 ITN、保留语气词和口语表达
  2. 经济性 — 主线 0.15 元/小时,低于 0.25 元/小时的心理预算
  3. 说话人识别 — 默认关闭,需要时开启,gate 不通过就不输出
  4. 效率 — 纯 ASR 7-10x,开 speaker 仍高于 2x

后续

  • speaker memory 现在只是匿名 cluster label,需要升级到真实声纹 embedding
  • 团山北路的 speaker 时间轴需要人工听音频复核
  • 长音频边界 chunk 的合并策略还可以优化

划重点

  1. ASR 模型分纯声学和 LLM 骨架两类,前者快但专有名词差,后者相反,目前没有全都要的方案
  2. 长音频退化是选型的决定性因素——短音频跑得好的模型,不一定能撑住 30 分钟以上
  3. Windows 跑 GPU 服务,WDDM TDR 是第一个要解决的问题
  4. Fun-ASR-Nano 是目前最好的本地方案,StepAudio 2.5 是性价比最高的云端方案
  5. 没有 benchmark 之前,模型选型基本靠感觉;有了 benchmark,讨论才有共同基础
  6. Speaker diarization 要加 gate——不稳定就不输出,比输出错误结果好
  7. 用 Notion 写文章 + Elog 同步 + CF Pages 自动部署,改个 status 就能触发上线
  8. 本地 ASR 能做到商用 API 90-98% 的文本相似度,专有名词差距在缩小
  9. 0.15 元/小时的云端 ASR + 本地 backup 的组合,目前用起来最舒服
  10. 这套东西从"搭个 HTTP 服务"膨胀到多模型 pipeline,本质是被问题推着走的,不是提前设计的

参考:FunASR 团队、StepFun、豆包 ASR、pyannote、CAM++。如果你有更好的 ASR 实践经验,也欢迎一起交流。

使用 Hugo 构建
主题 StackJimmy 设计