diff --git a/docs/adr/0007-demand-driven-dual-representation-quality.md b/docs/adr/0007-demand-driven-dual-representation-quality.md index d10ad1e..c3a50ed 100644 --- a/docs/adr/0007-demand-driven-dual-representation-quality.md +++ b/docs/adr/0007-demand-driven-dual-representation-quality.md @@ -61,8 +61,8 @@ stream generation across three stages: | Stage | Required evidence | | --- | --- | | A. Capture | `MediaStreamTrack.getSettings()` width, height, and frame rate | -| B. Host outbound | actual width/FPS/bitrate, target or available bitrate when present, interval encode time, `qualityLimitationReason`, RTT, loss/retransmission, and selected direct/TURN route | -| C. Viewer inbound | actual width/FPS/bitrate, loss, jitter, interval decode/drop counts, and freeze evidence | +| B. Host outbound | actual width/FPS/bitrate, target or available bitrate when present, interval encode time, `qualityLimitationReason`, RTT, loss/retransmission, selected direct/TURN route, and derived negotiated video codec/profile/parameters plus `scalabilityMode` when applicable | +| C. Viewer inbound | actual width/FPS/bitrate, loss, jitter, interval decode/drop/freeze evidence, the corresponding derived codec/profile/parameters and applicable `scalabilityMode`, and actual decode behavior | Interpretation is deliberately ordered: @@ -72,7 +72,7 @@ Interpretation is deliberately ordered: | Capture high, outbound low, reason `cpu` | sender encode/resource pressure | | Capture high, outbound low, reason `bandwidth` | congestion, uplink, GCC, or TURN/path pressure | | Outbound healthy, inbound degraded | transport or receiver-path problem | -| Inbound metrics healthy, image still blurry | insufficient bitrate/quantization, codec, or display scaling problem | +| Inbound metrics healthy, image still blurry | insufficient bitrate/quantization, negotiated codec/profile/layer, or display scaling problem | WebRTC stats are sampled dictionaries and many useful counters are cumulative. The controller must use adjacent, non-overlapping deltas and rebase on a missing @@ -82,14 +82,17 @@ they are not zeros. Implementation is staged. First correlate A and B locally in one sampling tick, with an explicit interval, media/stat identity, and valid deltas. Only after that probe is trustworthy may the product add a minimal authenticated C report -for the few receive/decode signals required by the two-state predicate. Do not -build a general telemetry schema or upload raw stats. +for the few receive/decode signals required by the two-state predicate. The B/C +correlation uses normalized fields derived from negotiated parameters/stats and +actual decode behavior; it must never upload raw SDP, raw stats, candidate +addresses, or other identifiers. Do not build a general telemetry schema. A viewer may request `LOW`, but the request is advisory. It must be carried on an authenticated, current room/path session and be rate-limited and deduplicated. -The sender/controller accepts it only when viewer receive/decode behavior agrees -with sender transport/GCC and encode evidence. A request alone cannot lower -quality or start a representation. +The sender/controller accepts it only when viewer receive/decode behavior and +derived negotiated codec/profile/parameters (including applicable +`scalabilityMode`) agree with sender transport/GCC and encode evidence. A +request alone cannot lower quality or start a representation. UA, platform, and device-model detection does not participate in quality selection. The existing mobile/iPad heuristic remains limited to conservative diff --git a/docs/research/realtime-quality-adaptation.md b/docs/research/realtime-quality-adaptation.md index 6740a30..4c4165e 100644 --- a/docs/research/realtime-quality-adaptation.md +++ b/docs/research/realtime-quality-adaptation.md @@ -86,8 +86,8 @@ Correlate one time interval and media generation across: | Evidence | Fields | | --- | --- | | A. Host capture | actual width, height, FPS from `getSettings()` | -| B. Host outbound | width/FPS/bitrate, target/available bitrate, interval encode time, limitation reason, path, RTT, loss, retransmission | -| C. Viewer inbound | width/FPS/bitrate, loss, jitter, interval decode/drop, freeze | +| B. Host outbound | width/FPS/bitrate, target/available bitrate, interval encode time, limitation reason, path, RTT, loss/retransmission, and derived negotiated codec/profile/parameters plus applicable `scalabilityMode` | +| C. Viewer inbound | width/FPS/bitrate, loss, jitter, interval decode/drop/freeze, corresponding derived codec/profile/parameters/layer, and actual decode behavior | Product inference from those facts: use the following ordered classification: @@ -105,8 +105,9 @@ reset evidence remains unknown and rebases the interval. The smallest implementation sequence is local A+B correlation in one host sampling tick, including the interval, media/stat identity, and valid deltas. Only after that is trustworthy should a minimal authenticated C report carry -the receive/decode signals needed by the two-state predicate. A general remote -stats stream or telemetry pipeline is unnecessary. +the receive/decode and derived negotiation signals needed by the two-state +predicate. It never carries raw SDP, raw stats, candidate addresses, or other +identifiers; a general remote stats stream or telemetry pipeline is unnecessary. ## Accepted Adaptation Direction diff --git a/docs/方案设计.md b/docs/方案设计.md index 989517c..3b4e0c9 100644 --- a/docs/方案设计.md +++ b/docs/方案设计.md @@ -133,9 +133,9 @@ Zod 在服务边界拒绝未知类型、超长字符串、非法 SDP/candidate | 1080p30 | 1920x1080、30 fps | 5 Mbps/peer | | 720p30 | 1280x720、30 fps | 3 Mbps/peer | -浏览器可返回更低设置,界面以 `track.getSettings()` 显示实际捕获结果。视频 track 保留 `contentHint = "motion"`;待合并质量控制默认使用 `degradationPreference = "maintain-resolution"`,三个推荐档位都采用清晰优先。折叠高级区将设置严格限制为 720p/1080p/1440p、15 至 60 整数 FPS、2 至 12 Mbps,以及 `maintain-resolution`、`balanced`、`maintain-framerate` 三种偏好。它们只是 ceiling 和浏览器偏好,不保证实际分辨率、帧率或码率。 +浏览器可返回更低设置,界面以 `track.getSettings()` 显示实际捕获结果。生产 release `769de201f7cc` 已部署有界手动质量控制:视频 track 保留 `contentHint = "motion"`,默认使用清晰优先的 `degradationPreference = "maintain-resolution"`,并允许显式选择 balanced 或 fluid。折叠高级区将设置严格限制为 720p/1080p/1440p、15 至 60 整数 FPS、2 至 12 Mbps,以及 `maintain-resolution`、`balanced`、`maintain-framerate` 三种偏好。它们只是 ceiling 和浏览器偏好,不保证实际分辨率、帧率或码率。 -每次 `setParameters()` 都必须从当次 `getParameters()` 派生更新,然后读回 requested/applied `maxBitrate`、`maxFramerate`、`scaleResolutionDownBy` 和 degradation preference。拒绝或浏览器改写必须进入可见状态,不能只写 `console.warn`。生产版本仍使用 `balanced`,用户报告的严重降级尚未完成受控分类;本改动只提供有界 clarity/balanced 控制,不得据此宣称画质提升。下一次真实质量验收仍需在同一高动态场景采样 1、2、3 名观看者和 TURN 路径。不得只提高 ceiling、强制 codec 或修改 SDP。 +每次 `setParameters()` 都必须从当次 `getParameters()` 派生更新,然后读回 requested/applied `maxBitrate`、`maxFramerate`、`scaleResolutionDownBy` 和 degradation preference。拒绝或浏览器改写必须进入可见状态,不能只写 `console.warn`。线上已是 clarity-first bounded controls,但用户报告的严重降级尚未完成受控分类,ADR-0007 自动质量控制也尚未实现;不得据此宣称画质提升。下一次真实质量验收仍需在同一高动态场景采样 1、2、3 名观看者和 TURN 路径。不得只提高 ceiling、强制 codec 或修改 SDP。 PoC 不强制 codec,也不做 SDP munging。先通过 stats 记录实际协商 codec、`encoderImplementation` 和 `powerEfficientEncoder`,再依据目标机器测量决定是否优先 H.264。这样避免静态 codec 偏好意外触发软件编码。 @@ -158,14 +158,14 @@ PoC 不强制 codec,也不做 SDP munging。先通过 stats 记录实际协商 | 阶段 | 必要证据 | | --- | --- | | A. Host capture | `track.getSettings()` 的实际宽、高、FPS | -| B. Host outbound | 实际宽高/FPS/码率、可用或目标码率、区间 encode time、`qualityLimitationReason`、RTT、丢包、重传和 direct/TURN 路径 | -| C. Viewer inbound | 实际宽高/FPS/码率、丢包、jitter、区间 decoded/dropped frame 和 freeze | +| B. Host outbound | 实际宽高/FPS/码率、可用或目标码率、区间 encode time、`qualityLimitationReason`、RTT、丢包、重传、direct/TURN 路径,以及派生后的实际协商视频 codec/profile/parameters 和适用时的 `scalabilityMode` | +| C. Viewer inbound | 实际宽高/FPS/码率、丢包、jitter、区间 decoded/dropped frame 和 freeze,以及对应派生 codec/profile/parameters、适用时的 `scalabilityMode` 和实际解码表现 | -判断顺序固定为:Capture 低归为采集或约束;Capture 高而 outbound 低且 reason=`cpu` 归为编码资源;Capture 高而 outbound 低且 reason=`bandwidth` 归为 GCC、上行或 TURN/路径;outbound 正常而 inbound 低归为传输或接收;inbound 指标正常但肉眼模糊归为码率/量化、codec 或显示缩放。累计统计只计算相邻、不重叠区间的 delta;缺字段、stats ID/媒体代次变化或计数器回退时重新建立基线,不能把未知当零。 +判断顺序固定为:Capture 低归为采集或约束;Capture 高而 outbound 低且 reason=`cpu` 归为编码资源;Capture 高而 outbound 低且 reason=`bandwidth` 归为 GCC、上行或 TURN/路径;outbound 正常而 inbound 低归为传输或接收;inbound 指标正常但肉眼模糊归为码率/量化、协商 codec/profile/parameters、适用的 scalable layer 或显示缩放。B/C 必须关联同一派生协商结果与实际解码表现。累计统计只计算相邻、不重叠区间的 delta;缺字段、stats ID/媒体代次变化或计数器回退时重新建立基线,不能把未知当零。 -探针按最小顺序落地:先在 host 同一个采样 tick 内关联 A+B,并携带明确 window、媒体/stats identity 和有效 delta;验证可靠后才增加只包含两态判定所需字段的受限、已鉴权 C 上报。不建设通用遥测 schema,也不上传原始 stats。 +探针按最小顺序落地:先在 host 同一个采样 tick 内关联 A+B,并携带明确 window、媒体/stats identity 和有效 delta;验证可靠后才增加只包含两态判定所需字段的受限、已鉴权 C 上报。不建设通用遥测 schema,只传派生后的协商字段,绝不上传 raw stats、raw SDP、candidate 地址或其他标识符。 -Viewer 可通过已鉴权、绑定当前房间/路径代次的控制面请求 `LOW`,但请求只是一条观测输入,必须限频和去重,并与 sender 的 Transport-CC/GCC、实际码率、RTT、丢包、重传及编码限制、viewer 的解码/丢帧/冻结表现交叉验证。UA、平台和设备型号不参与质量决策;现有 mobile/iPad 检测只用于保守设置 relay capacity。 +Viewer 可通过已鉴权、绑定当前房间/路径代次的控制面请求 `LOW`,但请求只是一条观测输入,必须限频和去重,并与 sender 的 Transport-CC/GCC、实际码率、RTT、丢包、重传及编码限制、派生协商 codec/profile/parameters(适用时含 `scalabilityMode`)和 viewer 的实际解码/丢帧/冻结表现交叉验证。UA、平台和设备型号不参与质量决策;现有 mobile/iPad 检测只用于保守设置 relay capacity。 若以后要求任何时刻严格只有一个编码输出,才单独评估 SVC:每条连接可独立选择基础层或增强层,但必须读回实际 codec/`scalabilityMode`,确认目标硬件或 power-efficient 编码路径,并通过游戏性能和亚秒延迟验收。浏览器的硬件偏好不是保证,不能静默回退为软件 SVC;常驻 SVC 不是默认方案。普通非分层编码包不能只靠转发生成另一档画质,实现路径差异只能用第二表示、SVC 或 relay/SFU 转码,当前优先第二表示。 diff --git a/docs/需求理解.md b/docs/需求理解.md index c0d53a8..593b57e 100644 --- a/docs/需求理解.md +++ b/docs/需求理解.md @@ -23,7 +23,7 @@ - [ ] NAT 兜底:每条 parent-child 边独立进行 ICE;生产环境必须提供 STUN、TURN/UDP 与 TURN/TCP candidates,通过优先级偏好直连和 UDP,同时允许无法使用 UDP 的网络选择 TCP,不能因为某条边的网络与其他边不同而静默失败。 - [ ] 质量控制:保留 1080p60(8 Mbps)、1080p30(5 Mbps)、720p30(3 Mbps)三档推荐上限,默认采用清晰优先;分享期间可直接换档或应用有界高级设置,不重新选择来源或重建健康连接。Peer-assisted relay 与可选 SFU 必须接收同一个严格校验的房间级权威设置,覆盖当前和以后建立的 sender;普通 P2P 信令结构保持不变。任何设置都只是浏览器上限和偏好,必须读回实际 sender 参数并显示参数拒绝、改写和持续受限原因。不做自定义动态 FPS、综合评分或周期性全房间调档。 - [ ] 按需双表示:健康房间只运行一套共享 `HIGH` 编码;只有一个或多个观看路径被同一时段的 sender 与 viewer 统计持续证明无法承受时,才临时启动一套由全部弱路径共用的 `LOW` 编码。健康路径继续使用 `HIGH`,全部弱路径稳定恢复后关闭 `LOW`。编码表示硬上限为二,禁止按观看者增长为 N 套,也禁止把最差路径的目标应用到整个房间。没有合格硬件/power-efficient 路径或第二编码造成不可接受的 CPU/GPU/游戏负载时必须 fail closed:保护 `HIGH`,向弱路径明确显示降级或不可用。 -- [ ] 路径级质量状态:每条观看路径只使用 `HIGH` 与 `FALLBACK` 两态。进入 `FALLBACK` 需要多个连续窗口的带宽不足、冻结或解码跟不上证据,回到 `HIGH` 需要更长的稳定窗口;进入与退出使用不同门槛且不计算综合分数。Viewer 的低档请求必须经当前会话鉴权、限频和去重,并由 sender 的 GCC/Transport-CC、实际码率、RTT、丢包、重传、编码限制与 viewer 的收流、解码、丢帧、冻结证据交叉验证,不能仅凭自报生效。 +- [ ] 路径级质量状态:每条观看路径只使用 `HIGH` 与 `FALLBACK` 两态。进入 `FALLBACK` 需要多个连续窗口的带宽不足、冻结或解码跟不上证据,回到 `HIGH` 需要更长的稳定窗口;进入与退出使用不同门槛且不计算综合分数。Viewer 的低档请求必须经当前会话鉴权、限频和去重,并由 sender 的 GCC/Transport-CC、实际码率、RTT、丢包、重传、编码限制、派生后的实际协商视频 codec/profile/parameters(适用时含 `scalabilityMode`)与 viewer 的实际解码、丢帧、冻结证据交叉验证,不能仅凭自报生效;上报不得包含 raw SDP、candidate 地址或其他标识符。 - [ ] 断线恢复:临时网络变化时尝试 ICE restart 和重连,并向用户显示当前连接状态。 - [ ] 可观测性:采集候选类型、RTT、丢包、抖动、实际码率、帧率、编码耗时和质量受限原因。 - [ ] 渐进式诊断:分享者和观看者默认只看到房间、画面、核心状态和常用控制;候选路径、RTT、丢包、编解码器、编码耗时等技术详情由一个明确的“显示连接详情”开关展开。隐藏诊断不能隐藏失败原因、音频缺失、持续画质受限或需要用户操作的告警。 @@ -114,7 +114,7 @@ - Given 房间所有观看路径持续健康,When 自动质量控制运行,Then 只存在一套共享 `HIGH` 表示,且任何单路径短暂抖动或未经验证的低档请求都不启动第二套编码或降低其他路径。 - Given 一个或多个路径在连续窗口中被 sender 与 viewer 证据共同确认无法承受 `HIGH`,When 它们进入 `FALLBACK`,Then 系统最多启动一套共享 `LOW`,只切换这些弱路径,其他路径继续 `HIGH`;所有弱路径经过更长稳定恢复窗口后返回 `HIGH` 并关闭 `LOW`。 - Given 启动第二套编码会超过游戏 CPU/GPU 预算或没有合格硬件/power-efficient 路径,When 弱路径请求 `LOW`,Then 系统保留健康路径的 `HIGH` 并向弱路径明确显示降级或不可用,不得退回全房间最低目标或静默软件编码。 -- Given 同一时刻采集、host outbound 与 viewer inbound 证据,When 进行根因分类,Then 依次区分 Capture 低、Capture 高但 outbound 因 CPU 低、Capture 高但 outbound 因 bandwidth 低、outbound 正常但 inbound 低、以及 inbound 正常但肉眼模糊五类,不用 UA 或设备型号代替运行时证据。 +- Given 同一时刻采集、host outbound 与 viewer inbound 证据,When 进行根因分类,Then 关联派生后的实际协商视频 codec/profile/parameters、适用时的 `scalabilityMode` 与真实解码表现,依次区分 Capture 低、Capture 高但 outbound 因 CPU 低、Capture 高但 outbound 因 bandwidth 低、outbound 正常但 inbound 低、以及 inbound 正常但肉眼模糊五类;不用 UA 或设备型号代替运行时证据,也不上传 raw SDP。 - Given Viewer 发送低档请求,When 请求未鉴权、过频、重复、过期或没有匹配的 sender/viewer 统计,Then 请求不改变表示或路径状态;有效请求也只能作为交叉验证输入。 - Given 受控 RTT/丢包测试条件,When 连续分享高动态游戏画面 30 分钟,Then 延迟、帧率与丢帧达到上述目标,且没有不可恢复的冻结。 - Given 分享过程中切换 Wi-Fi/有线网络,When ICE 连接失败,Then 客户端触发 ICE restart,并在成功或超时后给出明确状态。