Speech-to-Text
语音转文本(STT),也称自动语音识别,使用 Whisper 等神经网络模型将语音音频转录为文本,并以词错误率评估效果。
语音转文本(STT),也称为自动语音识别(ASR)或简称语音识别,可将口语音频转换为书面文本。STT 模型会将波形转换为时频表示,使用神经网络将其映射为字符或词片段,并输出转录文本,通常还包含标点、时间戳和说话人标签。它是语音助手、实时字幕、会议记录和通话分析的输入层,其转录文本还可供自然语言处理(NLP)用于搜索、摘要生成和意图检测。在无标签音频上进行自监督预训练,并大规模开展弱监督训练,例如 OpenAI 的 Whisper 使用来自互联网的 68 万小时多语言音频进行训练,使现代系统能够准确处理各种口音、背景噪声和数十种语言。
语音转文本的工作原理#
首先对音频进行重采样,Whisper 使用 16 kHz,然后将其转换为对数梅尔频谱图,即显示各频带能量随时间变化的网格。Whisper 使用 25 毫秒窗口、每隔 10 毫秒计算一次 80 个梅尔频带;其 large-v3 模型使用 128 个频带。由卷积层和 Transformer 层构成的声学编码器会将这些帧转换为特征。Conformer 编码器将卷积(用于捕捉局部声音模式)与自注意力(用于关联语句中相距较远的部分)交错组合;在不使用外部语言模型的情况下,它在 LibriSpeech test-clean 和 test-other 测试集上的词错误率分别达到 2.1% 和 4.3%。三类解码器会将编码器特征转换为文本:
- 连接时序分类(CTC): 为每个音频帧预测一个字符、词片段或空白符,然后合并重复项并移除空白符。所有帧并行解码,因此 CTC 速度很快。
- 转导器: RNN-T 及其后续模型会随着音频帧到达而输出 token,因此适用于手机上的流式识别和实时字幕。
- 注意力编码器-解码器: 文本解码器在关注编码后音频的同时,逐个生成 token。Whisper 通过这种方式解码 30 秒的窗口,并使用特殊 token 来识别语言、预测时间戳或翻译成英文。
流式系统会显示随着更多音频到达而不断变化的部分转录内容,并在说话人停顿时完成一个片段:
解码后,逆向文本规范化会将“twenty five dollars”等口语形式改写为“$25”;说话人分离则会按照说话人及其发言时间拆分转录文本。
训练数据与模型#
- 自监督预训练: Meta 的 wav2vec 2.0 通过遮蔽无标注音频的部分内容来学习语音表示。该模型使用 53,000 小时的无标注语音进行预训练,只用 10 分钟的转录音频进行微调,就在 LibriSpeech 的 clean 和 other 测试集上分别达到 4.8% 和 8.2% 的词错误率。
- 大规模弱监督: Whisper 使用在线获取的音频及其不完美转录文本进行训练。其模型规模从 tiny 的 3,900 万参数到 large 的 15.5 亿参数不等;turbo 模型是经过优化的 large-v3,包含 8.09 亿参数,运行速度约为 large 的 8 倍。
- 幻觉: 注意力解码器的行为类似于语言模型,因此静音或噪声可能导致它们编造流畅的文本。Careless Whisper 研究发现,约 1% 的 Whisper 转录内容包含音频中不存在的完整短语或句子;说话人长时间停顿时,这种情况更常见。
语音转文本与相关术语#
- 语音识别和 ASR: 语音转文本的同义词。
- 说话人识别与分离: 确定是谁在说话,而不是说了什么。说话人分离会为录音中的片段标注说话人,因此会议转录文本可以标明每一行内容由谁说出。
- 自然语言理解(NLU): 理解转录文本的含义,例如“七点订一张两人桌”中的意图和实体。
- 文本转语音(TTS): 与语音转文本方向相反,即根据文本生成语音。语音助手会将 STT、大型语言模型和 TTS 串联起来。
实际应用#
- 字幕与无障碍: 手机、视频平台和会议软件中的实时字幕,让失聪或听力障碍人士也能获取语音内容,并让所有人都能搜索这些内容。
- 临床文档: 环境式记录助手会转录医患对话,并为电子健康记录起草临床笔记。
- 联络中心: 转录后的通话内容可用于搜索、合规检查和情感分析。
- 视觉系统语音控制: 将“找出红色背包”这样的转录指令转化为提供给 YOLOE-26 的文本提示。YOLOE-26 是 Ultralytics YOLO26 的开放词汇版本,即使推理时指定的类别从未出现在训练类别中,也能检测并分割这些类别。
衡量准确率#
词错误率(WER)统计将转录文本转换为参考转录文本所需的替换、删除和插入操作次数,再除以参考文本的词数。以下代码使用词级编辑距离计算 WER:
import numpy as np
reference = ["turn", "on", "the", "kitchen", "lights"]
hypothesis = ["turn", "of", "the", "kitchen", "light", "please"]
# Edit distance over words: d[i, j] is the cheapest way to turn the first i reference words into the first j hypothesis words
d = np.zeros((len(reference) + 1, len(hypothesis) + 1), dtype=int)
d[:, 0] = np.arange(len(reference) + 1) # deletions
d[0, :] = np.arange(len(hypothesis) + 1) # insertions
for i in range(1, len(reference) + 1):
for j in range(1, len(hypothesis) + 1):
substitution = d[i - 1, j - 1] + (reference[i - 1] != hypothesis[j - 1])
d[i, j] = min(substitution, d[i - 1, j] + 1, d[i, j - 1] + 1)
# Word error rate: (substitutions + deletions + insertions) / words in the reference
print(f"{d[-1, -1]} errors / {len(reference)} words = WER {d[-1, -1] / len(reference):.0%}")它会输出 3 errors / 5 words = WER 60%:“of”替换了“on”,“light”替换了“lights”,而“please”是插入项。由于插入也计入错误,WER 可能超过 100%;在评分前,Open ASR Leaderboard 等基准会统一大小写、标点和拼写变体,因此“Lights.”和“lights”会被视为一致。对于中文和日语等词语之间没有空格的语言,则使用字符错误率进行评分。










