目录[-]
一、背景
公司上线了一个音生文功能:员工说话,AI转成文字。产品上线前,测试组遇到一个现实问题——没有真实的语音数据可以用来测试。
困境有三:
-
找员工录音?成本高、周期长、涉及隐私
-
随便说几句?覆盖不了不同说法、不同场景
-
上线后再发现问题?用户会直接骂
更麻烦的是:AI模型升级后,效果是变好了还是变差了,完全没有量化依据。
我需要建立一套测试体系:用可控的方式生成语音,量化评估音生文模型的识别准确率。
二、整体架构
测试文本(texts.txt) → 音频生成器(edge-tts) → 音频文件 + 记录Excel
↓
音生文测试执行器 → 调用公司API → 识别结果
↓
5维评估器 → 综合评分 → HTML报告
| 模块 | 技术栈 | 职责 |
|---|---|---|
| 音频生成 | edge-tts + asyncio | 将文本合成为音频,记录编号、原文、关键词 |
| 测试执行 | requests + pandas | 批量调用公司音生文API |
| 评估器 | Python + 正则 | 5维度评分(关键词、BLEU、长度、重复) |
| 报告生成 | HTML + CSS | 生成可视化测试报告 |
三、核心设计
1. 音频生成器(解决数据源问题)
没有真实语音数据,就用合成语音替代。edge-tts是微软的免费TTS服务,支持多种音色。
class AudioGenerator:
async def generate_with_retry(self, text, voice_name, filename):
for attempt in range(self.max_retries):
try:
communicate = edge_tts.Communicate(text, voice_name)
await communicate.save(temp_filepath)
# 检查文件大小
if file_size <= self.max_size:
return True
except Exception as e:
await asyncio.sleep(2 ** attempt)
return False
关键设计:
-
固定编号(
Xiaoxiao_001.mp3),覆盖模式,每次运行结果一致 -
生成后记录到Excel(编号、原文、关键词、音频路径)
-
支持断点续传,已存在的文件自动跳过
2. 测试用例管理(从Excel读取)
音频生成后,audio_records.xlsx成为测试用例的唯一数据源:
| 编号 | 原文本 | 关键词 | 音频路径 |
|---|---|---|---|
| 01-001 | 今天天气真不错,我们去公园散步吧。 | ["天气","散步"] | output\Xiaoxiao_001.mp3 |
| 01-002 | 你吃饭了吗?我刚吃完午饭。 | ["吃饭","午饭"] | ... |
def get_voice_test_cases():
df = pd.read_excel("audio_records.xlsx", sheet_name='音频记录')
cases = []
for _, row in df.iterrows():
case_id = int(row['编号'].replace('-', ''))
cases.append((case_id, row['编号'], row['原文本'], eval(row['关键词'])))
return cases
3. 公司音生文API适配
class VoiceToTextTranslator(BaseTranslator):
def translate(self, audio_id: str) -> str:
# 根据编号找到音频文件
audio_path = self._get_audio_path(audio_id)
# 调用公司API
with open(audio_path, 'rb') as f:
response = requests.post(
self.voice_to_text_url,
files={'file': (filename, f, 'audio/mpeg')},
headers=self.headers
)
return response.json()['content']['transcription']
4. 复用5维评估体系
与AI翻译框架共用评估器,核心指标不变:
| 指标 | 权重 | 作用 |
|---|---|---|
| 关键词命中 | 0.35 | 确保核心业务词汇被正确识别 |
| BLEU语义 | 0.50 | 字符级匹配准确率 |
| 长度比率 | 0.07 | 防止漏译或过度发挥 |
| 重复惩罚 | 0.08 | 检测是否出现重复内容 |
四、测试文本设计
按照场景分类,覆盖员工真实可能说的话:
| 类别 | 示例 | 数量 |
|---|---|---|
| 日常对话 | “今天天气真不错,我们去公园散步吧。” | 2 |
| 数字相关 | “我的手机号是138-1234-5678,微信同号。” | 5 |
| 专业术语 | “医生说我得了高血压,需要每天吃一片5mg的降压药。” | 4 |
| 中英文混合 | “我正在学习Machine Learning和Deep Learning。” | 4 |
| 长文本故事 | 白雪公主、三个儿子等 | 4 |
| 新闻报道 | 北斗卫星发射 | 1 |
| 客服对话 | 银行客服模拟 | 1 |
| 复杂句式 | “虽然天气预报说今天会下雨,但是我觉得应该不会下” | 4 |
| 容易混淆的词语 | “化肥会挥发,黑化肥发灰” | 4 |
| 情感表达 | “哇!这个礼物太漂亮了” | 4 |
共计32条测试语句,覆盖日常、数字、专业、长文本、边界情况等。
五、测试结果
首次运行,32条用例,通过率75.0%,综合得分0.50。
发现的问题
| 问题类型 | 示例 | 表现 |
|---|---|---|
| 数字转换错误 | “138-1234-5678” | 识别为“幺三八幺二三四五六七八”,数字被逐字转成中文读音 |
| 专业术语错误 | “Machine Learning” | 识别为“那是拉尼”,完全错误 |
| URL/邮箱处理 | “github.com/username” | 识别为“贝卡点抗斜杠优瑟连斜杠”,乱码 |
| 长文本遗漏 | 长篇故事 | 内容丢失严重 |
| 数字单位错误 | “5mg” | 识别为“五毫克”,正确但格式不符合预期 |
优化后
根据报告反馈给算法团队,针对性优化了业务词汇权重。第二次运行:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 通过率 | 75.0% | 93.8% |
| 综合得分 | 0.50 | 0.78 |
| 失败数 | 8条 | 2条 |
剩余2条失败主要集中在中英文混合和URL识别,后续继续优化。
六、踩坑记录
坑1:edge-tts生成失败
网络波动导致生成失败。
解决:添加重试机制(最多7次),指数退避(1s、2s、4s...)。
坑2:音频文件过大
长文本生成的音频超过5MB。
解决:生成后检查文件大小,超过限制自动删除并标记失败,后续优化切分策略。
坑3:Excel关键词解析失败
audio_records.xlsx的关键词列存储为字符串"['天气','散步']",直接读取是字符串不是列表。
解决:用ast.literal_eval()安全解析。
坑4:音生文API需要上传文件而非传递路径
API设计是接收文件流,不是路径。
解决:每次请求用open(filepath, 'rb')重新打开文件,用files参数上传。
坑5:音频生成覆盖模式
每次运行generate.py都会重新生成所有音频,浪费时间和API配额。
解决:添加文件存在检查,已存在的文件跳过生成,只生成新增的文本。
七、总结
这套框架的核心价值:
-
解决数据困境:用合成语音替代真实录音,测试数据完全可控、可复现
-
量化评估:从“凭感觉”变成“通过率93.8%、综合得分0.78”
-
可回归:模型升级后,跑一次就知道效果变化
-
框架复用:评估体系直接复用了AI翻译的5维指标
核心思想:先用AI合成语音建立测试基线,排除“输入信号质量”这个变量,精准定位模型本身的问题。等模型准确率稳定后,再逐步引入真实语音做鲁棒性测试。
测试报告