首页博客 → 如何提高语音识别准确率:八个实用方法

如何提高语音识别准确率:八个实用方法

发布于 2026-08-05 · 7 分钟阅读

「识别得不好」不是诊断结论。在几乎所有真实案例里,质量问题都出自少数几个具体原因——而其中大部分是在你这一侧解决的,在音频离开你的服务器之前。下面按值得尝试的先后顺序列出。

先测量,不要猜

没有数字,任何改动都只是口味问题。取 20 到 30 条和线上流量分布相似的录音,写下实际说了什么,然后计算字错率:替换加删除加插入,除以说出的词数。

pip install jiwer
from jiwer import wer

score = wer(reference_text, recognised_text)
print(f"WER: {score:.1%}")

有两点比绝对数值更重要。第一,在你自己的音频上测量,而不是公开基准。第二,按你在意的东西加权:如果业务需要订单号,那么 5% 的字错率配上全错的数字是失败,15% 的字错率配上干净的数字才是成功。

方法一:给模型干净的音频

识别模型内部使用 16 kHz 单声道。超出的部分会被丢弃,缺失的部分永远补不回来:

ffmpeg -i input.wav -ac 1 -ar 16000 -b:a 64k clean.mp3

重度降噪是那个通常会适得其反的例外:激进的滤波会啃掉辅音,识别反而更差。能在麦克风端解决噪音就在麦克风端解决。

方法二:说明这是什么语种

自动判定在长录音上几乎总是对的,在三秒的短片段上明显差一些。如果音频流是单一语种,就直接说明:

r = client.audio.transcriptions.create(
    model="whisper-1", file=f, language="zh",
)

这消除了一整类故障——短句被判成另一种语言,然后返回一堆不知所云的内容。同时也略微加快处理,因为跳过了语种判定这一步。

方法三:用 prompt 喂进词表

价值最高、也最常被忽略的一个参数。prompt 不会出现在响应里,它把识别向你列出的词偏移:

r = client.audio.transcriptions.create(
    model="whisper-1", file=f,
    prompt="Products: Kestrel, Kestrel Pro, Hawknest. Agents: Duarte, Ivanova, Ng.",
)

写得短而具体。20 到 40 个真实出现过的术语有效;一整段泛泛的描述没有任何作用。按场景轮换词表:计费相关的工单队列和硬件相关的队列,需要的术语并不一样。

提示词还携带风格。如果你希望转录保留标点和大小写,就把提示写成一个标点完整的句子——模型倾向于沿用给它的风格。

方法四:切掉静音

长段静音正是幻觉的来源:没有东西可识别时,模型可能自行产出填充文本。它同时也在花钱,因为计费按音频分钟。

ffmpeg -i input.mp3 -af silenceremove=start_periods=1:stop_periods=-1:stop_duration=2:stop_threshold=-45dB out.mp3

阈值要小心:切得太狠会把轻声说话连同静音一起删掉。放进流水线之前先在几个文件上验证效果。

方法五:按停顿切,不要按时钟切

长录音无论如何都要切开,才能装进 25 MB 的限制。切在哪里很关键:切点落在句子中间,两侧的词都会丢。

# 按静音而不是固定分钟切分
ffmpeg -i long.mp3 -af silencedetect=noise=-40dB:d=0.7 -f null - 2> pauses.txt

把检测到的停顿作为候选切点,每段保持在 5 到 20 分钟。更短会丢失段与段之间的上下文,更长则没有额外好处。

方法六:选择带置信度的响应格式

verbose_json 返回的不只是文本,还有分段和带概率的语种判定结果。这是自动质检的原料:

r = client.audio.transcriptions.create(
    model="whisper-1", file=f, response_format="verbose_json",
)

if r.language_probability < 0.6:
    queue_for_review(r)          # 可疑录音,转人工检查

把可疑的那百分之几路由到人工复核队列,对整条流水线质量的提升,远比继续压榨识别本身最后那一个百分点划算。

方法七:做后处理,而不是重新识别

有些错误是系统性的:同一个产品名每次都以同样的方式识别错。一份替换词典一行就修好,而且不花钱:

FIXES = {"cast rail": "Kestrel", "hawk nest": "Hawknest"}

for wrong, right in FIXES.items():
    text = text.replace(wrong, right)

词典要根据真实见过的错误来建,不要凭想象。一周生产流量里攒下的十条替换,通常比任何参数调优都更能消除可见的错误。

方法八:处理空结果和编造内容

有两种失败模式值得在代码里显式处理:空结果,以及可疑的泛泛结果。幻觉过滤器会切掉片尾字幕、「感谢观看」这类经典情况,所以空字符串确实意味着没有语音。

text = r.text.strip()
if not text:
    return None            # 是静音而不是错误,不要重试

对空录音重试只会消耗分钟数。记一条日志,跳过,继续下一条。

哪些做法没有用

用你自己的录音试一试。 注册只需一分钟,免费额度足够判断识别质量。

免费获取 API 密钥

常见问题

字错率应该在什么水平?

在支持良好的语种上、语音清晰时,个位数百分比是正常的。电话音频、背景噪音、抢话和浓重口音都会推高它。请在自己的录音上测量——公开基准说明不了你的流量。

prompt 参数真的有用吗?

有用,而且是成本最低的改进手段。把音频中出现的人名、产品和编号列成一份短清单,会明显减少最关键那些词上的错误。

应该指定语种还是让它自动判定?

音频流是单一语种时就指定,短片段尤其如此。消息确实来自不同语种时,保留自动判定。

发送前值得降噪吗?

轻度归一化有帮助;激进降噪通常有害,因为它会损伤辅音。噪音严重时,改善录音环境比任何滤波器都管用。

长录音每段切多大合适?

5 到 20 分钟,按停顿切而不是按固定间隔切。这样句子保持完整,也留在 25 MB 的请求限制之内。

相关阅读