语音识别圈子里有一句话:批量转写是站着说话不腰疼,流式转写才是真功夫。我前阵子在一套实时会议纪要系统里,把 Gemini 3.5 Transcribe 的流式转写 API 从头到尾摸了一遍,最终在一个混合测试集上拿到了 WER 4.0% 的成绩。数字看着挺漂亮,但真正值钱的其实不是这个数本身,而是为了保住这个数,背后做的一系列工程取舍——模型怎么配、VAD 怎么配合、结果怎么兜底、成本怎么扛。这篇文章把我的完整实测过程和踩坑记录整理出来,给想上流式转写的朋友一个参考。
先交代一下背景。我手头的项目是做一个多路实时语音转写服务,来源是远程会议音频流,业务方要求说完话之后 3 秒内出可读文本,最终整理稿的错别字率要控制在一定范围内。这个场景可以说把语音识别的难点全占了:实时性要求高、说话人重叠、网络抖动、专业术语多。当时我用了大概两周时间做方案选型和压测,最后选择了基于 Gemini 3.5 Transcribe 的流式接口。这篇文章不会贴太多源码,重点放在"为什么这么选"和"实测中到底发生了什么"上。
1. 为什么盯上 Gemini 3.5 Transcribe:实时会议纪要的选型考量
1.1 场景需求:为什么"流式"是个硬约束
很多第一次做语音转写的人会问:直接录完音再丢给离线转写不行吗?省心又准确。
大部分场景还真不行。我做的是实时会议纪要,产品逻辑是让参会者一边开会一边看到字幕和待办事项,会议结束立刻能拿到整理稿。如果走离线转写,准确率确实更高,但文本出来的时间滞后少说一两分钟,对实时协作场景基本没有帮助。还有一个更实际的原因:会议的录音文件质量往往不可控,如果某一路音频因为网络问题损坏了,离线转写会在事后才发现,而流式接口在音频进来的时候就能暴露问题,方便系统第一时间做告警和重连。
所以需求一上来就锁定了流式。流式转写意味着语音识别引擎必须在每一小段音频到达时立即给出结果,而不是等整段音频结束。这个小差异对模型的内部机制影响非常大:批量模型可以看完整段音频再优化全局路径,流式模型只能依赖左侧上下文,相当于"走一步看一步"。这也是为什么流式 WER 通常会比同模型的批量 WER 高一些。
1.2 候选方案对比:为什么是它
选型期我横向比了四类方案:开源本地模型、国内云厂商的流式接口、通用 ASR 接口、还有 Gemini 3.5 Transcribe 这种模型家族里带出来的新接口。
开源本地模型(比如 Whisper 系)的好处是免费、数据不出内网,但实时的工程成本极高,需要自己搭 Websocket 网关、处理并发、优化推理引擎,还要考虑 GPU 成本曲线。我当时测算过,如果跑 50 路并发,光显卡投入就是个大数字,而且语音识别模型的显存占用、批处理策略、断句边界这些都得一行一行调,两周时间肯定不够。
云厂商的通用流式接口胜在稳定,但有几个问题:一是长音频的分片策略不透明,二是部分接口的热词功能有限,三是某些接口在口语化表达上表现一般,"嗯""啊"这类语气词占位混乱。
选 Gemini 3.5 Transcribe 的核心理由有三个:第一,它在基准测试里对流式场景的上下文理解好,尤其是会议这种长会话场景,不会因为前面说了什么就忘了;第二,接口原生支持部分结果(partial result)和最终结果(final result)的双层返回,做实时字幕体验会好很多;第三,模型家族共用一套底层能力,后续如果我想在同一套系统里做摘要、待办抽取,不需要再切换服务商。
当然,选它不等于没有成本和风险。后面第五部分我会展开讲实际接入时遇到的坑。
2. WER 4.0% 是怎么测出来的:评测方法和数据集构成
2.1 WER 计算方式:别被一个数字骗了
WER(Word Error Rate,词错误率)的概念不复杂,就是把识别结果和人工转写文本对齐,算编辑距离——有多少个字被替换了、删掉了、插进来了,除以参考文本总字数。
公式长这样:
WER = (S + D + I) / N * 100%其中 S 是替换错误数,D 是删除错误数,I 是插入错误数,N 是参考文本总词数。
之所以说"别被一个数字骗了",是因为 WER 对测试集极度敏感。同样是 4.0%,在标准普通话、安静录音室测出来,和在地铁噪声里测出来,完全是两个含义。我这次报告的 4.0%,来自自己的混合测试集,里面有安静办公室、咖啡馆背景音、远程会议压缩音质、不同口音四大类音频,比例大概是 35% / 25% / 25% / 15%。这个组成的代表性比单一场景强很多,但也意味着你不能拿它和别的团队在自己测试集上跑出来的数字直接对比。
2.2 数据集构成:我们测了什么
我准备了三组测试数据:
- 基准组:20 小时广播级质量普通话音频,单人朗读风格,干净背景
- 压力组:15 小时会议录音,含两人以上对话、轻微重叠、电话语音、压缩失真
- 领域组:10 小时医疗问诊模拟对话,含大量药品名、症状描述、数字串
每组都有对应的人工转写文本作为参考。人工转写这里有个容易被忽略的细节:参考文本的标点和大小写怎么处理?如果模型输出了标点,而参考文本没标点,标点会被算进 WER 里,导致数字虚高。我统一约定:参考文本保留标点,但把标点单独做为 token 参与对齐。理由是实际产品里标点对可读性影响大,不能直接忽略。
在基准组上,Gemini 3.5 Transcribe 的流式 WER 做到了 2.1%;压力组 5.3%;领域组因为有热词加持,3.8%。整体混合加权下来是 4.0%。这个数字比离线模型的成绩通常差 0.8~1.5 个百分点,符合流式模型的预期规律。
2.3 流式特有问题:延迟指标和结果稳定性
WER 只能衡量"最终文本好不好",但流式场景还需要关心另外两件事:延迟和稳定性。
延迟方面我主要测三个指标:
- 首词延迟(TTFT,time to first token):说话人开口后多久看到第一个字。我实测的 p50 在 350ms 左右,p95 在 900ms。这意味着人已经说出完整一句话了,字幕才刚蹦出前几个字,体验上还是能接受的。
- 实时率(RTF,real-time factor):处理 1 秒音频需要多少秒计算时间。流式接口因为是服务端并发处理,本地不太容易测准,但通过并发压测,50 路同时跑时整体 RTF 仍然小于 1,没有出现计算追不上音频的情况。
- 尾延迟:说完最后一个字到收到最终结果的时间。这个数字实测平均在 800ms 到 1.2s,取决于端点检测(VAD)什么时候认为句子结束了。
稳定性也很关键。流式接口通常会输出多个部分结果(partial),然后在一个断句点输出最终结果(final)。我统计了"文本回退"现象:部分结果里出现的词,到了最终结果里被改掉。正常情况下,一段 10 秒的句子大约会产生 8~15 个 partial,其中有 1~2 个词在过程中被修正,这是正常的。如果修正太频繁,说明模型在局部上下文里摇摆,字幕会出现明显抖动。
Gemini 3.5 Transcribe 的 partial 稳定性还算不错,会议场景下大约 87% 的 partial 内容与 final 完全一致。这个指标不在官方文档里,但我建议任何用流式接口的人都要自己统计一下,因为它直接影响前端字幕的观感。
3. 4.0% 的含金量:五个压力场景的实测拆解
3.1 安静环境不惊喜,嘈杂环境才是分水岭
我在安静办公室里播放标准朗读音频,WER 2.1%,说句实话,这个水平跟市面上头部 ASR 差距不大,没有给我太多惊喜。真正拉开差距的是嘈杂环境。
咖啡馆场景(背景音乐 + 零散人声,信噪比大约 15dB)实测 WER 5.8%,比安静环境高出近 4 个百分点。但仔细看错误类型,发现替换错误占据了 80% 以上,而且是"音近字错",比如"快速"变成"快速"这类。这说明模型在噪声下不是听不清,而是对混淆音的选择不够果断。这时候靠热词可以救回来一部分,具体做法后面讲。
远场说话人场景(距离麦克风 1.5 米)表现也出乎我意料,一开始 WER 高达 9% 以上,后来发现是增益问题,前端做了一次 AGC 自动增益补偿之后,降到 6.2%。这个事提醒我:流式转写不是模型单方面的事,前端音频质量直接影响最终效果。
3.2 专业术语和热词:数字的另一个真相
医疗问诊这个领域组我专门多花了心思。里面有一堆专业名词,比如"阿托伐他汀钙片""房颤射频消融术",还有各种剂量的数字串。任选一个通用模型,裸跑这类数据,WER 很容易飙到 10% 以上,因为模型没见过这些词,只能按字面发音瞎猜。
我用了两招来解决。第一招是热词列表(也有的平台叫词汇表或自定义词表),把领域常见词、科室名、药品名加进去,并给一个适中的权重。加了热词之后,领域组的 WER 从 7.6% 降到 3.8%,效果非常明显。第二招是后端文本纠错,针对数字单位组合做规则,比如"两克""2克"统一成"2g"。这一招不属于模型层面,但工程上极其有效。
有一个经验供参考:热词别贪多,尤其别给普通词加太高的权重。我一开始把 200 个常用词都加进去,结果出现了"房颤消融术"这种误融合——模型开始频繁产出领域相关但上下文不对的词。后来把热词压缩到 50 个核心词,权重分了三档,问题缓解不少。
3.3 口音、语速和重叠语音:流式模型的软肋
这套系统在广东普通话上表现一般,WER 从基准的 2.1% 升到 4.6%。我能理解:模型训练语料里标准普通话占比高,方言口音属于长尾分布。如果业务里口音用户比例很高,我建议单独收集口音音频做评测,别只看整体指标。
重叠语音(两个人同时说话)是这次实测里最让我头疼的场景。会议里经常出现插话、抢话,模型在这个状态下会产生"语音分裂"或"吞字"。压力组里重叠片段的比例大概 10%,但这部分贡献的错误率占了总错误的一半左右。Gemini 3.5 Transcribe 支持说话人分离(speaker diarization),但流式场景下分离质量明显不如离线模式。我最后的产品方案是:重叠片段的转写结果保留原文,不做降权,但展示时用透明度区分置信度,让用户知道这段可能不靠谱。
4. 工程取舍的核心:延迟、成本和质量的三角关系
4.1 延迟和准确率的矛盾:什么时候该牺牲 WER
流式接口普遍有"快速返回"和"稳定返回"两种倾向,本质上是同一个模型的不同参数配置。我这边实测下来,如果把 partial 返回间隔从默认的 300ms 拉长到 600ms,首词延迟会从 350ms 升到 520ms,但 final 的 WER 能降低 0.6 个百分点。原因不难理解:三角色频率越高,模型看到的上下文越短,错误概率越高。间隔拉长一点,模型决策时参考的信息更多。
问题来了:这个延时你的业务能接受吗?
我做的是会议纪要,用户字幕允许有半秒的滞后,所以我把 partial 间隔调到了 500ms 左右,在可接受延迟范围内换来了更稳的字幕流。如果你的场景是语音助手、实时字幕翻译,延迟优先级更高,那就得接受 partial 里多一些反复修正。
另外还有个参数值得关注:最长静音等待。默认值通常在 1.5 到 2 秒,如果说话人停顿时间超过这个值,模型就认为句子结束并返回 final。开会时经常有人"呃……呃……"半天,停顿时间很长,这时候要是不调这个参数,文本会被切得稀碎,后续自然语言处理的召回率会大幅下降。我把它调到了 4 秒,句子完整度明显改善,代价是每句话的结果等到得晚一些。这个取舍逻辑是:宁可让一句话晚 2 秒出,也别把一个完整观点切开。
4.2 成本账:流式接口不是一个廉价方案
任何商业 ASR 的流式接口定价都比批量接口贵,Gemini 3.5 Transcribe 也不例外。按我测试的量级,流式价格大约是批量的 1.8~2.2 倍。为什么差这么多?因为流式要求服务端持续维持连接、实时计算、随时返回部分结果,资源的占用和浪费都比批量大。
这里有个隐蔽的计费陷阱:流式按"音频时长"计费,但判断"音频时长"的口径很关键。有些平台按上行音频的总时长算,有些按 VAD 检测到的有效语音时长算。如果业务现场经常有人不开麦克风但环境音一直传上去,那么按总时长计费会让你花很多冤枉钱。我建议在接入前仔细核对计费文档,最好做一次小流量账单验证——先跑三四天真实业务流量,对比估算账单和实际账单,确认一下计费口径。
成本优化的方向有两条:一是做前端语音活动检测,只有检测到有效人声才把音频流交给转写服务,环境静音直接拦截掉,能省下不少时长;二是降低并发峰值,把转写请求排队,用消息队列削峰填谷。前提是你的业务允许转写结果有一点延迟。
4.3 稳定性与兜底:流式服务的可用性实测
我压测那几天,总共跑了大约 60 小时的长连接音频流,粗算下来遭遇了 4 次连接中断,平均每次恢复时间在 20 秒左右。对于实时会议场景,20 秒的文本空白是能感知到的,所以兜底逻辑必须提前做好。
我的做法是:前端同时负责本地录音和上行转发,转写服务连接中断时,本地录音不打断;重连后,把断点前的音频重新补传给服务端。这个方案的前提是转写服务支持"从某个时间点开始续传"。当时我用的是手动判断:客户端记录发送到哪个字节位置,重连后从那个位置重新开始。注意了,这里有个关键细节——补传的音频必须和实时流走的是同一条处理管道,否则会因为音频格式、采样率的微小差异导致识别结果错位。
另外,限流问题要重点测。流式接口通常有并发连接数的上限,有的还按项目维度限制并发数。我一开始没注意,在 50 路并发压测时直接撞了限流,大量转写请求开始排队,RTF 飙升到 2.5,字幕延迟肉眼可见。建议在架构设计阶段就把并发配额和业务高峰对齐,宁可接一个流量控制层,也不要依赖服务的即时扩容。
5. 上线前必须处理的细节:标点、VAD 和长会话
5.1 标点、数字和英文大小写:数据清洗不能省
语音识别的输出原始内容包括文本、开始时间、结束时间、置信度,有些还带标点和大小写。即使模型自带标点,直接拿来用仍然会踩坑。
我遇到一个典型案例:医疗场景里医生说"两片,每天三次",模型输出成"两片每天三次",少了逗号,导致用药指令的语义变化。另一个例子是数字,"二零二四"被模型当成中文数字输出,而业务系统需要阿拉伯数字。这些都不是模型错误,而是输出格式与业务需求的错配。
我的建议是:在模型输出后加一层格式层,做这些事:
- 中文数字统一转阿拉伯数字(白话说"三点五毫克",输出"3.5mg")
- 英文单词转小写或统一首字母策略
- 按业务字典修正领域常见词(比如"吃一片"要不要统一为"1片")
- 断句标点按照句子完整性再整理一遍,去掉让 NLP 模块困惑的零散碎片
这层逻辑看起来和 ASR 无关,但做好了,下游摘要、实体抽取的准确率能提升 5%~10%。
5.2 VAD 切边和端点检测的配合
VAD(语音活动检测)是流式转写的隐形大战场。模型的 VAD 和前端自研的 VAD 是两回事,很多集成失败案例就出在两者打架。
我最初的做法是前端用自己的 VAD 判断人声开始,然后才开始往转写服务发音频。这样确实能节省流量,但问题也来了:前端的 VAD 和模型的 VAD 阈值不一致,前端已经判断"没人说话"并且断了流,模型这边还在等后续音频,断句被硬生生掐断。后来改成前端 VAD 只做流控(超过一定静音时长就停止发送),但不主动掐断,把断句决策完全交给服务端的 VAD。这样改了之后,final 结果的句子完整性明显好转。
另外还有个经验:VAD 的前置填充(pre-roll)很重要。也就是说,当检测到人声开始后,向前回退 200~300ms 把音频补进去,避免句首第一个音被 VAD 吃掉。句首音可是 WER 的大户,一个"呃"字被吞掉,整句话意思可能就不对了。
5.3 长会话与上下文:一场一小时会议怎么不停顿
流式接口会维护一个会话上下文,所以一旦会议持续一个小时,上下文累积对结果的影响需要专门处理。实测发现,会议开到后面,早期提到的专属名词(比如某个项目的代号"云帆")在后续转写里会更容易被识别正确,这是上下文带来的好处。但反过来,如果会议中途话题完全切换,模型可能还带着旧话题的下意识倾向,导致新话题的某些词组被强制匹配到旧词上。
我的处理方案是:提供上下文重置机制,允许业务方在检测到明确的话题切换(比如主持人说"我们进入下一个议题")时清空会话或者注入新的话题提示词。这个功能在文档里不一定有,需要看平台是否支持。如果不支持,可以退而求其次,用热词列表的替身来影响当前会话的倾向性。
5.4 异常输入的保护:非语音音频
还有一个很容易被忽略的场景:参会人那边没说话,但传来了鼠标点击声、键盘声、甚至短视频外放。模型面对这些非语音输入时,可能会输出一些毫无意义的"幻觉文本"——也就是听起来像语言、实则完全随机的字串。这在流式场景下特别恼人,因为它们也会成为 final 结果,污染下游摘要。
我实测里,键盘敲击声偶发会触发幻觉文本,概率大约 2%。处理方式是给 final 结果做一个置信度阈值过滤——当整句平均置信度低于某个值(我这边取的是 0.45),丢弃该句并标记为"非语音"。这个操作简单,但能挡掉大部分幻觉污染,也能减少对用户注意力的干扰。
6. 最后聊几句实测感受
我花在评测上的时间很多,但回头看,真正影响项目成败的不是模型本身,而是围绕它做的工程决策。WER 4.0% 这个数字,单独拿出来不能说明任何问题,只有把它放进你的业务场景、你的延迟预算、你的成本范围里,它才算一个有用的参考值。
这里有一个总体印象:Gemini 3.5 Transcribe 的流式转写在通用场景下属于第一梯队,准确率和稳定性之间的平衡点调得不错,尤其是 partial 的稳定性让人省心。但它在强口音、强噪声场景下并没有神奇到超越物理规律,还是需要配合前端增益、热词列表和置信度过滤来压住错误。
如果只看一个数字来决策,我建议不管换哪家服务,都先按我第二部分的方法建一套自己的评测集,跑三天真实流量,再做决定。语音识别这个领域,每个人的"4.0%"含金量都可能完全不同,拿别人的数字直接套用,大概率会在生产环境里翻车。
最后分享一个可复用的经验:所有流式转写服务的调优,本质上是在延迟、成本和准确率之间做三角取舍。你不可能三者全占,只能根据业务核心诉求选择牺牲谁。像我这种会议纪要场景,延迟要求中等、成本敏感、准确率要求高,所以我的取舍顺序是:先守住准确率,再谈延迟优化,最后抠成本。如果你的业务是实时字幕翻译,可能第一优先级就是延迟。想清楚自己的优先级,再去调那些参数,就不会被厂商的基准分数牵着鼻子走。