口语发音评测(SOE)技术分册 · GOP / wav2vec2 / 商用 SDK¶
用途:为「跟读评测」服务提供发音打分能力(用户跟读 → ASR 对齐 → 音素级打分 → JSON 报告);同时说清开源方案的边界,避免把研究代码当产品用。 环境:Windows Server 宿主机,2×Xeon Gold 6138(40 核 / 80 线程)、256GB 内存、F 盘 895G(剩余 862G);无独立 GPU,纯 CPU 推理。所有服务以 Docker 容器部署,产物只落
F:\EricLiu\,模型权重放labs\models\。 版本基线:OpenPronounce v0.4.0(2026-11-09)|Kaldiegs/gop_speechocean762(recipe 随 Kaldi 主干)|CTC-based-GOP(INTERSPEECH 2024)|speechocean762 语料(SLR101,5000 句)|商用侧 Azure Pronunciation Assessment、讯飞 ISE、腾讯云智聆 SOE、驰声 Chivox(核对日期 2026-11-11,来源:官网/GitHub)
0. 现状核实结论(先看这段,避免走错路)¶
结论:开源"完整产品"极少,绝大多数是论文研究代码。截至目前,能直接 pip install 上手、且带 HTTP 接口和 Docker 的口语评测开源项目,实际只有 OpenPronounce 一个。
核实到的可用实现:
| 实现 | 形态 | 语言 | 成熟度 | 能否直接用 |
|---|---|---|---|---|
| OpenPronounce(Halleck45) | pip 包 + FastAPI + Docker + Web UI | 英语(另有 6 语种实验性) | ★★★★ 有版本、有 benchmark、有 CI | ✅ 本机首选,CPU 可跑 |
Kaldi egs/gop_speechocean762 |
Kaldi recipe(需自己编译 Kaldi) | 英语 | ★★★ 官方 baseline,PCC 0.45 | ⚠️ 教学价值高,工程化成本高 |
| CTC-based-GOP(NTNU, INTERSPEECH 2024) | 论文代码 + 脚本 | 英语 | ★★ 研究代码 | ⚠️ 需自己拼流水线 |
| gopt(YuanGongND) | 研究代码(GOPT Transformer) | 英语 | ★★ 研究代码 | ⚠️ 偏论文复现 |
| Si-Tones(laoszu) | Conformer-CTC + AISHELL-1 + GOP 思路 | 中文(拼音) | ★ 早期项目 | ⚠️ 只能作为中文方案起点 |
| 商用:Azure / 讯飞 ISE / 腾讯云 / 驰声 | SaaS API | 中英及多语种 | ★★★★★ | 需付费,本库只做对比,不代注册 |
三个必须提前讲清的事实 1. 中文开源 SOE 基本是空白。公开标注语料只有英语的 speechocean762(且说话人是中国学习者);中文要自己解决"拼音音节 + 声调"的音素集与打分标准问题,没有公认开源基线。 2. 开源方案给的是"相对分",不是"考试分"。OpenPronounce 在 speechocean762 上与人类评分的 Spearman ρ≈0.65(按说话人 0.83),属于"可用反馈",不能用于认证、发证、分级考试。 3. 本机无 GPU 不影响 SOE。SOE 用的 wav2vec2-large 是 3 亿参数级模型,CPU 单句 1-3 秒,是语音链路里最不吃算力的一环。真正的瓶颈是"没有中文标注数据",不是算力。
1. 技术路线对比¶
1.1 三条路线¶
| 维度 | ① 传统 GOP(GMM/DNN/HMM) | ② wav2vec2 / CTC 端到端 | ③ 商用 SDK |
|---|---|---|---|
| 代表实现 | Kaldi gop_speechocean762(TDNN nnet3) |
OpenPronounce、CTC-based-GOP、GOPT | Azure PA、讯飞 ISE、腾讯云智聆 SOE、驰声 |
| 核心原理 | 母语声学模型前向得帧后验 → 强制对齐 → 算"期望音素后验 vs 最强竞争音素后验"的差 | 自监督表征 + CTC 音素识别,用后验或嵌入距离打分,可免强制对齐 | 厂商自研(多为 DNN/HMM + 大规模母语/学习者数据 + 专家标定) |
| 是否需要强制对齐 | 必须(GOP 的定义依赖音素边界) | 可选(CTC 后验可直接按帧取;OpenPronounce 用编辑距离对齐替代) | 不需要,黑盒 |
| 是否需要音素词典 | 必须(lexicon / LG FST) | 需要发音词典做"期望音素串"(espeak-ng / CMUdict / pypinyin) | 不需要 |
| 中文支持 | 需自建拼音音素集 + 声调建模 | 同上,缺标注数据 | ✅ 完整(声母/韵母/声调) |
| 可解释性 | ★★★★★ 每个音素的 GOP 值可追溯 | ★★★☆ 后验/嵌入距离,可解释性中等 | ★★ 只给分数与错误类型 |
| 冷启动成本 | 高(编译 Kaldi、训 TDNN、训 SVR) | 中(下模型、拼流水线) | 低(一个 API Key) |
| 本机 CPU 可行性 | ⚠️ 可行但重(Kaldi 编译 + 特征提取慢) | ✅ 可行(单句 1-3s) | ✅ 但走公网 |
| 典型精度 | baseline:GOP 特征 + SVR,MSE 0.16 / PCC 0.45(音素级 0-10 分) | OpenPronounce:句级 ρ=0.65(对 speechocean762 人工总分) | 商用最佳,无公开可比口径 |
GOP 的定义(Witt & Young, 2000)——理解这一行,就理解了整个传统路线:
GOP(p) = log P(p | O) − max_{q ≠ p} log P(q | O)
O 是该音素对齐到的帧区间,p 是词典里的期望音素,q 遍历其它音素。
含义:"这段音频像 p 的程度,比像最强竞争对手 q 的程度高出多少"。差值为 0 或负 → 大概率发错;差值大 → 发音清晰。工程上再把这个标量(或它的分段统计 LPP/LPR)喂给每个音素一个回归器(Kaldi recipe 用 SVR),映射到 0-10 的人类评分。
1.2 商用 SDK 能力对比(只比能力,不代注册、不代调用)¶
| 能力 | Azure Pronunciation Assessment | 讯飞 ISE | 腾讯云智聆 SOE | 驰声 Chivox |
|---|---|---|---|---|
| 评分维度 | Accuracy / Fluency / Completeness / Prosody(+ 非脚本模式的 Content:词汇/语法/话题) | 准确度、流利度、完整度、声调、音素级 | 精准度、流利度、完整度(PronCompletion)、音素级 PhoneInfos |
总分 + 声母/韵母/声调,对齐 PSC 普通话水平测试口径 |
| 粒度 | 句 / 词 / 音素(可选 viseme) | 句 → 词 → 音节 → 音素 四层 | 句 / 词 / 音素(起止时间、重音标记) | 字 / 词 / 句,中文按拼音拆解 |
| 中文声调 | 支持,但社区反馈中文声调维度弱于国内厂商 | ✅ 强项 | ✅ 支持 | ✅ 核心卖点(mā/má/mǎ/mà 级) |
| 接入方式 | REST / SDK(key 或 Entra ID) | WebSocket 流式为主 | HTTP / WebSocket | HTTP + MCP Server(可直连 LLM 工具链) |
| 音频限制 | 15s(短音频)/ 流式更长 | 分题型 | 段落/自由说 ≤300s,其余 ≤60s | 按题型 |
| 语言覆盖 | 多语种,Prosody/Content 仅 en-US | 中英为主 | 中英 | 中英,考试口径(IELTS/TOEFL/PSC) |
| 计费量级 | 按音频时长 | 按次(第三方公开数据:20 万次套餐约 ¥0.006/次) | 按次/套餐 | 注册赠 600 次,之后按成功调用计费 |
| 数据合规 | 音频出境需评估 | 国内 | 国内 | 国内,宣称评测后删音频 |
结论:做产品 → 商用 SDK;做学习/内网/零成本 → 开源。 本库实验一律走开源,商用只做对比说明(这也是 Roadmap 阶段 B 的既定规则)。
1.3 选型决策¶
要中文、要考试级口径、能付费? ── 是 ──> 商用 SDK(讯飞/驰声/腾讯云)
│ 否
↓
英语跟读、要今天就能跑? ── 是 ──> OpenPronounce(CPU,pip 一行)
│ 否
↓
中文、必须自研? ──> 自己拼:pypinyin 音节+声调 → CTC 音素模型 → GOP/后验打分
(参考 Si-Tones 思路,做好"没有标注集"的心理准备)
1.4 推荐结论¶
- 首选 = OpenPronounce v0.4.0(MIT,纯 CPU):目前唯一"pip 一行 + 自带 FastAPI/Docker/Web UI"的开源 SOE,句级 ρ≈0.65 足以做练习反馈(不是考试分,官方亦明示 CPU 可跑)。
- 选配 = Kaldi
egs/gop_speechocean762:只想理解 GOP 原理或做学术复现时用;它是研究 recipe(PCC 仅 0.45,需自编译 Kaldi + 训 TDNN/SVR),不是产品。 - 商用对照 = 讯飞 ISE / 腾讯云智聆 SOE / 驰声(Azure PA 补多语):要考试级口径、中文声调、四层粒度只能走商用;本库只做能力对比、不代注册不代调用。
- 回避 = 把研究代码当生产、给中文硬套英语阈值:GOPT/Si-Tones 等仅作起点;中文没有公开标注集,必须先自建"拼音音节 + 声母/韵母/声调"评测集并标定,否则不得对外宣称支持中文评分。
2. 最小跑通路径:OpenPronounce(EB3-1)¶
2.1 为什么选它¶
- MIT 许可,可改可商用(商用仍需自评效果)。
- 纯 CPU,官方明示 "Runs on your machine, on CPU"。
- 自带 HTTP 服务,有
POST /pronunciation、GET /health、GET /docs,与我们的服务化规范天然对齐。 - pipeline 完整:音素识别 → 编辑距离对齐 → CTC 后验置信度 → DTW 声学距离 → 韵律曲线 → 0-100 分。
代价:模型不小(两个 wav2vec2-large,各约 1.2GB),首次运行要下 2.4GB;中文未标定。
2.2 安装(二选一)¶
方式 A:pip(最快,宿主机 venv)
python -m venv F:/EricLiu/Envs/openpronounce
F:/EricLiu/Envs/openpronounce/Scripts/activate
# 关键:先装 CPU 版 torch,体积小一半以上
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install openpronounce
# 系统依赖:ffmpeg(解码任意音频)+ espeak-ng(音素化)
# Windows 用 winget / choco 安装后确认在 PATH 里:
ffmpeg -version
espeak-ng --version
方式 B:Docker(服务化用)
cd F:/EricLiu/AppDocs/SOE/labs/src
git clone https://github.com/Halleck45/OpenPronounce.git
cd OpenPronounce
docker build -t local/openpronounce:0.4.0 .
docker run -d --name soe -p 8102:8000 \
-e OPENPRONOUNCE_DEVICE=cpu \
-e OPENPRONOUNCE_TTS=piper \
-e OPENPRONOUNCE_TTS_VOICE=en_GB-cori-medium \
-v F:/EricLiu/AppDocs/SOE/labs/models/hf:/root/.cache/huggingface \
local/openpronounce:0.4.0
OPENPRONOUNCE_TTS=piper让"参考音"离线合成(默认 gTTS 需要联网);但注意 Piper 音色会改变声学距离的基准,换引擎后要为该引擎重新校准(官方文档实测:换 Piper 会让好朗读的声学距离上移 1-2,分数略偏低)。
2.3 验证(EB3-1 判据)¶
# CLI 一行验证
openpronounce F:/EricLiu/AppDocs/SOE/labs/EB3-1-first-run/record.wav \
"Hello, how are you?" --json --no-prosody
期望输出结构:
Score : 59.0/100
Transcription: HELL NO WHO ARE YOU
Mispronounced:
- hello: expected /həloʊ/, heard /hɛlnoʊ/ (confidence 89%)
- how: expected /haʊ/, heard /hu/ (confidence 50%)
# HTTP 验证
curl -s localhost:8102/health
curl -s -X POST localhost:8102/pronunciation \
-F "file=@record.wav" \
-F "expected_text=Hello, how are you?" \
-F "lang=en" | python -m json.tool | head -40
判据:CLI 输出 0-100 分 + 至少一个 words 级错误项;/health 返回 200;同一段音频重复跑分数稳定(±2 内)。
2.4 耗时与内存(本机估算,首次跑完请回填实测)¶
| 环节 | CPU 耗时(估算) | 说明 |
|---|---|---|
| 首次启动(下模型) | 2.4GB / 视带宽 5-30 分钟 | 之后走本地缓存,HF_HUB_OFFLINE=1 可断网 |
| 模型加载到内存 | 10-30s | 常驻进程只付一次 |
| 单句分析(5-10s 音频) | 2-6s | = 音素识别 + 词识别 + 参考音合成 + DTW + pYIN |
| 常驻内存 | 3-5GB | 两个 wav2vec2-large + torch |
| 并发 | 1 路/容器 | CPU 上别开多线程并发,靠多副本扩 |
3. 评测流水线设计(EB3-2)¶
3.1 架构¶
┌─────────────────────────────────────────────┐
句子文本 ──────────▶│ ① 文本前端:分词 + 音素化(拼音/CMU/espeak) │
└───────────────┬─────────────────────────────┘
│ 期望音素序列 P_ref
麦克风/上传 ──▶ ② 规整:重采样 16k 单声道、去首尾静音、峰值归一
│
▼
┌─────────────────────────────────────────────┐
│ ③ 声学模型:CTC 音素后验 / 强制对齐边界 │
└───────────────┬─────────────────────────────┘
│ 帧后验 + 音素边界
▼
┌─────────────────────────────────────────────┐
│ ④ 打分:GOP(p) → 音素分 → 词分 → 句分 │
│ 辅以:PER/WER、DTW 声学距离、韵律(F0/能量)│
└───────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ ⑤ 聚合与反馈:错音定位 + 建议 + JSON 报告 │
└─────────────────────────────────────────────┘
3.2 各环节要点¶
| 环节 | 做法 | 坑 |
|---|---|---|
| ① 文本前端 | 英文 CMUdict/espeak;中文 pypinyin 取带声调拼音,再拆声母/韵母/声调三元组 | 多音字必须按上下文取音("银行/行走") |
| ② 规整 | 统一 16kHz/16bit/单声道;ffmpeg -ar 16000 -ac 1;VAD 掐头去尾 |
采样率不对 → 后验全错;不归一化 → 音量小的被判"没发出来" |
| ③ 声学 | 优先 CTC 音素模型(wav2vec2 微调);传统法需 nnet3 TDNN + LG FST 强制对齐 | Kaldi 的 chain 模型不适合算 GOP(官方 recipe 明确用 no-chain TDNN) |
| ④ 打分 | 音素 GOP → 词内加权 → 句内加权;再与流利度/完整度融合 | 单词过短(<3 音素)GOP 噪声大,需要置信度衰减 |
| ⑤ 反馈 | 只报"高置信度错误",宁缺勿滥 | 假阳性比漏报更伤学习体验 |
3.3 JSON 报告契约(服务间统一格式)¶
{
"request_id": "20261111-0001",
"lang": "en",
"reference_text": "Hello, how are you?",
"asr_transcript": "HELL NO WHO ARE YOU",
"scores": {
"overall": 59.0,
"accuracy": 62.5,
"fluency": 70.1,
"completeness": 100.0,
"prosody": null
},
"metrics": {
"phoneme_error_rate": 0.21,
"word_error_rate": 0.25,
"acoustic_distance": 12.4
},
"words": [
{
"word": "hello",
"position": 0,
"score": 31,
"expected_ipa": "h ə l oʊ",
"heard_ipa": "h ɛ l n oʊ",
"phones": [
{"expected": "ə", "heard": "ɛ", "confidence": 0.89, "gop": -1.42},
{"expected": "oʊ", "heard": "n oʊ", "confidence": 0.55, "gop": -0.31}
]
}
],
"prosody": {"f0_mean": 118.3, "f0_range": [82.1, 191.4], "energy_rms": 0.071},
"engine": {"name": "openpronounce", "version": "0.4.0", "device": "cpu"},
"elapsed_ms": 3180
}
字段命名对齐 OpenPronounce 原生输出(
score/differences.errors[]/acoustic_distance/prosody.f0),外层再包一层统一信封,便于后续换引擎(商用 SDK)时上层不改。
3.4 编排骨架(可直接改成 assess.py)¶
"""跟读评测编排:音频 → 规整 → 音素打分 → JSON 报告。
依赖:openpronounce(音素识别/对齐/打分)、faster-whisper(可选,要词级时间戳时用)。
"""
import json
import subprocess
import tempfile
from pathlib import Path
from openpronounce import load_audio, compare_audio_with_text
def to_wav16k(src: str | Path) -> Path:
"""统一成 16kHz/16bit/单声道 —— 采样率错了后面全错。"""
dst = Path(tempfile.mkdtemp()) / "norm.wav"
subprocess.run(
["ffmpeg", "-y", "-i", str(src), "-ar", "16000", "-ac", "1",
"-af", "silenceremove=start_periods=1:start_threshold=-45dB",
str(dst)],
check=True, capture_output=True,
)
return dst
def assess(audio_path: str, expected_text: str, lang: str = "en") -> dict:
wav = to_wav16k(audio_path)
sound = load_audio(str(wav)) # 内部已重采样为 16k mono
raw = compare_audio_with_text(sound, expected_text, lang=lang)
errors = raw.get("differences", {}).get("errors", [])
words = [{
"word": e["word"],
"position": e.get("position"),
"expected_ipa": e.get("expected"),
"heard_ipa": e.get("actual"),
"confidence": round(float(e.get("confidence", 0)), 3),
"phones": e.get("phones", []),
} for e in errors]
# 置信度过滤:低于 0.5 的错误不报,减少假阳性(教学体验优先)
words = [w for w in words if w["confidence"] >= 0.5]
return {
"lang": lang,
"reference_text": expected_text,
"asr_transcript": raw.get("transcribe"),
"scores": {
"overall": round(float(raw["score"]), 1),
"accuracy": None, # 开源版没有独立 accuracy,留空待融合
"fluency": None,
"completeness": None,
"prosody": None,
},
"metrics": {
"phoneme_error_rate": raw.get("differences", {}).get("phoneme_error_rate"),
"word_error_rate": raw.get("differences", {}).get("word_error_rate"),
"acoustic_distance": raw.get("acoustic_distance"),
},
"words": words,
"engine": {"name": "openpronounce", "device": "cpu"},
}
if __name__ == "__main__":
print(json.dumps(
assess("F:/EricLiu/AppDocs/SOE/labs/EB3-1-first-run/record.wav",
"Hello, how are you?"),
ensure_ascii=False, indent=2))
3.5 想自己算 GOP?核心只有 20 行(示意,非可直接运行)¶
import numpy as np
import torch
# posteriors: (T, V) 音素后验,来自 CTC 模型 softmax
# spans: [(p_idx, t_start, t_end), ...] 期望音素及其对齐区间
def gop(posteriors: torch.Tensor, spans, eps: float = 1e-8) -> list[dict]:
logp = torch.log(posteriors + eps)
out = []
for p, ts, te in spans:
seg = logp[ts:te] # (L, V)
if seg.numel() == 0:
continue
# 期望音素在该段的平均对数后验
target = seg[:, p].mean().item()
# 最强竞争音素(排除自身与静音)
others = seg.clone()
others[:, p] = -1e9
best_other = others.max(dim=1).values.mean().item()
out.append({
"phone_idx": int(p),
"gop": round(target - best_other, 4), # 越接近 0/负 → 越可疑
"lpp": round(target, 4), # 绝对后验,辅助判断
})
return out
真实实现还要处理:静音/停顿帧、插入与删除(对齐路径里没有对应音素)、音素时长归一化、以及对 GOP 做时长与上下文归一化后再回归到 0-10 分(Kaldi recipe 用音素级 SVR)。别自己从零写打分器,除非你准备标几千条数据。
4. 与 TTS / ASR 的集成要点(EB3-3 里程碑)¶
4.1 端到端时序¶
① 取题:题库给一句文本 S
② TTS:Piper 合成 S 的参考音 ref.wav(0.1-0.5s),缓存 key = hash(S+voice+length_scale)
③ 播放:前端放 ref.wav,用户跟读,录 user.wav(16k mono)
④ ASR:faster-whisper int8 转写 → 判断"是不是念的这句"(WER 过高直接提示重录,不进打分)
⑤ SOE:OpenPronounce 对 user.wav + S 打分 → JSON
⑥ 融合:SOE 分(发音)+ ASR WER(内容)+ 时长比(流利度)→ 最终报告
⑦ 反馈:错音高亮 + 参考音重播 + 建议("th 咬舌")
4.2 集成清单¶
| 要点 | 做法 | 原因 |
|---|---|---|
| 参考音必须缓存 | cache/{sha1(text+voice+len)}.wav |
同一句重复练,避免重复合成;也保证分数基准一致 |
| 参考音引擎固定 | 全站固定同一个 Piper 音色,勿混用 gTTS | 换引擎会让 acoustic_distance 整体偏移,分数不可比 |
| 采样率统一 16k/单声道 | 前端录音也强制 16k,服务入口再 ffmpeg 兜底 |
wav2vec2 输入固定 16k,错了结果全废 |
| 先 ASR 再 SOE | WER>0.6 直接判"未按要求朗读" | 防止"念完全无关内容"被算成发音错误 |
| 超时预算 | TTS 1s + ASR 3s + SOE 6s,总 ≤10s | CPU 现实值;超过就异步任务 + 轮询 |
| 端口规划 | TTS 8101 / ASR 8103 / SOE 8102 | 与 §TTS 分册一致,避免冲突 |
| 同网段 | docker network create ai-net,服务名互访 |
避免走宿主机 IP |
| 健康检查 | 三服务都要 /health,网关按此摘除 |
EB1-2 已定规范 |
| 音频落盘 | labs/EB3-3-follow-read/{req_id}/{ref,user}.wav |
便于复现与听感对比 |
4.3 与 ASR 分册的边界¶
| 需求 | 用谁 | 说明 |
|---|---|---|
| 只要"说了什么" | faster-whisper / FunASR | 有语言模型纠错,恰恰不适合发音评测(会把错音"纠正"成对的) |
| 要"说得准不准" | SOE 音素识别模型 | 必须关掉/绕过语言模型,直接看音素后验 |
| 要词级时间戳 | faster-whisper word_timestamps=True |
只用于定位,不用于判分 |
一句话:ASR 负责"内容对不对",SOE 负责"发音准不准",两者不可互相替代。 OpenPronounce 内部同时用了两种 wav2vec2(音素识别 + 词识别),已经隐含这个分工。
5. 排障与局限¶
5.1 排障速查¶
| 现象 | 根因 | 处理 |
|---|---|---|
espeak-ng: command not found |
系统缺音素化工具 | Windows 装 espeak-ng 并加入 PATH;Docker 镜像已内置 |
ffmpeg not found |
同上 | 装 ffmpeg,或用镜像 |
| 分数莫名很低(20-40) | 采样率/声道不对、或音量为 0 | ffprobe 查 16k/mono;加峰值归一化 |
| 所有词都报错 | 参考文本与音频语言不匹配(lang 传错) |
--lang en;中文目前不校准 |
| 分数波动大 | 短词(<3 音素)、背景噪声 | 置信度阈值提到 0.6;前端加降噪/VAD |
| 首次调用超时 | 下 2.4GB 模型 | 预下载并挂载 HF 缓存;HF_HUB_OFFLINE=1 |
| 内存爆 | 多进程各自加载模型 | 单容器单进程,副本横向扩 |
OPENPRONOUNCE_TTS=gtts 报网络错 |
默认走 Google TTS | 改 piper 或 kokoro 离线 |
| Docker 里 GPU 报错 | 镜像选错 | CPU 用 Dockerfile,GPU 才用 Dockerfile.gpu |
5.2 局限(必须向用户明说)¶
- 只有英语被人工评分校准。法/西/德/意/葡/荷为实验性,直接复用英语阈值;中文不在支持列表。
- 音素识别器本身有错误率。官方说明:干净母语朗读约 1/10 音素会错 → 短词偶发假警报。在 speechocean762 上,被它标错的词里只有 1/5 被人类评委也判为错。
- 它是"校准过的启发式",不是在学习者标注数据上训练的模型。别当考试系统用。
- 强口音、儿童、噪声会显著掉点。wav2vec2 训练集是成人朗读语音;speechocean762 里儿童占一半,这正是它的短板场景。
- 中文需要另起炉灶:pypinyin 取带声调音节 → 声母/韵母/声调三元组 → 训练中文 CTC 音素模型(可参考 Si-Tones 用 AISHELL-1 的做法)→ 自建母语者参考分布。没有标注集就没有可信分数,这是最大障碍。
- 无 GPU 的现实:本方案能跑,但别指望实时并发。10 路并发需要 ~10 个副本 ≈ 40GB 内存 + 80 vCPU,已接近宿主机红线。
- 评分不可跨引擎比较。换 TTS 参考音、换麦克风、换阈值,分数都会整体平移;只在同一配置内做纵向对比(同一个用户多次练习)。
6. AI 操作守则(本分册强制)¶
- 先声明"这是相对分"。任何给出分数的场合,都要附带"非考试级、仅供练习反馈"的说明。
- 模型下载先报体积:OpenPronounce 两个 wav2vec2 约 2.4GB;Kaldi 镜像/编译产物 5GB+;中文 CTC 模型另算。确认后再下,落
labs\models\。 - 长任务后台跑:模型下载、Kaldi 编译、批量评测(>20 条)一律后台 + 定期汇报,不阻塞对话。
- CPU 耗时先预告:单句评测按 3-6 秒报,批量按
条数 × 5s报;禁止承诺"实时"。 - 先跑 1 条再批量:批量前用 1 条已知"读对/读错"的样本验证,确认分数方向正确(读对高分、读错低分),再放大。
- 不碰商用 SDK 的注册与密钥:讯飞/腾讯云/Azure/驰声只做能力对比;用户自己要接,给文档链接即可。
- 不伪造语料:没有中文标注集就如实说"中文开源方案不成熟",不要用英语模型硬套中文再宣称"支持中文"。
- 产物留证:每次评测把
ref.wav/user.wav/report.json存到labs\E*XX-*\,报告里引用文件名。 - 改阈值要记录:置信度阈值、分数权重任何改动,写进实验报告,否则历史分数不可比。
- 失败即沉淀:踩坑与解决方式同步
AppDocs\Reusable\。
7. 参考链接与更新记录¶
- OpenPronounce:https://github.com/Halleck45/OpenPronounce | PyPI:
openpronounce - speechocean762 论文:Zhang et al., speechocean762: An Open-Source Non-native English Speech Corpus For Pronunciation Assessment, Interspeech 2021(arXiv:2104.01378)
- speechocean762 数据:https://github.com/jimbozhang/speechocean762 | OpenSLR SLR101
- Kaldi GOP recipe:https://github.com/kaldi-asr/kaldi/tree/master/egs/gop_speechocean762
- CTC-based-GOP(INTERSPEECH 2024):https://github.com/a2d8a4v/CTC-based-GOP
- GOPT:https://github.com/YuanGongND/gopt
- Si-Tones(中文,实验性):https://github.com/laoszu/si-tones
- Azure Pronunciation Assessment:https://learn.microsoft.com/azure/ai-services/speech-service/how-to-pronunciation-assessment
- 腾讯云口语评测:https://cloud.tencent.com/document/product/269/136040
- 讯飞语音评测(ISE):https://www.xfyun.cn/doc/Ise/IseAPI.html
- 驰声:https://www.chivox.com/
| 日期 | 变更 |
|---|---|
| 2026-11-11 | 建档:核实开源 SOE 现状(结论:完整产品仅 OpenPronounce)、三路线对比、OpenPronounce 最小路径、GOP 流水线与 JSON 契约 |