Modal 用开源 ASR 模型实现 100 倍更快更便宜的语音转写
Transcribe speech 100x faster and 100x cheaper with open models
Modal 基于 NVIDIA parakeet-tdt-0.6b-v2 和 canary-1b-flash 搭建批量语音转写服务,在约一周的 ESB 数据集音频上实现比某专有 API 快 100 倍或便宜 100 倍,错误率相当。文章给出端到端吞吐的测量方式,并分享请求分批、GPU 内按音频时长排序、并行下载数据等优化细节。一周音频可在约一分钟内、花费约 1 美元完成转写。
Modal 用开源 ASR 模型搭批量转写服务,给出批处理与调度细节,可迁移到自建推理流水线。
开放 ASR 模型已经到来。
自从 ChatGPT 向世界展示生成式建模和人工智能已准备好进行工业级商业应用以来,性能最强的建模和智能服务大多由专有 API 提供。
但在过去一年里,开放权重模型已在从语言到图像再到视频的一系列领域迎头赶上。运行这些模型的开源框架,如 PyTorch 和 vLLM,也保持了同步。
你可能没有注意到,但在过去短短几个月里,涌现了一波专注于自动语音识别(ASR),也就是语音转文本(STT),也就是转录的高性能开放权重模型。
这些模型——包括 NVIDIA 的 Parakeet 和 Canary 以及 Kyutai 的 STT——报告了令人难以置信的准确率(词错误率,WER)、速度(实时因子,RTFx),并包含多语言、词级时间戳或语音活动检测(VAD)等附加功能。
| 模型 | ESB WER,英语(%) | RTFx | 语言 | 时间戳 | VAD |
|---|---|---|---|---|---|
| nvidia/parakeet-tdt-0.6b-v2 | 6.05 | 3386.02 | ✅ | ✅ | ❌ |
| nvidia/canary-1b-flash | 6.35 | 1045.75 | ✅✅✅✅ | ✅ | ❌ |
| kyutai/stt-2.6b-en | 6.4 | 88.37 | ✅ | ✅ | ✅ |
一些 CEO 数学:Modal + 开放 ASR > 100 倍
一个快速的信封背面计算就足以让我们对这些新模型感到非常兴奋。
- 专有 API 对每分钟音频收费约 0.4 美分
- 开放 ASR 排行榜显示,在 A100 上,RTFx,即每壁钟分钟的音频分钟数,达到数千
- Modal 上的 A100 或 L40S GPU 目前约为每分钟 4 美分
即使对开销做出悲观假设,粗略计算表明,运行转录时每分钟音频的成本可能降低 100 倍。
我们听到一些传言说这是真的(来自那些从专有 API 转向我们平台的人),所以我们决定亲自验证。
我们
- 在 Modal 上实现了一个批量转录服务
- 使用 NVIDIA 的 parakeet-tdt-0.6b-v2(英语)和 canary-1b-flash(多语言)
- 并将其与一个流行的专有 API 进行比较
- 在来自 ESB 基准测试数据集的大约一周(7 * 24 小时)语音数据上,这些数据集用于 HuggingFace ASR 排行榜。
经过一些优化和实验后,我们能够部署一个转录服务,其速度比我们测试的专有 API 快 100 倍以上,或成本低 100 倍以上,同时错误率与之相当。(严格来说,开放模型在这个数据集上的错误率略低……)
那就是
- 一周的音频
- 仅在一分钟内转录完成
- 只需 1 美元。

