docs: define mobile sender capability gates (#51)
docs: define mobile sender capability gates
This commit is contained in:
commit
99b4817330
7 files changed
+155
-2
No files matched your search
@@ -23,6 +23,7 @@ Last updated: 2026-08-19
|
||||
- Browser relays resend remote `MediaStreamTrack` values and re-encode at each hop; WebRTC does not guarantee a shared encoder across peer connections, so measure the cost.
|
||||
- Keep experiments bounded: the standard representation sequence is below; native RTP relay, encoded-object striping, and FEC remain separate.
|
||||
- ADR-0006's fixed-`HIGH` canary reached host setup and one encoder output but retained no downstream checkpoint before the first-viewer timeout. It is no-go-unclassified; no native product code is accepted, and any revisit starts at its staged evidence gate.
|
||||
- Mobile Web Host is unsupported: current Android Chrome/Firefox and iOS Safari lack reliable `getDisplayMedia`; feature-detect and fail clearly, never by UA. Mobile Viewer stays leaf-only. After P1 Windows native/deploy, P2 may gate Android 14+ fixed-`HIGH`; iOS waits for stable iOS 27 ScreenCaptureKit without ReplayKit.
|
||||
- ADR-0005 accepts SFU roots as the primary central fallback after direct/peer UDP. The candidate has no TURN consumer or credential wire; any future exceptional-edge grant is a complete separate change. PR #12 is superseded.
|
||||
- Keep the failure-only controller default-off until the isolated STUN/SFU exact-room gates pass. Preserve break-before-make, sticky healthy subtrees, mobile leaves, and PR #20 prewarm; public transport/load remains open.
|
||||
- Local reparenting is a later candidate: start with unassigned relay admission rescue; do not block current work.
|
||||
|
||||
@@ -192,6 +192,35 @@ connectivity smoke. Correlate capture settings, negotiated codec/derived fmtp,
|
||||
actual outbound/inbound bitrate, loss, jitter, concealment, jitter buffer, and
|
||||
A/V playout timing using a distinguishable stereo fixture plus game/film audio.
|
||||
|
||||
## Deferred Android Application-Audio Candidate
|
||||
|
||||
This is a P2 input for the later Android 14/API 34+ native sender, not a current
|
||||
Web or Windows requirement. Android's `AudioPlaybackCapture` API can constrain
|
||||
captured playback with `addMatchingUid()` when the target UID is already known,
|
||||
or with `addMatchingUsage()` for eligible usages. The source player still must
|
||||
use `USAGE_MEDIA`, `USAGE_GAME`, or `USAGE_UNKNOWN`, run in the same user
|
||||
profile, and permit capture under its manifest/runtime/player policy. The capture
|
||||
app also needs `RECORD_AUDIO` permission and an approved `MediaProjection`
|
||||
session. The most restrictive source policy wins, so silence or refusal is a
|
||||
valid result and must not trigger a whole-system fallback.
|
||||
|
||||
Android 14 QPR2's system `MediaProjection` picker can limit video to one selected
|
||||
app window. However, the public API 34 result contract passes the consent result into
|
||||
`getMediaProjection()` and documents only a projection grant; it does not
|
||||
promise the capturing app the selected package or UID. It is therefore an
|
||||
inference, not an API guarantee, that the video selection can be associated with
|
||||
the UID required by `addMatchingUid()`. Screener must separately prove the
|
||||
selected-app-video plus selected-app-audio pairing on target devices with an
|
||||
independently established UID, or keep that mode unsupported. Usage-only
|
||||
filtering is broader and cannot be relabeled as per-app isolation.
|
||||
|
||||
The bounded audio gate covers a known target UID, an unknown picker target,
|
||||
`USAGE_GAME`/`USAGE_MEDIA`, source opt-out, no active render stream, process
|
||||
restart, voice/notification leakage, secure/protected video, rotation, lock-stop,
|
||||
thermal load, one/two Web viewers, and A/V sync. Missing audio remains a visible
|
||||
silent/unsupported state. PID/UID/package, source labels, raw audio, and device
|
||||
identity stay local and are not retained or uploaded.
|
||||
|
||||
## Revisit Gates
|
||||
|
||||
Add a user-facing audio setting only when all of these are true:
|
||||
@@ -225,3 +254,8 @@ Add a user-facing audio setting only when all of these are true:
|
||||
- [Windows process-loopback parameters](https://learn.microsoft.com/en-us/windows/win32/api/audioclientactivationparams/ns-audioclientactivationparams-audioclient_process_loopback_params)
|
||||
- [Windows 10 release information](https://learn.microsoft.com/en-us/windows/release-health/release-information)
|
||||
- [Microsoft WASAPI loopback recording](https://learn.microsoft.com/en-us/windows/win32/coreaudio/loopback-recording)
|
||||
- [Android capture video and audio playback](https://developer.android.com/media/platform/av-capture)
|
||||
- [Android `AudioPlaybackCaptureConfiguration.Builder`](https://developer.android.com/reference/android/media/AudioPlaybackCaptureConfiguration.Builder)
|
||||
- [Android `MediaProjectionManager`](https://developer.android.com/reference/android/media/projection/MediaProjectionManager)
|
||||
- [Android media projection](https://developer.android.com/media/grow/media-projection)
|
||||
- [Android secure-window capture boundary](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_SECURE)
|
||||
@@ -93,6 +93,55 @@ Audio, per-process WASAPI capture, WGC/DDA fallback, source selection, Electron,
|
||||
installers, updating, and cross-platform abstractions stay outside the first
|
||||
spike.
|
||||
|
||||
## Deferred Mobile Sender Boundary
|
||||
|
||||
This section records later capability work; it does not broaden ADR-0006's
|
||||
Windows scope or authorize mobile runtime code. Priority remains the current
|
||||
deployment and staged Windows fixed-`HIGH` gate. The first mobile candidate is a
|
||||
separate P2 Android 14/API 34+ spike only after those P1 gates complete.
|
||||
|
||||
Android's official `MediaProjection` path captures the display into a `Surface`;
|
||||
selected-app-window capture starts with Android 14 QPR2. API 34 requires fresh
|
||||
consent for each session, one use of each projection token, and a foreground
|
||||
service declared as `mediaProjection`. Rotation or selected-content resizing requires
|
||||
`onCapturedContentResize()` handling; user stop, screen lock, another projection,
|
||||
or process death invalidates the session and requires bounded cleanup through
|
||||
`onStop()`. These OS consent and foreground indicators are part of the product
|
||||
experience and cannot be made invisible.
|
||||
|
||||
The bounded Android data path is:
|
||||
|
||||
```text
|
||||
MediaProjection Surface -> one hardware MediaCodec fixed-HIGH encoder
|
||||
-> existing Host admission / room / WSS / standard WebRTC
|
||||
-> one or two unmodified Web viewers
|
||||
```
|
||||
|
||||
It adds no mobile-only topology, `LOW`, AV1, codec ladder, third downstream edge,
|
||||
or software fallback. `MediaCodecInfo.isHardwareAccelerated()` is metadata
|
||||
provided by the manufacturer that Android explicitly says cannot be tested for correctness,
|
||||
so it is only an admission signal. The spike must also prove the selected named
|
||||
encoder, supported fixed format, interval encode cost, CPU/GPU, temperature and
|
||||
throttling, power, queue bounds, actual bitrate/quality, and game impact on real
|
||||
devices. Missing or failed hardware evidence is no-go; the implementation must
|
||||
not silently select a software codec. Network changes reuse the existing
|
||||
per-edge WebRTC recovery contract rather than restarting capture or creating a
|
||||
new transport.
|
||||
|
||||
iOS work remains later and separate. Apple's current ScreenCaptureKit
|
||||
documentation says the framework replaces ReplayKit for screen streaming and
|
||||
that a broadcast extension is no longer required, but the iOS sample requires
|
||||
iOS 27 and the current APIs are still beta. Screener therefore does not build a
|
||||
ReplayKit/Broadcast Upload Extension compatibility stack. After the final iOS
|
||||
27 SDK and stable OS ship, one narrow ScreenCaptureKit system-picker spike may
|
||||
feed a fixed-`HIGH` VideoToolbox encoder into the same one/two-Web-viewer
|
||||
contract. It must set
|
||||
`kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder` and verify
|
||||
`kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder`; otherwise it
|
||||
fails closed. Rotation, background execution, lock-screen behavior, network
|
||||
switching, thermal throttling, audio scope, and A/V sync remain explicit gates
|
||||
on real devices, not implied framework capabilities.
|
||||
|
||||
## Pion Validation Route
|
||||
|
||||
Pion is the released-public-API validation route while the larger libwebrtc
|
||||
@@ -273,6 +322,14 @@ evidence does not retain its policy.
|
||||
- [RFC 4588 RTP retransmission](https://www.rfc-editor.org/rfc/rfc4588.html)
|
||||
- [RFC 8888 congestion-control feedback](https://www.rfc-editor.org/rfc/rfc8888.html)
|
||||
- [Electron desktop capture](https://www.electronjs.org/docs/latest/api/desktop-capturer/)
|
||||
- [Android media projection](https://developer.android.com/media/grow/media-projection)
|
||||
- [Android media-projection foreground service](https://developer.android.com/develop/background-work/services/fgs/service-types#media-projection)
|
||||
- [Android `MediaCodecInfo`](https://developer.android.com/reference/android/media/MediaCodecInfo)
|
||||
- [Android `MediaCodecList`](https://developer.android.com/reference/android/media/MediaCodecList)
|
||||
- [Apple ScreenCaptureKit](https://developer.apple.com/documentation/ScreenCaptureKit)
|
||||
- [Apple iOS ScreenCaptureKit sample](https://developer.apple.com/documentation/screencapturekit/capturing-screen-content-on-ios)
|
||||
- [Apple required hardware encoder key](https://developer.apple.com/documentation/videotoolbox/kvtvideoencoderspecification_requirehardwareacceleratedvideoencoder)
|
||||
- [Apple hardware encoder readback](https://developer.apple.com/documentation/videotoolbox/kvtcompressionpropertykey_usinghardwareacceleratedvideoencoder)
|
||||
|
||||
libwebrtc uses a BSD-style license and Pion uses MIT, but distribution still
|
||||
requires a full libwebrtc third-party notice review and an H.264 patent/licensing
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# P2P 优先游戏屏幕共享调研与可行性评估
|
||||
|
||||
- 调研日期:2026-08-18
|
||||
- 移动端采集能力复核:2026-08-19
|
||||
- 目标场景:一名玩家向少量熟人私密分享,观看者可用手机/桌面浏览器加入,低延迟,尽量不消耗媒体服务器带宽
|
||||
- 结论状态:本文记录已部署 PoC 的 P2P/coturn 基线。ADR-0005 与[低服务器成本媒体路由](./low-server-media-routes.md)已取代本文早期“每条 peer edge 必带 TURN”的旗舰建议;生产代码尚未迁移
|
||||
|
||||
@@ -173,6 +174,28 @@ await sender.setParameters(parameters);
|
||||
- [RTCRtpSender 参数](https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpSender/setParameters)
|
||||
- [Chromium capture 架构](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/media/capture/)
|
||||
|
||||
### 移动浏览器分享端边界
|
||||
|
||||
截至 2026-08-19,普通手机浏览器不能作为可靠的 Screener Host。当前
|
||||
MDN Browser Compatibility Data 把 `getDisplayMedia()` 标为 Chrome Android、
|
||||
Firefox Android 和 Safari iOS 均不支持;Chrome Android 72--88 与 Firefox
|
||||
Android 66--79 曾暴露方法,但调用恒定以 `NotAllowedError` 失败。屏幕音频在
|
||||
Chrome Android 也标为不支持。桌面模式、UA 或设备性能不能改变这个平台 API
|
||||
边界。
|
||||
|
||||
Web UI 后续只做最小诚实处理:运行时检查
|
||||
`navigator.mediaDevices?.getDisplayMedia`,缺失时在建房/发布前明确显示不支持;
|
||||
方法存在也只表示可以尝试,真实调用失败仍区分 denied/cancelled/capture-failed,
|
||||
不能按 UA 宣称兼容。移动 Viewer 不需要该 API,继续使用同一响应式 Web 播放端并保持
|
||||
leaf-only。移动 Host 若要落地,必须走后续原生 sender,而不是在 Web 端模拟
|
||||
screen track 或加入私有媒体协议。
|
||||
|
||||
来源:
|
||||
|
||||
- [MDN Browser Compatibility Data: `MediaDevices.getDisplayMedia`](https://github.com/mdn/browser-compat-data/blob/main/api/MediaDevices.json)
|
||||
- [MDN `getDisplayMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia)
|
||||
- [W3C Screen Capture](https://w3c.github.io/mediacapture-screen-share/)
|
||||
|
||||
### Electron 分享端
|
||||
|
||||
Electron 可以固定 Chromium 版本,枚举屏幕/窗口,改善选源、热键和分享状态 UX,并使用 loopback 系统音频。它底层仍是 Chromium,单靠封装不会自动获得 Discord 级捕获质量。
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ unconfigured, so production remains one host connection per viewer and P2P/TURN.
|
||||
## Unverified Boundaries
|
||||
|
||||
- Full-resolution 30-minute runs, relay CPU/GPU, controlled loss/RTT, and depth latency are unverified. Production `769de201f7cc` game sharing is reported low-FPS/high-load; latest `main`, preview cost, codec, and hardware encoding are not yet compared.
|
||||
- Android Chrome/iOS Safari leaves are unverified; runtime conservatively marks detected mobile/iPad clients as leaves.
|
||||
- Android Chrome/iOS Safari Viewer leaves remain unverified and conservatively leaf-only. Mobile Web Host is unsupported; native senders are planned only.
|
||||
- Silent partitions can wait 30 to 60 seconds for heartbeat detection before the default 5-second grace; this remains unverified.
|
||||
- Real audio and heterogeneous clients remain unverified. Production reports poor film audio and voice-call self-echo under system capture; there is no app audio ceiling or Web process isolation. Diagnose A/B/C and sync, then gate Windows 11 game-process audio; Windows 10 stays unresolved without system fallback.
|
||||
- Production `769de201f7cc` reportedly sustains bandwidth-limited blur on a capable LAN; Host refresh recovered while Viewer refresh did not, and persistence across churn was also reported. This prioritizes, but does not prove, host sender/PC/GCC/capture generation.
|
||||
|
||||
@@ -191,6 +191,36 @@ SVC 的标准能力门禁已经静态关闭为 `no-go-web-svc-cross-path-hardwar
|
||||
|
||||
标准表示能力排在任何自定义双表示媒体实现之前。当前 Web P2P simulcast 因 receiver 不能选 RID 且跨 PeerConnection 无 shared-encode 契约而静态 no-go;当前 Web/LiveKit SVC 因 direct/peer 无独立选层、硬件不可证明且 pinned screen share 为 `L1T3` 而静态 no-go。下一 gate 优先验证 pinned LiveKit 的标准 exactly-two screen-share simulcast:Dynacast off 常驻 `HIGH+LOW`,zero-descendant SFU leaf 以 `HIGH` 为 maximum,由 SFU BWE 独立降层和恢复;通过后不实现自定义媒体 selector。Root-with-children 的 suspect/确认/有界迁移是 default-on 前硬门。只有内建选择不满足门槛时才显式设置标准 subscriber quality;常驻成本违反硬件、游戏或上传预算时才测标准 sender 手动启停,全部标准路径失败后才进入 custom/native dual encode。当前 subscriber 未 attach `RemoteTrack`,因此不直接启用 `adaptiveStream`,但这不阻塞 SFU BWE leaf 候选。Cumulative Dynacast-on 只作为另一种 always-on 形态。本 SVC 静态审查不跑 browser。具体门槛由 ADR-0007 和[实时质量调研](./research/realtime-quality-adaptation.md)持有,任何方案都不得复用 PR #28 的 minimum-of-two 或绕过 stock WebRTC congestion control。
|
||||
|
||||
## 移动分享端能力边界与排期
|
||||
|
||||
普通移动浏览器当前只承担 Viewer。Chrome Android、Firefox Android 与 Safari
|
||||
iOS 都没有可靠的 `getDisplayMedia()`;Web Host 入口必须检查运行时 API 并明确
|
||||
区分 unsupported、用户拒绝/取消与 capture failure,不能用 UA、desktop mode
|
||||
或设备型号放行。该边界不影响普通手机浏览器观看;手机仍是 leaf-only,并继续通过真机矩阵。浏览器版本证据由
|
||||
[WebRTC 调研](./research/webrtc-p2p-screen-sharing.md)持有。
|
||||
|
||||
优先级保持 P1 Windows native sender 与当前 deployment,移动 Host 不得抢跑。
|
||||
之后的 P2 Android 14/API 34+ 整屏 spike 只做一条窄纵向链路:系统
|
||||
`MediaProjection` selection -> `mediaProjection` foreground service -> 一个经筛选
|
||||
的硬件 `MediaCodec` fixed-`HIGH` encoder -> 现有 Host admission/room/WSS/标准
|
||||
WebRTC -> 一至两名未修改 Web Viewer。它不增加移动端专属信令、拓扑、`LOW`、
|
||||
AV1、codec ladder 或第三条 Host 下游边。`MediaCodecInfo.isHardwareAccelerated()`
|
||||
是厂商声明而非充分证明,所以还必须用真实设备持续测量 codec、encode time、
|
||||
CPU/GPU、温度/降频、功耗、游戏 FPS、队列、实际码率与画质;无合格硬件路径、
|
||||
创建/配置失败或性能门槛失败都停在 no-go,不静默切软件编码。
|
||||
|
||||
Android 的逐 session 授权、系统指示、旋转/尺寸回调、锁屏/撤销终止与资源释放
|
||||
都是产品行为,不能隐藏或用重启 capture 掩盖 transport 问题。应用音频可按已知
|
||||
UID 或 usage 过滤,但 Android 14 QPR2+ 单应用 picker 未承诺返回目标 UID;“所选应用画面 +
|
||||
同一应用音频”必须单独实测,来源策略或 secure/protected content 可产生静音、
|
||||
空白或拒绝,不能自动扩大为整机捕获。API 证据与矩阵由[原生 sender 调研](./research/native-shared-encode-sender.md)和[音频调研](./research/browser-screen-audio-quality.md)持有。
|
||||
|
||||
iOS 当前不建设 ReplayKit Broadcast Upload Extension 兼容栈。待 iOS 27 与
|
||||
ScreenCaptureKit SDK final/stable 后,只做 system picker -> VideoToolbox
|
||||
fixed-`HIGH` -> 现有 WebRTC/一至两名 Web Viewer 的 P2 窄实验。硬件编码必须要求
|
||||
并读回,未证明时 fail closed;系统授权/指示和全部生命周期/性能边界留给真机
|
||||
矩阵,不追加兼容 fallback。
|
||||
|
||||
## 媒体传输配置
|
||||
|
||||
当前仓库候选已经删除旧全房 TURN contract。`ServerConfig` 只接受
|
||||
@@ -302,6 +332,8 @@ hop 按[低服务器成本媒体路由](./research/low-server-media-routes.md)
|
||||
- CGNAT、双 NAT、移动热点和普通家宽下使用隔离 candidate,LiveKit 显式关闭 TCP fallback 且不配置 TURN,验证 host 与 roots 使用 SFU/UDP;人为封锁 UDP 时必须有界明确失败。旧 production release 留在独立实例作为回滚,不在同进程保留旧 transport;
|
||||
- Windows Chrome/Edge 的 tab/window/monitor 音轨有/无、同时语音通话和 video-only;Windows 11 原生候选另测 game process tree、通知、无渲染流与进程重启,Windows 10 记录明确不支持/未解决;
|
||||
- Android Chrome 与 iOS Safari 的播放手势、旋转、前后台和网络切换;
|
||||
- 仅在 Windows native/deploy P1 完成后,Android 14/API 34+ 原生 sender 才运行一至两名 Web Viewer 真机 gate:整屏、授权拒绝与撤销、旋转、锁屏停止、Wi-Fi/蜂窝切换、持续热降频、硬件 codec 读回/实测、目标 UID 已知/未知的 audio capture policy、secure/protected content、A/V sync 与资源释放;单应用窗口只在 Android 14 QPR2+ 测试;
|
||||
- iOS 27 ScreenCaptureKit 在 final SDK/OS 前不进入实现或矩阵;稳定后只运行 system picker、VideoToolbox 硬编 fail-closed、一至两名 Web Viewer、后台/锁屏/旋转/网络/热状态与 A/V sync 的窄 gate;
|
||||
- 一名分享者、八名异构观看者连续 30 分钟,同时记录较低人数基线、实际上行、编码负载和首帧时间。真实 1:8 未完成前不得把默认上限写成性能承诺。
|
||||
- 真实桌面 Chrome 对 balanced 与 clarity 做控制传播和连接身份 smoke;该项只证明直播中应用与不重建,不代替清晰度、负载或公网矩阵。
|
||||
|
||||
@@ -316,6 +348,9 @@ hop 按[低服务器成本媒体路由](./research/low-server-media-routes.md)
|
||||
5. 完成 automatic peer/SFU controller 与 exact-room canary 边界。
|
||||
6. 用有界网络矩阵验收 direct/peer UDP、SFU/UDP 和明确失败;selected-edge 兼容 transport 只有出现真实缺口后才另立完整 PR。
|
||||
7. 在媒体主线阶段验收后,用一个原子 PR 迁移 Host admission、`screener-v2`、room-scoped Viewer grant 和 SQLite v2;同一部署切换客户端/服务端/环境和数据库备份,随后删除 v1 配置、wire 与测试。用户名/roster 保持独立。
|
||||
8. P1 继续完成 Windows native fixed-`HIGH` staged gate 与 deployment;移动 Host 不阻断或先于它。
|
||||
9. P2 只在上述门槛后运行 Android 14/API 34+ fixed-`HIGH` 原生 sender spike;失败即停,不扩展为跨平台 framework。
|
||||
10. iOS 27 ScreenCaptureKit final 后再决定是否运行独立 P2 spike;不实现 ReplayKit compatibility path。
|
||||
|
||||
任何一步只实现当前消费者需要的接口。不得为未来账号、第三种媒体拓扑或原生 sender 预建抽象层。
|
||||
|
||||
|
||||
+4
-1
@@ -55,6 +55,8 @@
|
||||
### P2 - 可选功能
|
||||
|
||||
- [ ] 原生 Windows 捕获辅助程序,使用 WGC/DDA、WASAPI 和硬件编码器降低复制与编码开销。
|
||||
- [ ] Android 原生分享端有界实验:只在 Windows native/deploy 的 P1 门槛完成后,以 Android 14/API 34+ 整屏捕获为首个范围,使用 `MediaProjection`、`mediaProjection` foreground service 和经实测合格的硬件 `MediaCodec` 发送一份 fixed-`HIGH` 给一至两名普通 Web Viewer;单应用窗口选择只在 Android 14 QPR2+ 验证。复用现有 room、Host admission、WSS 与标准 WebRTC 契约,不新增移动端专属拓扑、`LOW`、AV1、codec ladder 或软件编码兜底。系统选源、授权和持续前台指示必须保留;旋转、锁屏终止、Wi-Fi/蜂窝切换、持续热降频、资源释放和真机画质/延迟都是硬门槛。
|
||||
- [ ] iOS 原生分享端有界实验:当前不实现 ReplayKit/broadcast-extension 兼容栈。待 iOS 27 与对应 ScreenCaptureKit SDK 脱离 beta 并稳定后,只评估 ScreenCaptureKit system picker + fixed-`HIGH` + 一至两名 Web Viewer 的窄路径;VideoToolbox 必须要求并读回硬件编码,无法证明时 fail closed,不增加 ReplayKit fallback、`LOW`、AV1 或新拓扑。
|
||||
- [ ] 多地区 SFU-root 调度,以及可选 TURN 兼容层的按地区、运营商可达率。
|
||||
|
||||
## 非功能需求
|
||||
@@ -67,7 +69,7 @@
|
||||
- 隐私:P2P 会向房间内好友暴露网络地址,首版威胁模型仅覆盖可信熟人;若要求隐藏 IP,必须切换为服务器转发。
|
||||
- 可维护性:代码、需求、调研、项目记忆、`AGENTS.md` 和 `.codex/` 均在 Git 中跟踪;开发配置不得依赖单一操作系统的绝对路径。
|
||||
- 迁移完整性:同一 release 的客户端、服务端和部署配置原子迁移;canary 结束后删除被替代的配置、wire、parser、双写与测试,不为无当前消费者的旧版本保留兼容层或第二套架构。Git 历史承担旧实现追溯。
|
||||
- 兼容性:分享端首个目标矩阵为 Windows 10/11 的当前 Chrome/Edge;观看端还必须覆盖当前 Android Chrome 和 iOS Safari,并实测自动播放限制、横竖屏、锁屏恢复与移动网络切换。Peer-assisted 实验只允许能力完整的前台桌面 Chrome/Edge 作为 relay,手机必须保持 leaf。
|
||||
- 兼容性:分享端首个目标矩阵为 Windows 10/11 的当前 Chrome/Edge;普通移动浏览器当前只属于 Viewer 矩阵。截止 2026-08-19,Chrome Android、Firefox Android 和 Safari iOS 都没有可靠的 `getDisplayMedia()`;Web Host 必须用运行时能力检测,API 缺失时明确显示不支持,API 存在但调用拒绝时区分用户拒绝/取消与 capture failure,不能用 UA/设备型号伪造兼容。观看端仍必须覆盖当前 Android Chrome 和 iOS Safari,并实测自动播放限制、横竖屏、锁屏恢复与移动网络切换。Peer-assisted 实验只允许能力完整的前台桌面 Chrome/Edge 作为 relay,手机必须保持 leaf。
|
||||
|
||||
## 边界与约束
|
||||
|
||||
@@ -110,6 +112,7 @@
|
||||
### 浏览器与移动端观看
|
||||
|
||||
- Given 观看者只有受支持的手机浏览器,When 打开有效邀请链接并执行浏览器要求的播放手势,Then 无需安装应用即可进入房间、看到首帧并听到可用音频。
|
||||
- Given 用户在普通手机浏览器尝试成为 Host,When `navigator.mediaDevices.getDisplayMedia` 缺失,Then 页面在创建发布路径前明确显示该浏览器不支持移动端屏幕分享,并保留加入房间入口。Given API 存在但真实调用失败,When 失败原因是拒绝/取消或其他 capture error,Then 分别显示对应状态而不是一律重标为不支持;判断使用运行时能力/结果而不是 UA、平台或设备型号,也不能把移动 Viewer 支持宣传成移动 Web Host 支持。
|
||||
- Given 观看者调节音量或静音,When 媒体切流、换父或恢复连接,Then 当前页面的本地播放音量保持不变,其他观看者和发送端不受影响;刷新页面后恢复默认音量,不产生信令、持久化或媒体重协商。
|
||||
- Given 用户在本机设置显示名,When 以 Host 或 Viewer 加入房间,Then 所有在线参与者看到同一份服务端权威 roster、对应房间标题和“名称 + room-scoped peer 后缀”;刷新后本机名称仍在,清除站点数据后恢复未命名默认值,数据库中不存在显示名或成员记录,展示身份不参与授权或路由。
|
||||
- Given 手机从 Wi-Fi 切换到蜂窝网络或页面从后台恢复,When 原候选对失效,Then 客户端执行 ICE restart 或重建连接,并显示恢复进度而不是永久黑屏。
|
||||
|
||||
Reference in new issue
Block a user