长音频转写慢 10 倍、99% 的 Attention 在白做功——MURMUR 是怎么解决的
长音频转写慢 10 倍、99% 的 Attention 在白做功——MURMUR 是怎么解决的
1. 前言
你有没有遇到过这种场景:一小时的会议录音,想转成带时间戳和说话人标注的文字稿,发现要等将近 6 分钟才出来?
现在语音识别领域其实分两派:
切片派(WhisperX 为代表):把录音切成 30 秒小段,并行跑 ASR,再拼起来。速度快,但跨片段的说话人和时间戳对不上,识别质量差。
全段派(VibeVoice-ASR 为代表):整段音频一次性塞进长上下文模型,自回归输出文字+时间戳+说话人,质量好,但慢整整 10 倍。而且有个更致命的问题——自回归模型有时候会陷入”重复循环崩溃”,整段录音直接废掉(后面详细说)。
MURMUR 这篇论文做的事情是:在几乎不损失精度的前提下,把全段派的延迟压到只比切片派慢 2 倍左右——从 370.7 秒压到 88.43 秒,实现 4.2 倍加速。
今天聊聊它的思路。
2. 背景:几个必要的前置概念
2.1 为什么长音频这么难?
现代 ASR 本质上是 Transformer 的 Encoder-Decoder(或 Decoder-only)结构。解码(生成文字)是逐 token 自回归的:生成第 1 个词,把这个词加入上下文,再预测第 2 个词……每一步都要 attend 到之前所有的 token。
问题在于:序列越长,每步 decode 的 attention 计算量越大,KV cache 占用越多。一段 300 秒的音频比 30 秒多产出约 10× 的 token,但延迟不止增加 10×。
这是长上下文模型慢的根本原因,也是 MURMUR 要优化的目标。
2.2 什么是 WER、DER、tcpWER?
先把这三个指标说清楚,不然看论文结果会云里雾里:
- WER(Word Error Rate):字词错误率,只看”说了什么”,不管谁说的、什么时间说的
- DER(Diarization Error Rate):说话人识别错误率,判断”谁在说话”
- tcpWER(Time-Constrained minimum Permutation WER):综合考虑”说了什么”、”谁说的”、”什么时间说的”,是最贴近实际场景的指标,也是这篇论文的核心优化目标
WhisperX 的 WER 是 22.5%,VibeVoice-ASR 是 19.2%,差距看起来不大。但 tcpWER 上,WhisperX 是 35.5%,VibeVoice-ASR 是 25.7%——差了将近 10 个百分点。
这才是两种方案真正的差距所在:切片系统在处理说话人归属和时间戳时表现很差,这恰恰是会议记录、庭审转录等真实应用最关心的东西。
如下图:

2.3 什么是”重复循环崩溃”?
这是自回归语言模型一个已知的 failure mode:解码器陷入循环,不停重复同一段短语或 token,直到达到最大长度上限,整段输出废掉。
想象模型在转写一段会议录音,转到某个片段时突然开始反复输出”好的好的好的好的好的……”再也停不下来——这就是重复循环崩溃。
为什么这个问题在长音频更严重?
在切片方案里,崩溃只影响一个 30 秒的片段,其他片段正常转写,损失可控。但在单次全段推理里,一旦某个时刻触发重复循环,整段 44 分钟的录音彻底报废,没有任何恢复手段。
这不是小概率事件——在 AMI-IHM 的 14 段测试录音中,有 2 段因重复循环失败被排除在 VibeVoice-ASR 的评测结果之外。也就是说,那份”精度更好”的数字,实际上是在数据上做了筛选的。如果把崩溃的录音算进去(以 100% 错误率计),单次全段推理的实际效果比报告数字差很多。
这也是为什么 MURMUR 采用 chunk-based 方案之后,真实部署场景下的精度反而比 single-pass 基线更好——因为 chunk 粒度把失败的影响限制住了。
3. MURMUR 的整体架构
如下图,MURMUR 分三步走:VAD(语音活动检测)分块 → 并行跑长上下文 ASR 模型 → 拼接并做跨 chunk 的说话人对齐。