| 相对端到端吞吐量 | 成本节省 | |
|---|---|---|
| 仅英语 | ||
| Parakeet,最快 | 112 倍 | 60 倍 |
| Parakeet,最便宜 | 25 倍 | 200 倍 |
| 专有 API | 1 倍 | 1 倍 |
| 多语言 | ||
| Canary,最快 | 80 倍 | 55 倍 |
| Canary,最便宜 | 12 倍 | 152 倍 |
| 专有 API | 1 倍 | 1 倍 |
我们如何在一分钟内以 1 美元转录一周的音频。
我们想分享一些与批处理和跨工作器分发转录请求相关的实现和优化过程的细节。
希望这些能帮助你优化自己的转录服务并构建更高性能的 Modal 应用。
现实世界的用例:每小时转录数小时的音频。
在我们深入工程实现之前,先确保我们清楚要针对哪些用例来优化系统。这对任何性能工程任务来说都是个好主意!
大规模批量转录的理想用例是那些每秒收集大量音频的公司。比如一个呼叫中心,你的通话可能被录音以用于质量保证,每小时产生数千小时的新录音。数据被丢到 S3 上加载到数据湖中,每小时我们需要加载新文件并转录它们。
或者你可能是一家基础模型公司,到处寻找语言 token。你从互联网各处抓取了音频文件,想要转录它们,以便用于基于文本的语言模型的下一个 token 预测训练。
在这两种情况下,我们都可以假设静态时数据存储在某种对象/文件式的云存储中,而衡量指标是
- 我们多快能完成所有数据的处理
- 处理成本是多少
批量转录与流式场景有本质区别,后者有许多用户,每个用户都需要低延迟的转录服务用于实时应用。两者的评估指标不同,所需的实现选择也不同。
如果你对流式转录感兴趣,可以看看我们的 Kyutai STT 示例。对于介于纯批量任务和流式之间的用例,你可以考虑动态批量转录(代码示例见此处)。
为批量音频转录设计基准测试
我们通过 WER 和 ESB/HuggingFace Open ASR Leaderboard 基准测试对质量进行了合理性检查。
选择 HuggingFace ASR Leaderboard 中所包含模型的一个好处是,我们可以使用相同的数据集和 WER 评分代码。这让我们能够验证我们的部署没有引入任何 bug 或以某种方式降低准确率。
这也有助于将我们的准确率与专有 API 的对比建立在完整排行榜结果的基础上。
但我们衡量的是端到端性能,而不仅仅是模型执行时间。
ASR 模型报告的速度是 RTFx,它只考虑转录时间。如果你在本地运行推理(相对于音频字节生产者和文本消费者而言),这是合理的。但对于分布式云服务,你需要考虑数据传输时间。对于具有水平扩展能力的云服务,你还需要考虑冷启动时间。

我们理解模型提供商为什么想聚焦于模型所花费的时间。但对我们来说,忽略流程中的这些部分似乎不公平。我们大多数人最终关心的是任务的总耗时,而不仅仅是花哨的“AI”部分。为了考虑到这一点,我们报告端到端吞吐量,它衡量客户端侧的持续时间,并包含冷启动、网络延迟以及其他形式的数据移动。
使用 Modal 构建批量转录架构
我们使用 Modal 搭建了转录的批量处理,同时使用了开放权重模型和专有 API。在这两种情况下,我们都花时间优化了吞吐量。
两种架构的主要区别在于,使用开源模型时,我们在 Modal 容器本身上配置 GPU 并执行转录,而使用专有 API 时,我们配置 CPU 容器来发起并行 HTTP 请求。我们的所有数据中都不包含 CPU 的成本。与 GPU 和 API 请求相比,它们几乎可以说是免费的!
在 Modal GPU 上部署 NVIDIA 的 ASR 模型
NVIDIA 声称拥有许多最准确、最快的开源 ASR 模型。我们选择使用他们的 parakeet-tdt-0.6b-v2 模型,因为它报告的推理速度比任何错误率相当的模型快 3 倍,以及它的姊妹模型 canary-1b-flash, 该模型 RTFx 较低,但支持多种语言(英语、法语、西班牙语和德语)。
我们的服务构建在 NVIDIA 的 NeMo 框架之上,这使得在 NVIDIA 的任何 ASR 模型之间切换变得相对简单。
从 HuggingFace Open ASR GitHub 仓库中获取 NeMo 代码,并将其转换为分布式批处理服务,在我们启动作业时动态配置 GPU,这并非难事。一个基本演示只需一个 Python 文件——无需 YAML,没有问题。

从 Modal CPU 饱和专有 API
我们选择了一个流行且有竞争力的专有 ASR API,并测试了基础级别的服务。为了在吞吐量上进行公平比较,我们测试了多种方法,使用分布式 Modal 部署来饱和请求速率。最大化吞吐量的核心策略是将转录请求分配到与 API 最大并发限制相等数量的工作线程上。

我们观察到了限流,但为了更公平,我们忽略了它。
在完整数据集上运行时,我们的请求吞吐量可能受到了限流。为了尽可能公平,我们报告了我们观察到的最大吞吐量。虽然我们无法确定我们测量的是同一件事,但我们估计的最大吞吐量与 API 文档和营销网站上报告的速度相符。
做一些 100 倍的工程
分布式计算——无论是在单个 GPU 内的流式多处理器之间,还是在全球云实例集群中——都可以带来令人印象深刻的吞吐量提升。但根据你的实现如何有效地移动数据并利用可用硬件,它也可能导致吞吐量下降。
确定最佳实现是架构系统时的深思熟虑设计与对系统旋钮进行实验的结合——你知道的,就是“工程”。
将数据分配到批次中
我们可以将一些优化视为打包问题——无论是在内存还是时间方面。当我们没有高效地打包内存时,我们最终会执行比必要更多的迭代或请求。当我们没有高效地打包时间时,我们最终会在等待工作的同时拥有空闲的计算通道。这就是平衡与不平衡负载分布之间的区别。
换句话说,我们希望始终填满所有可用的通道。

