质检单位是应答机会
用户完成有效发言,业务状态要求 AI 回答,但观察窗内没有可听 AI 语音。不是泛化的“静音片段”。
AI Voice Quality Assurance · Special Research
从波形症状走到可运营的“应答机会”检测:工程规则负责计时与召回,ASR / 大模型负责语义排误报,链路日志负责根因。
仅凭录音可以发现“疑似无声症状”,不能证明根因在 EOU、ASR、LLM、工具、TTS、RTP、播放器还是录音器。根因确认需要组件与播放侧事件。
01 · Executive decision
本轮没有找到一个成熟、通用、可直接端到端判定该缺陷的开源仓库。可靠组件分别解决分轨、VAD、ASR、说话人分离、标注和运行时观测;最终需要组装业务状态机。
用户完成有效发言,业务状态要求 AI 回答,但观察窗内没有可听 AI 语音。不是泛化的“静音片段”。
录音是否分轨、通道映射是否可信、是否能取得 Agent / TTS / RTP / 播放日志。它们决定准确率和归因上限。
VAD / 规则全量初筛,ASR + 文本 LLM 语义复核,音频 LLM 只看疑难短片段,人工负责金标与边界。
规则为主,LLM 只复核歧义;可检测并大概率定位根因。
VAD + ASR + 文本 LLM 可高质量发现症状,但根因只能标为未知。
Diarization + 角色映射 + ASR + 规则;必须允许 role_uncertain,不能强制二选一。
02 · Detection contract
response_gap_ms = first_ai_audible_speech_ms - user_turn_end_msright_censored = true;不能把失败样本从延迟分母删除。confirmed_silent_failure日志确认系统应答,但播放侧/录音中没有 AI 可听语音。suspected_silent_failure用户有效话轮后,观察窗内没有检测到 AI 语音;仅代表症状。delayed_ai_responseAI 最终出声,但超过当前业务阶段阈值。valid_no_response告别挂机、转人工、显式等待、取消或无需回答。user_incomplete_or_backchannel用户未说完,或只是“嗯 / 啊”等附和。non_speech_trigger咳嗽、键盘、铃声、音乐、底噪触发能量或 VAD。role_uncertain单轨分离后无法稳定判断用户 / AI;应弃权或送人工。recording_or_channel_defect整段 AI 轨缺失、全零、错映射、截断或编码异常。03 · Five viable routes
| 现有数据 | 推荐方案 | 能达到的结论 | 主要风险 |
|---|---|---|---|
| 用户 / AI 双轨 + 全链路日志 | 分轨 VAD + 状态机 + 日志瀑布 | 检测并大概率定位根因 | 时钟不同步、播放起音未埋点 |
| 双轨、无日志 | 分轨 VAD + ASR + 语义规则 | 高质量症状检测 | 无法区分 LLM / TTS / RTP 根因 |
| 单轨 + 固定 AI 音色参考 | Diarization + speaker verification + ASR | 映射角色后检测 | 回声、串音、变声、多人用户 |
| 单轨、无音色参考 | Diarization + 结构映射 + LLM | 带置信度候选 | speaker 标签翻转、重叠、短句 |
| 仅有转写 | 文本 LLM 判断是否应答 | 发现流程 / 语义异常 | 不能证明 AI 是否真的出声 |
FFprobe / FFmpeg 体检与分轨 → Silero VAD → 合并短间隙 → 用户话轮后搜索 AI 首个人声 → JSONL + 复核片段。CPU 可批跑、可解释、隐私最好;但只能报症状。
pyannote.audio、WhisperX 或 FunASR 生成匿名 speaker 时间线;再用固定音色、开场白或元数据映射角色。无法稳定映射就输出 role_uncertain。[S4][S5][S6]
LLM 只判断完整问题、告别、附和、转人工、显式等待等“是否应答”语义,输出固定枚举;不让它生成波形时间、speaker 真值或媒体根因。
只发送用户开口前 1 秒到结束后 5–10 秒的候选窗口。OpenAI gpt-audio-1.5 或本地 Qwen3-Omni 可判断人话 / 提示音 / 预期回复,但不替代 VAD 和通道真值。[S7][S8]
规则保召回和复算,ASR / 文本 LLM 降低语义误报,音频 LLM / 人工解决歧义,T0–T10 日志负责根因与 owner 路由。
04 · Recommended production architecture
若能重新导出数据,优先争取:用户与 AI 分轨、单调时钟时间戳、Agent 生成与播放事件、通道定义、固定 AI 音色的 2–10 秒干净参考片段。OpenAI 当前 diarized transcription 可用已知说话人参考,但仍要在本方样本验证角色与切段。[S9]
05 · GitHub stack & implementation
| 组件 | 用途与价值 | 不能替代什么 |
|---|---|---|
| FFmpeg [S1] | 分轨、重采样、全零 / RMS / 静音与格式体检 | 不是人声、角色或语义检测 |
| Silero VAD [S2] | 8k / 16k 人声区间,CPU 全量初筛,MIT | 不分 speaker,不判断完整话轮 |
| faster-whisper [S3] | 离线多语种 ASR、词时间戳、量化与 VAD | 不自带可靠业务角色 |
| WhisperX [S4] | ASR + 强制对齐 + pyannote diarization | 重叠语音和 diarization 有公开限制 |
| pyannote.audio [S5] | speaker change / overlap / embedding / diarization | speaker ID 不等于用户 / AI |
| FunASR [S6] | 中文 ASR、FSMN-VAD、标点、CAM++ speaker | 模型权重许可证需逐项核查 |
| TEN VAD [S14] | 16k、ONNX / C / Python / WASM,可做对照 | 项目方结果需独立复测 |
| whisper.cpp [S15] | Apple Silicon / 低依赖离线批处理 | 仍只是 ASR / VAD 组件 |
| librosa split [S16] | 快速非静音能量基线 | 不是人声 VAD |
| Qwen3-Omni [S7] | 本地音频理解与疑难候选解释 | 部署重,不是确定性计时器 |
| OpenAI Audio / diarize [S8][S9] | 云端音频理解、speaker-labeled 转写 | 数据出域、成本与供应商依赖 |
| Label Studio [S17] | 候选片段、speaker 与 ASR 人工标注 | 不是自动检测器 |
schema_version: 1 call_id: c_20260831_00017 recording_path: recordings/c_00017.wav recording_sha256: ... channel_layout: stereo user_channel: 0 agent_channel: 1 call_start_epoch_ms: 1788140000000 locale: zh-CN workflow: after_sales_refund agent_voice_ref: refs/agent_voice.wav trace_path: traces/c_00017.jsonl
未知字段留空,不能用默认值伪造真值;每批先抽样确认左右通道映射。
for user_turn in merge_user_vad_segments(user_segments, config):
if not acoustic_user_qualified(user_turn):
continue
observation_end = min(
next_user_turn_start(user_turn) or call_end,
hangup_time or call_end,
user_turn.end + config.max_observation_ms,
)
first_agent = first_agent_speech(
start=user_turn.end + config.post_user_guard_ms,
end=observation_end,
)
gap_ms = (first_agent.start if first_agent else observation_end) - user_turn.end
if gap_ms >= phase_threshold(call_state):
emit_for_asr_and_semantic_review(...)生产实现还需合并极短 VAD 间隙、单独处理 barge-in、保存用户重复开口证据、区分提示音 / hold music / 真人接管,并把阈值配置版本化。
{
"event_type": "voice_agent.suspected_silent_failure",
"call_id": "c_20260831_00017",
"turn_id": "t_06",
"phase": "after_user_speech",
"user_end_ms": 42180,
"observation_end_ms": 45940,
"first_agent_speech_ms": null,
"gap_ms": 3760,
"expected_ai_response": true,
"acoustic_confidence": 0.97,
"role_confidence": 1.0,
"semantic_confidence": 0.88,
"reason_codes": ["complete_user_question", "no_agent_vad", "next_user_reprompt"],
"detector_version": "dead-air-v0.1.0",
"review_status": "pending"
}只用 RMS == 0:底噪、压缩噪声和舒适噪声会让 dead air 非零。
只看整通静音比例:关键话轮会被平均值淹没。
只看转写是否为空:ASR 空文本不等于用户没说话。
把 speaker_0 固定为 AI:编号无业务语义且会跨文件翻转。
整通丢给音频 LLM:成本高、时间定位不稳、难复算。
AI 轨有能量就算回答:提示音、音乐、回声也会误通过。
06 · Community evidence & root cause
以下 GitHub issues 是单个用户报告或维护者讨论,只能证明失败模式存在,不能当作发生率或模型排名。
气流被判为 voice;8k 窄带电话在安静背景误触发、强噪声漏检。保存能量、VAD、ASR 三组独立证据。[S18][S25]
faster-whisper 与 Whisper 讨论了 VAD / 静音附近的 hallucination;文字产出不能覆盖声学真值。[S19][S20]
背景噪声和长静音配置可能让 STT commit 延迟 10–15 秒;应先查 TURN_NOT_COMMITTED。[S23][S24]
重叠检出和按整句多数 speaker 分配会退化;barge-in 与 fast turns 必须单独分桶。[S21][S29]
请求正常结束、有 token,却没有 text frame、TTS 和最终音频;最终指标必须落到 audible onset。[S26]
多声道处理误留一轨,会让人声概率异常低;缺轨 / 换轨应进入回归测试。[S28]
| 时间点 | 事件 | 初步归因 |
|---|---|---|
| T0 | user_acoustic_end | 声学起点真值 |
| T1 | vad_speech_stopped | VAD / 噪声 / 阈值 |
| T2 | eou_commit | endpointing / 状态机 |
| T3 | asr_final | ASR final / 连接 |
| T4 | llm_request | 编排是否启动 |
| T5 | llm_first_token | 模型 / 限流 / Prompt |
| T6 | tool_end | CRM / API / 重试 / 超时 |
| T7 | tts_first_audio | TTS 供应商 / 连接 |
| T8 | downstream_first_rtp | 媒体网关 / 编码 |
| T9 | playout_or_audible_onset | 播放队列 / 静音 / 设备 |
| T10 | 录音 AI 轨首次人声 | 录音器与最终可见证据 |
FFmpeg + Silero VAD 成本最低、隐私最好;ASR / diarization 只对候选或按需全量。工具许可证不自动覆盖模型权重与 gated 条款;pyannote 遥测配置应纳入审计。
录音可能含声纹与 PII。优先上传脱敏短候选,使用短时对象权限;保存模型快照、提示词、结构化输出和失败状态,并按当日合同核对区域、留存与训练使用。
07 · Gold set, metrics & rollout
金标单位同样是“应答机会”。随机正常通话、规则候选、困难负样本、真实事故和投诉要同时进入抽样;开发 / 校准 / 隐藏集按完整 call_id 切分。
补充报告:calls with ≥1 failure、false positives / 100 calls 或 / audio hour、delayed-response 检出率、gap 时间误差、仅在有日志真值时的 root-cause accuracy、RTF、CPU/GPU 小时、云 API 成本 / 音频小时。
role_uncertain 和解析失败不从分母消失08 · Sources
官方能力、项目自报与社区个案分层呈现;社区 issue 不代表发生率。
按音量阈值与持续时间检测静音,支持逐通道元数据。
MIT;8k / 16k、PyTorch / ONNX 与人声时间戳。
CTranslate2 Whisper、批处理、词级时间戳与 Silero VAD。
强制对齐、词时间戳、pyannote diarization 及公开限制。
说话人分离、重叠、embedding、DER benchmark 与遥测配置。
ASR / VAD / 标点 / speaker pipeline 与中文相关模型。
音频输入、理解、描述与混合音频分析。
音频输入 / 输出与 Realtime 架构。
Diarized JSON、已知说话人参考与长录音分块。
普通转写、speaker labels、词时间戳和字幕的模型分工。
Silence Detected 的缺 RTP / 一方全静音定义。
VAD、STT endpointing 与语义 / 声学话轮检测。
噪声对 VAD endpointing 的影响与启发式边界。
16k VAD 与 ONNX / C / Python / WASM 接口。
C / C++ Whisper、Apple Silicon 加速、量化与 VAD。
按相对峰值阈值返回非静音区间。
音频区域、说话人和转写人工标注模板。
已标注 deprecated / no longer maintained,仅作历史参考。
2026-06-27;话轮定义、starter threshold、根因矩阵与事件 schema,属厂商实践。
吹气 / 麦克风气流触发 VAD 的用户报告。
VAD / ASR 与 hallucination 边界讨论。
跳过疑似幻觉附近静音的改动与讨论。
重叠说话检出的用户报告。
号码 / 邮箱场景中的 endpoint delay 与误切权衡。
用户停说后 turn 迟迟不提交与双 VAD 权衡。
8k 窄带电话误触发 / 漏检及版本跟进。
LLM 请求结束却无 text / TTS / 可听回复的日志个案。
确定性 validator 先于 LLM Judge 的项目设计提案。
多声道只保留一轨导致检测异常的用户自查。
快速话轮按整句多数 speaker 分配退化的用户报告。