AudioEngine · /api/audio/signal-stats/history
AI 生成 · 待 owner review
本文档由 DocAgent S1 模式自动生成(spec-first · 代码尚未实现,文档作为施工蓝图)。status: draft,owner 工程师 review 通过后请把 status 改为 published,并删除 frontmatter 中的 generated_by 字段。
实现待对齐
本文档描述的 endpoint 尚未实现。代码完成后需在季度架构评审中对比文档与实际实现,如有偏差按 doc-code-sync-policy.md §3.5 漂移容忍窗口 处理。
1. 背景与目标
1.1 背景
现有 /api/audio/signal-stats(见 LegacyTestRoutes.cs:41-55)只返回实时瞬时快照(单点):isRunning / readCount / exceptionCount / rmsDbfs / lastStopReason / wasapiRunning / lastExceptionType / lastExceptionMessage。
前端调音工具需要绘制最近 N 秒的 RMS 曲线来诊断"播放是否中断 / 音量起伏",当前只能让前端自己以 100ms 间隔轮询并在前端缓存历史。这有 3 个痛点: - 前端首次进入页面时无历史(看不到刚才发生的事) - 网络抖动会丢点 - 前端崩溃 / 刷新会丢失整个历史
1.2 目标
- 在后端维护一个固定容量的环形缓冲(默认 600 个采样点 × 100ms = 60 秒),记录每次
GetSignalStats()调用的瞬时统计 - 暴露
/api/audio/signal-stats/history?seconds=N&downsample=K供前端按需拉取 - 端到端延迟:返回 < 50ms(纯内存查询,无 IO)
1.3 非目标
- 不做持久化(进程重启后历史清零)
- 不做多客户端订阅(前端直接 HTTP 轮询 1 次拿到全部历史即可,不需要 WebSocket / SSE)
- 不做多通道分别统计(本期只统计混合后的 RMS dBFS,后续可扩展)
2. 数据流图
flowchart LR
A[WASAPI Capture]:::xyL1 --> B[AudioEngineService<br/>读 PCM 帧]:::xyL3
B --> C[计算瞬时 RMS dBFS]:::xyL3
C --> D[SignalStatsCollector<br/>环形缓冲 600 点]:::xyL3
D --> E["/api/audio/signal-stats<br/>(单点 · 现有)"]:::xyL3
D --> F["/api/audio/signal-stats/history<br/>(时间序列 · 本次新增)"]:::xyL3
F --> G[前端绘制 RMS 曲线]:::xyL4
classDef xyL1 fill:#5DDECF,stroke:#5DDECF,color:#000
classDef xyL3 fill:#D4A574,stroke:#D4A574,color:#fff
classDef xyL4 fill:#C77DFF,stroke:#C77DFF,color:#fff
3. 接口契约
3.1 输入参数
| 字段 | 类型 | 必填 | 默认 | 说明 | 示例 |
|---|---|---|---|---|---|
seconds |
int (query) |
❌ | 60 |
拉取最近 N 秒的历史(范围 [1, 60]) |
?seconds=10 |
downsample |
int (query) |
❌ | 1 |
降采样因子(每 K 个原始点取 1 个,用于减少前端绘制压力) | ?downsample=5 |
3.2 输出 Schema
{
"ok": true,
"data": {
"windowSeconds": 60,
"downsample": 1,
"samplePeriodMs": 100,
"count": 600,
"samples": [
{ "tMs": -59900, "rmsDbfs": -23.12, "readCount": 12345, "exceptionCount": 0, "wasapiRunning": true },
{ "tMs": -59800, "rmsDbfs": -22.87, "readCount": 12349, "exceptionCount": 0, "wasapiRunning": true },
...
]
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
data.windowSeconds |
int |
实际返回的时间窗口(可能 < seconds 入参,若历史不足) |
data.downsample |
int |
实际生效的降采样因子 |
data.samplePeriodMs |
int |
原始采样间隔(ms · 由 AudioEngine 决定 · 默认 100) |
data.count |
int |
samples 数组长度 |
data.samples[].tMs |
int |
相对当前时刻的偏移(ms · 负数表示过去) |
data.samples[].rmsDbfs |
number |
该时刻的 RMS dBFS(2 位小数) |
data.samples[].readCount |
long |
累积读取计数 |
data.samples[].exceptionCount |
long |
累积异常计数 |
data.samples[].wasapiRunning |
bool |
该时刻 WASAPI 是否在跑 |
3.3 异常码
| HTTP Code | Error Code | 含义 | 处置建议 |
|---|---|---|---|
| 400 | INVALID_SECONDS |
seconds 超出 [1, 60] 范围 |
调整入参 |
| 400 | INVALID_DOWNSAMPLE |
downsample < 1 或 > 60 |
调整入参 |
| 503 | STATS_NOT_READY |
AudioEngine 尚未启动,环形缓冲为空 | 先调 /api/audio/start,再轮询本接口 |
4. 时序
sequenceDiagram
participant FE as Frontend
participant API as /api/audio/signal-stats/history
participant SVC as SignalStatsCollector
participant ENG as AudioEngineService
Note over ENG,SVC: 后台线程:每 100ms 调一次<br/>SVC.Push(rmsDbfs, readCount, ...)
ENG->>SVC: Push(s_t)
ENG->>SVC: Push(s_{t+100})
ENG->>SVC: Push(s_{t+200})
FE->>API: GET ?seconds=10&downsample=2
API->>SVC: GetHistory(window=10s, ds=2)
SVC-->>API: samples[] (50 points)
API-->>FE: 200 OK + JSON
5. 关键决策
设计哲思
环形缓冲在后端,绘制在前端 —— 这是 Xisound 调音工具的一贯模式。后端不绘制不渲染,只暴露原始数据;前端按需拉取并用 Canvas/WebGL 高效绘制。这种"数据-视觉解耦"让后端 API 永久稳定,前端可以独立迭代曲线样式而不动后端。
参见相关 ADR:ADR-08.20.NNN(待新建,关于环形缓冲容量决策) (实施时由 DocAgent 用 ADR 模板生成)
6. 验收标准
-
SignalStatsCollector单元测试覆盖率 ≥ 90%(含环形覆盖、降采样边界、空缓冲) - 端到端延迟 P99 < 50ms(纯内存)
-
seconds=60 + downsample=1时返回 600 点,数组正确按时间升序 - AudioEngine 未启动时返回 503 +
STATS_NOT_READY - 不引入新的内存分配热点(环形缓冲预分配,Push 不 new 对象)
- mkdocs build 0 ERROR / 0 新增 WARN
7. 测试验证(代码完成后填写)
| 测试类型 | 路径 | 说明 |
|---|---|---|
| Unit | AlgoDepartment/04_development/backend_csharp/TuningTool.Backend.Tests/Services/SignalStatsCollectorTests.cs |
(代码未完成,待对齐)覆盖 Push/GetHistory/降采样/边界 |
| Integration | AlgoDepartment/04_development/backend_csharp/test/integrationtest/SignalStatsApi/ |
(代码未完成,待对齐)起 AudioEngine + WASAPI loopback,跑 5 秒后 GET history,断言 ≥ 45 点 |
8. 影响面(代码完成后填写)
- 调用方:前端调音工具
frontend_vue3的 RMS 曲线组件(待新增) - 兼容性:Non-breaking(新增 endpoint,不动现有
/api/audio/signal-stats) - 迁移指引:N/A(新功能)
9. Changelog
| 版本 | 日期 | 改动 |
|---|---|---|
| 0.1.0 | 2026-05-13 | 首版 spec-first(DocAgent 基于 LegacyTestRoutes.cs:41-55 现状 + 假想增强生成) |