在我们的系统中,我们需要将数据分配到对我们 Modal Function 的请求批次中,以及每个 GPU 内部。
将音频文件批处理到请求中
为了平衡我们 Modal 自动扩展池中的工作负载,我们希望以以下方式匹配每个请求中发送的数据分布
- 字节数
- 音频文件数
- 音频文件的总时长,以确保每个 worker 下载数据和执行转录所花费的时间大致相同。
幸运的是,对于大批量任务,我们可以在将数据分成请求批次之前简单地打乱数据,以确保分布匹配。务必不要跳过这一步。样本顺序与时长之间可能存在相关性,并已固化在你的表中;或者数据可能像 ESB/HF 数据集那样是预先排序好的。
按字节分批,让 GPU 飞起来
ASR Leaderboard 上的大多数(如果不是全部)参赛者都进行批量 GPU 推理。对于 Parakeet 来说,这就像在 transcribe 调用中添加 batch_size 关键字参数一样简单。
批量推理能更好地利用 GPU,一种大规模并行、面向吞吐量的计算设备。它向底层程序运行时和硬件暴露更多并行性。我们的批大小受限于GPU 的内存。
幸运的是,NVIDIA 提交给 HuggingFace 排行榜的作品让我们对使用多大的 GPU 批大小有了一些了解。在实验中,我们发现一系列取值的效果大致相同。
但按时间打包呢?
较长的录音需要更长的处理时间。这对我们如何将音频分配到批次中有重要影响,因为一个批次只有在其所有元素都处理完毕后才算完成。这引出了一个策略:在 GPU 批次内匹配音频时长,以最大化 GPU 每个通道内的执行时间。

要实现这一策略,请在映射推理调用之前对音频片段进行排序。记住,我们说的是对单个 GPU worker/请求的音频进行排序。我们在分批成请求之前进行了打乱以平衡工作负载,但现在我们要对每个请求进行排序,以最大化 GPU 批处理的效率。
如果你因此对 Hadoop Map-Reduce 中的排序阶段产生了 PTSD 般的闪回,1)我们感同身受,2)我们正在招聘,我们保证你永远不会在生产环境中看到 HDFS。虽然修复本身相对简单,但效果可能相当大,因为录音长度通常呈指数分布(大概反映了底层的无记忆动态)。
将数据下载到 worker
我们还需要将数据移动到每个 worker。最佳解决方案高度依赖于你静态数据的位置和状态。
在我们的设置中,我们从保存在 Modal Volume 上的 WAV 文件形式的音频片段开始。在转录开始之前,我们将文件下载到本地磁盘。为了最小化传输时间,我们使用 Python 的 multiprocessing.ThreadPool 通过并行请求来饱和网络带宽。通过将文件保留在内存中来避免磁盘写入可能会稍微加快速度,但 SSD 吞吐量远高于网络吞吐量,我们认为不值得尝试。
选择 GPU 类型和请求数量
还有两个设计决策会对我们的成本和吞吐量产生重大影响:GPU 型号和请求数量。
这些选择以某种复杂的方式相互作用:例如,大 GPU 更快但更贵。我们没有试图推理哪种组合会带来最佳结果,而是选择通过经验来确定最优配置——在座的 MLE 们,想想超参数微调。
因为我们有两个衡量指标——成本和吞吐量,所以不一定存在单一的“最优配置”。相反,每个模型都存在一个帕累托前沿配置集合,这些配置优于所有其他配置,但代表了成本与速度之间不同的权衡。
请注意,专有推理服务未显示在此图表上——如果我们要绘制它,它会位于本句开头“专有”一词附近。

对于我们的批量转录服务,我们可以根据是想省钱、省时间还是折中,选择不同的 GPU 型号和 worker 数量组合。但无论我们具体选择哪种配置,在 Modal 上部署顶级的开源 ASR 模型都是专有服务的有竞争力的替代方案。
几分钟内即可在 Modal 上运行你自己的大规模、高性能音频转录!
像 Substack 和 Zencastr 这样的 Modal 用户都在 Modal 上大规模运行他们的转录工作负载——无需专有 API 或 AWS YAML 工程师认证,只需开源模型、一两个 Python 文件,以及一个 Modal API 密钥即可在我们平台上配置资源。
了解有关使用 Modal 增强你的 音频推理服务的更多信息,使用本文中的代码快速部署你自己的批量转录服务,或查看我们的其他语音转文本示例。
来源:Modal Blog · modal.com