[低延迟端点]:完成首句保留和快速结束修正,包含ACK缓冲策略、批量读帧和主说话人端点回归测试

This commit is contained in:
mkbk
2026-06-17 22:04:25 +08:00
parent e74ec28e7d
commit a64bb86da4
15 changed files with 136 additions and 15 deletions
@@ -101,6 +101,16 @@ The controller owns one turn state machine and delegates work to provider-backed
The first implementation is a per-turn heuristic endpoint, not persistent voiceprint recognition. It extracts local PCM features from speech frames and compares future frames against the profile. If profile creation fails because the user speech is too short or too quiet, capture falls back to existing VAD silence endpoint.
## Low Latency Capture Revision
真人运行反馈显示,当前 capture 仍可能把用户第一句话开头吞掉或需要用户重复提问才能结束。本修正把低延迟 capture 作为 pipeline 内部约束:
1. `OWNER_POST_PLAYBACK_DRAIN_MS` 默认改为 `0`。ACK 播放结束后仅清掉播放期间积压在输入队列中的帧,不再主动等待并丢弃后续音频。
2. `SoundDeviceAudioTransport.read_frames()` 在拿到首帧后立即返回队列中所有可用帧,避免真实麦克风回调积压时 pipeline 逐帧追赶。
3. `OWNER_SPEAKER_PROFILE_MIN_MS` 控制临时主说话人画像最低就绪语音长度,默认 `120` ms,不再复用 `OWNER_VAD_MIN_DURATION_MS`
4. 主说话人画像就绪后,`OWNER_SPEAKER_ABSENT_MS` 是结束正式问题采集的主条件;主说话人连续缺席达到该值后直接进入 STT,不再额外等待普通 VAD 最小时长。
5. 普通 VAD 静音仍作为画像不足或音色特征不可用时的兜底,最大录音时长仍作为最终保护。
## Model Files
```text
@@ -129,6 +139,8 @@ models/
6. Real microphone VAD miss: default `OWNER_VAD_PROVIDER=hybrid` SHALL accept speech when either the local model or the energy fallback detects speech.
7. Primary speaker endpoint profile failure: fallback to VAD silence endpoint.
8. Pipeline stage failure: emit `stage_error`, recover to standby, and keep the process alive unless startup dependencies are missing.
9. Playback drain misconfiguration: negative `OWNER_POST_PLAYBACK_DRAIN_MS` remains invalid; non-zero values are treated as explicit user tuning rather than default behavior.
10. Speaker profile threshold misconfiguration: non-positive `OWNER_SPEAKER_PROFILE_MIN_MS` fails config validation.
## Testing Strategy
@@ -140,6 +152,9 @@ models/
6. Model-check test validates wake required files.
7. Pipeline event order test validates successful two-turn event sequence.
8. Primary speaker endpoint test validates that background noise or a later repeated utterance does not extend the current turn after the main speaker disappears.
9. First utterance preservation test validates that frames immediately after ACK are not discarded by post-playback drain.
10. Low-latency endpoint test validates that a short first question ends by primary speaker absence without waiting for a repeated second question.
11. Transport batching test validates that queued SoundDevice frames are returned together.
## Migration
@@ -48,6 +48,9 @@
6. 模型管理问题:已有 `models/` manifest 只覆盖 VAD/STT,不覆盖专用 KWS 模型和关键词表。
7. Pipeline 边界问题:live runtime 缺少 stage 级事件和 controller,终端输出、错误恢复、TTS 播放、STT 调用顺序散落在同一个类里,后续 GUI 桌宠无法复用稳定事件。
8. 端点问题:`HybridVadProvider` 用“本地 VAD 或能量阈值任一为语音”同时控制开始和结束,底噪偏高时会持续重置静音计数,导致录音结束慢。
9. 首句保留问题:真人验收显示唤醒应答后仍会感觉“第一句话没有获取到”,当前 ACK 后会执行 `flush_input -> read/drop -> flush_input`,默认额外丢弃 50 ms 麦克风输入,用户若紧跟提示开口会损失正式问题开头。
10. 实时消费问题:`SoundDeviceAudioTransport.read_frames()` 每次只返回一个队列帧,在音频回调批量积压时会增加 pipeline 对真实麦克风流的追帧成本。
11. 画像门槛问题:`PrimarySpeakerVadRecorder._profile_ready()` 把主说话人画像就绪阈值绑定到 `OWNER_VAD_MIN_DURATION_MS`,默认至少等待 250 ms 后主说话人端点才参与结束判断,短句用户会被迫等普通 VAD 静音或重复说话。
## 详细需求
@@ -67,6 +70,10 @@
12. Pipeline SHALL 发出稳定事件:`pipeline_started``wake_listening``wake_detected``ack_started``capture_started``speech_started``speech_ended``stt_started``transcript_final``llm_started``tts_started``playback_finished``standby_resumed``stage_error`
13. 正式问题采集 SHALL 默认使用本轮临时主说话人端点:唤醒后以正式问题开头短音频建立本轮音色画像,主说话人音色连续消失达到配置时间后结束采集。
14. 主说话人端点 SHALL 不保存长期声纹、不写音频文件、不跨进程复用音色画像。
15. ACK 后输入清理 SHALL 只清除播放期间已积压的麦克风缓冲,不得在播放结束后额外读取并丢弃新的正式问题音频;默认 `OWNER_POST_PLAYBACK_DRAIN_MS` SHALL 为 `0`
16. SoundDevice 音频输入 SHALL 支持一次读取当前队列中可用的多个帧,避免 pipeline 在真实麦克风输入积压时逐帧追赶。
17. 主说话人画像就绪 SHALL 使用独立配置 `OWNER_SPEAKER_PROFILE_MIN_MS`,默认 `120` ms;该阈值不得被 `OWNER_VAD_MIN_DURATION_MS` 放大。
18. 主说话人端点在画像就绪后 SHALL 以 `OWNER_SPEAKER_ABSENT_MS` 作为主要结束条件;主说话人连续缺席达到配置值后 SHALL 结束采集,不得额外等待普通 VAD 的最小时长门槛。
### 非功能需求
@@ -106,6 +113,8 @@
10. `OWNER_SPEAKER_SIMILARITY_THRESHOLD=0.70`:音色相似度阈值。
11. `OWNER_SPEAKER_MIN_RMS=0.012`:进入音色画像/匹配的最低能量。
12. `OWNER_CONTEXT_MODE=session_memory`:本次进程内临时上下文。
13. `OWNER_POST_PLAYBACK_DRAIN_MS=0`:ACK 或 TTS 播放完成后只 flush 已积压输入,不额外读取并丢弃新音频。
14. `OWNER_SPEAKER_PROFILE_MIN_MS=120`:主说话人画像参与端点判断的最低有效语音长度。
终端输出:
@@ -210,6 +219,9 @@ standby
3. 唤醒隔离:wake 命中后清理 VAD 状态,正式问题只从后续 frames 构建 `AudioSegment`
4. 转写显示:STT 成功后先 reporter 输出,再追加上下文,再 LLM。
5. 主说话人端点:从正式问题开头的有效语音帧提取 RMS、过零率、谱质心、谱带宽、谱滚降、谱平坦度和频带能量比例,构建本轮临时画像;后续帧相似度低于阈值且连续达到 `OWNER_SPEAKER_ABSENT_MS` 后结束采集。
6. ACK 后首句保留:播放“我在”期间允许输入队列积压,播放完成后只执行一次队列 flush 清掉播放回声,不再额外读取 `post_playback_drain_ms` 毫秒并丢弃,默认值改为 0。
7. 批量读帧:真实 SoundDevice 输入在拿到首帧后立即 drain 当前队列中所有可用帧并返回给 pipeline,使 wake、capture 和 VAD 能在同一个循环内处理积压帧。
8. 快速主说话人结束:画像就绪最低语音长度由 `OWNER_SPEAKER_PROFILE_MIN_MS` 控制,默认 120 ms;一旦画像就绪,主说话人缺席计时达到 `OWNER_SPEAKER_ABSENT_MS` 即结束,不再叠加 `OWNER_VAD_MIN_DURATION_MS`
### 数据库/状态管理变更
@@ -238,6 +250,9 @@ standby
| 唤醒应答期间用户抢说被缓冲清理吞掉 | 中 | 高 | 终端提示顺序改为“唤醒命中 -> 应答中 -> 请说出问题 -> 录音中”,用户只在应答完成后收到提问提示;默认播放后排水从 250 ms 降为 50 ms |
| 本地 VAD 对真实麦克风音量过保守 | 中 | 高 | 默认 VAD provider 改为 `hybrid`,本地模型判断和能量阈值兜底任一命中即认为有语音;保留 `local``energy` 可配置回退 |
| 能量兜底让录音无法及时结束 | 高 | 高 | 将能量兜底限制为“开始录音辅助”,结束录音优先使用主说话人音色消失和本地 VAD 静音 |
| ACK 后额外丢弃音频截断首句 | 高 | 高 | 默认 `OWNER_POST_PLAYBACK_DRAIN_MS=0`;播放结束后只 flush 已积压输入;新增首句保留回归测试 |
| 主说话人画像等待过久 | 高 | 中 | 新增 `OWNER_SPEAKER_PROFILE_MIN_MS=120`;画像就绪后主说话人缺席结束不再等待普通 VAD 最小时长 |
| 麦克风帧队列积压导致状态滞后 | 中 | 中 | `SoundDeviceAudioTransport.read_frames()` 批量返回已积压帧;新增批量读帧测试 |
| 手写音色特征不等于严格声纹识别 | 中 | 中 | 明确第一版为本轮临时主说话人端点;不承诺长期主人识别;保留后续接入 speaker embedding 模型的接口空间 |
| Pipeline 重构影响现有 CLI/测试 | 中 | 高 | 保留 `run-live` 命令和兼容类名;新增事件顺序测试、两轮回归测试和错误恢复测试 |
| 本地 KWS 增加启动加载时间 | 低 | 中 | 模型约 15 MB,启动加载一次;不在每轮重复加载 |
@@ -315,6 +330,7 @@ standby
6. `Fast user utterance endpointing`:默认 VAD provider 改为 `hybrid`,用能量阈值兜底真实麦克风音量差异。
7. `Live assistant pipeline events`:新增 stage 化事件要求,终端和后续 GUI 必须消费事件。
8. `Primary speaker endpointing`:新增本轮临时主说话人音色消失结束录音要求。
9. `Low latency capture and first utterance preservation`:新增 ACK 后不额外丢弃正式问题、批量读帧、独立画像就绪阈值和快速主说话人端点要求。
### 删除项
@@ -332,6 +348,7 @@ standby
4. M4README、真实验收、archive 和最终提交完成。
5. M5:真人验收反馈修正唤醒提示顺序、KWS 阈值和 hybrid VAD,并在门禁通过后提交。
6. M6Stage 化 pipeline、事件总线、TurnController、主说话人端点和文档验收分模块提交。
7. M7:低延迟端点与首句保留修正完成后提交,保留真人 `run-live` 验收任务,不在用户确认前归档。
估时:
@@ -26,6 +26,25 @@ The live runtime SHALL support a per-turn primary speaker endpoint mode that end
- **WHEN** the process exits
- **THEN** no primary speaker profile SHALL be stored or reused across runs
### Requirement: Low latency capture and first utterance preservation
The live runtime SHALL preserve the start of the user's formal utterance after wake acknowledgement and SHALL end capture promptly after the primary speaker stops.
#### Scenario: Acknowledgement finishes before the user speaks
- **WHEN** acknowledgement playback completes and the runtime enters capture
- **THEN** the runtime SHALL NOT perform an additional timed microphone read-and-discard window before listening for the user's formal question
#### Scenario: Queued microphone frames are available
- **WHEN** the live microphone transport has multiple frames queued
- **THEN** the transport SHALL return the available batch to the pipeline so wake and capture stages do not process stale audio one frame at a time
#### Scenario: Primary speaker profile becomes ready quickly
- **WHEN** the user starts the formal utterance after wake
- **THEN** the primary speaker endpoint SHALL use an independent profile readiness threshold no greater than the configured `OWNER_SPEAKER_PROFILE_MIN_MS` rather than waiting for generic VAD minimum duration
#### Scenario: User stops after a short first question
- **WHEN** the primary speaker profile is ready and the primary speaker disappears for the configured absence duration
- **THEN** capture SHALL close the utterance and proceed to STT without waiting for a second repeated question or generic VAD minimum duration
### Requirement: Realtime transcript terminal output
The live runtime SHALL display the recognized user utterance text in the terminal after STT succeeds and before the LLM request is sent.
@@ -46,7 +65,7 @@ The live runtime SHALL provide an audible local acknowledgement after local wake
#### Scenario: Acknowledgement playback finishes
- **WHEN** the acknowledgement playback completes
- **THEN** the runtime SHALL clear buffered microphone input captured during acknowledgement playback before starting VAD recording for the user's question
- **THEN** the runtime SHALL clear buffered microphone input captured during acknowledgement playback before starting VAD recording for the user's question and SHALL NOT discard additional post-acknowledgement user speech by default
### Requirement: Fast user utterance endpointing
The live runtime SHALL use project-local VAD capability with an energy-threshold fallback by default for user utterance endpoint detection and SHALL expose configurable silence timing so the recording stops promptly after the user stops speaking.
@@ -54,3 +54,11 @@
- [x] 7.4 实现本轮主说话人端点;前置条件:7.3 完成;验收标准:主说话人音色消失约 300 ms 后结束采集;测试要点:一次提问后背景噪声不拖尾、短暂停顿不断句、画像不足回退;优先级:P0;预计:60 分钟。
- [x] 7.5 更新 README、`.env.example`、本地 `.env` 非密钥配置;前置条件:7.2 至 7.4 完成;验收标准:运行说明匹配新 pipeline;测试要点:`--show-config` 不泄露 key;优先级:P0;预计:30 分钟。
- [x] 7.6 验证并提交“Pipeline 文档验收”模块;前置条件:7.1 至 7.5 完成;验收标准:compileall、unittest、security-check、model-check、device-check、OpenSpec strict 全通过;优先级:P0;预计:30 分钟。
## 8. 低延迟端点与首句保留修正
- [x] 8.1 更新 OpenSpec 描述首句保留和低延迟端点;前置条件:真人 `run-live` 日志确认首句/端点仍慢;验收标准:proposal/design/spec/tasks 明确 ACK 后不额外丢弃音频、主说话人画像独立阈值、批量读帧和真人验收后再归档;测试要点:OpenSpec strict;优先级:P0;预计:35 分钟。
- [x] 8.2 实现 ACK 后首句保留和 SoundDevice 批量读帧;前置条件:8.1 完成;验收标准:默认 `OWNER_POST_PLAYBACK_DRAIN_MS=0``SoundDeviceAudioTransport.read_frames()` 能一次返回积压帧,播放后不额外读丢正式问题;测试要点:transport 单测和 ACK 后首句回归;优先级:P0;预计:45 分钟。
- [x] 8.3 实现主说话人画像独立就绪阈值;前置条件:8.2 完成;验收标准:新增 `OWNER_SPEAKER_PROFILE_MIN_MS=120`,主说话人缺席结束不再被 `OWNER_VAD_MIN_DURATION_MS` 拖慢;测试要点:短首句、背景噪声和重复提问不合并;优先级:P0;预计:45 分钟。
- [x] 8.4 补充配置文档、回归测试和门禁验证;前置条件:8.1 至 8.3 完成;验收标准:`.env.example`、README、配置显示和测试匹配新默认值;测试要点:compileall、unittest、security-check、model-check、device-check、OpenSpec strict;优先级:P0;预计:45 分钟。
- [x] 8.5 提交“低延迟端点”模块;前置条件:8.4 门禁通过;验收标准:中文 commit 信息为 `[低延迟端点]:完成首句保留和快速结束修正,包含ACK缓冲策略、批量读帧和主说话人端点回归测试`,提交后 `git status --short` 为空;优先级:P0;预计:10 分钟。