核心优化分两个层次,原论文称为 inter-chunk(跨 chunk) 和 intra-chunk(chunk 内) 优化。
- inter-chunk:chunk 之间的粒度设计——把 chunk 大小本身当一个可调超参数,找到精度和延迟的最优平衡点
- intra-chunk:单个 chunk 内部——利用 attention 稀疏性做 KV cache eviction,在不影响精度的前提下减少每步 decode 的计算量
4. Inter-chunk 优化:chunk 大小不是固定的 30 秒
传统 chunk-based 系统(如 WhisperX)用固定 30 秒切片,是因为 Whisper 本身的输入长度限制。但 VibeVoice-ASR 这类现代长上下文模型没有硬限制,chunk 大小就成了一个可以调的超参数。
MURMUR 做了一个系统性实验,把 chunk size 从 30s 拉到 900s,观察各项指标的变化:

关键发现:
精度随 chunk 大小增加而提升,但到约 300 秒就基本饱和——继续增大 chunk,边际收益极小,而延迟持续增加。更有意思的是,在噪声较重的场景(AMI 会议录音)里,chunk 超过 300 秒后精度反而会下降:更长的上下文让模型需要追踪更多说话人的声纹,混淆概率反而增大。
对于相对干净的音频(TED 演讲、财报电话),饱和点更早;对于嘈杂的会议录音,从更长的上下文中受益更多,但上限也就到 300 秒。
下图更直观地展示了 chunk size 和延迟/精度的 trade-off:

MURMUR 选择 300 秒作为 chunk 上限。这一步本身就把延迟从 370.7 秒压到 100.8 秒,实现 3.68 倍加速,且精度不降反升(因为规避了单次推理的失败录音问题)。
5. Intra-chunk 优化:KV Cache 里 75% 以上的 speech token 是冗余的
chunk 大小定好之后,MURMUR 进一步分析:能不能在单个 chunk 的 decode 过程里再压榨延迟?
先 profile 了一段 44 分钟录音:
- 解码(decode)占总推理时间的 95.3%
- attention 操作占 decode 时间的 74.6%
所以不优化 attention / KV cache,其他什么都白优化。
5.1 KV Cache 里有哪些 token?
在 VibeVoice-ASR 这类 ASR 模型里,一次推理的输入序列结构大致是这样的:
[system prompt] [speech tokens] [system prompt] [text tokens(逐步生成)]
其中涉及两类核心 token,它们的特性完全不同,需要分开处理:
Speech token(音频 token):音频先经过 Whisper 风格的 encoder 压缩成特征向量,再展开成 token 序列——约 1 秒音频对应 7.5 个 token。300 秒的音频 ≈ 2,250 个 speech token。关键是:这些 token 在 prefill 阶段(推理开始时)就一次性全部写入 KV cache,之后每步 decode 都要 attend 它们,是固定的”静态负担”,不会增长但始终存在。
Output token(文本 token):解码时逐步生成的文字 token。300 秒的会议音频大约会生成 ~2,700 个 output token,随着解码进行不断追加到 KV cache 里,是动态增长的部分。
两类 token 在 KV cache 里的位置不同、attention 模式也完全不同,MURMUR 因此对它们设计了不同的 eviction 策略。
5.2 Speech token 的 attention 是稀疏的
MURMUR 可视化了 attention 权重矩阵:

左边是 30 秒 chunk 的 attention,比较密集;右边是 300 秒 chunk 的,出现了明显的对角线稀疏模式——解码推进到哪里,有效 attention 就集中在对应音频位置附近,前面已经转写完的音频基本用不到了。
更精确的量化:

在 28 层 Transformer 里的 24 层,保留不到 25% 的 speech token,就能覆盖 99% 的总 attention 权重。超过 75% 的 speech token 是可以安全驱逐的。
直觉上也很自然:模型在转写”第 200 秒说了什么”时,不需要回头看”第 10 秒的音频”——那段已经处理完了。
5.3 两种 KV cache eviction 策略
Output token eviction
Output token 的 attention 有两个规律:近端偏向(recency bias)——大部分权重集中在最近生成的 token 上;以及 attention sink——序列最开头的几个特殊 token 会吸收大量权重(这是 Transformer 的常见现象,模型把”不确定该 attend 什么”的权重都堆到了最前面的 token 上)。
MURMUR 直接套 StreamingLLM 的方案:保留 4 个 sink token + 最近 1024 个 token,其余全驱逐。
Speech token eviction
Speech token 不能用同一套策略,因为它的有效 attention 区域是随着解码进度向后平移的(那个对角线),不是固定在最近端。
MURMUR 设计了一个带延迟的滑动窗口:
- 前 d 步(延迟阶段):窗口保持在起点不动,让模型充分看到音频开头的上下文
- 之后每解码一步:窗口向后移动一格,追踪解码进度
参数:延迟 d = 512,窗口大小 w = 1024。
论文里特别强调:可驱逐的 speech token 不是位置连续的,它们散落在各处,所以简单的头部/尾部截断不够用,必须用这套精确追踪的滑动窗口。
6. 实验结果
在 AMI-IHM 数据集、300 秒 chunk、batch size 16 下:

- MURMUR 基础版(仅 chunked,无 eviction):延迟 100.8s,加速 3.68×,tcpWER 24.92%,略优于 single-pass(25.68%)
- + Output token eviction:延迟 97.6s,加速 3.79×,tcpWER 25.01%,几乎无损
- + Speech token eviction(d512 w1024):延迟 88.43s,加速 4.20×,tcpWER 25.29%,比 single-pass 只多了 0.61%
- 两种 eviction 同时用:延迟 96.1s,加速 3.85×——反而比单独用 speech eviction 慢,因为同时管理两套 eviction 策略有额外 overhead,相互抵消了部分收益
多数据集泛化结果如下:

干净数据集(Tedlium3、Earnings21)在较小 chunk size 就饱和;嘈杂条件(IHM、SDM)受益于更长上下文,但上限也就到 300 秒。
7. 讨论
MURMUR 的核心 insight 其实很简单:chunk size 不是固定参数,是超参数。传统方案非此即彼——30 秒切片或者全段一把梭,中间有大片值得探索的空间,这篇论文把它系统地测了一遍。这个贡献本身就有价值,即便没有 KV cache eviction,单纯把 chunk size 从 30 秒改到 300 秒就已经实现了 3.68 倍加速。
语音 token 的注意力稀疏性比通常预期的要高得多——75% 以上的 speech token 可以安全驱逐,而精度损失不到 1%。这和 LLM 推理优化里的注意力稀疏性观察是一脉相承的,但音频场景下的稀疏模式(对角线时序局部性)和纯文本不一样,在语音领域是相对新颖的系统性研究。
有几个地方值得进一步追问:
一、speech eviction 的实际加速为什么远低于理论值? 论文的理论计算显示 speech token eviction 的注意力计算量能降约 1.06×,但实测加速比要更低,因为延迟阶段和 cache 管理 overhead 部分抵消了收益。更根本的原因在于:可驱逐的 speech token 不是位置连续的,当前实现需要把不连续的 token 先 gather 出来再算 attention,这个 gather 操作本身就有代价。如果换用稀疏 attention 的专用 kernel(类似 FlashAttention 的 block-sparse 变体),理论和实测之间的差距理应可以收窄。这个实现层面的优化空间目前论文没有展开。
二、eviction 策略是位置感知的,但不是内容感知的。 当前的滑动窗口假设”音频内容和解码进度是线性对应的”——解码推进到哪里,前面对应的音频就可以驱逐。但实际上,录音里某段 30 秒可能包含一个关键的说话人名字,后续所有说话人归属都依赖它——这段 speech token 不该被驱逐,但位置感知的策略不会区分。论文也承认这个局限,指出 query-aware 或 acoustic-feature-guided 的自适应 eviction 是值得探索的后续方向。一旦能精准识别”哪些 speech token 真正重要”,驱逐比例还能进一步提升。
三、两种 eviction 合用反而更慢,这个结果比较反直觉。 理论上 output token eviction 和 speech token eviction 针对的是 KV cache 的不同区域,应该可以正交叠加——加速比应该高于单独用任意一种。但实验结果是合用的加速比(3.85×)反而低于单独用 speech eviction(4.20×)。一个可能的解释是:两套策略的 cache 管理逻辑相互干扰,维护两套独立的 eviction 状态机的 overhead 是非线性叠加的。如果在底层统一成一套 KV cache 管理框架再做优化,这个 overhead 应该可以消除。
如果你在做语音推理系统或者对 attention 稀疏性感兴趣,这篇值得读原文。欢迎评论区交流。
另外,我们团队最近出版了《动手学 AutoML:从 NAS 到大语言模型优化实战》,感兴趣的话可以看看。
