docs(viewer): define background playback boundary (#124)

This commit is contained in:
AAA authored and GitHub committed 2026-08-21 10:38:23 +08:00
1 parent 18263804b9
commit f53e4eb2f4
4 files changed
+14 -4

No files matched your search

+2 -1
View File
@@ -20,6 +20,7 @@ Last updated: 2026-08-21
## Current Recommendation
- Keep desktop Chrome/Edge and the responsive Web viewer as the baseline. Validate Android Chrome and iOS Safari as leaves.
- Keep Viewer playback on one persistent, user-started audible media element while hidden. Continuity evidence uses media/connection counters; hidden video composition is presentation-only, and iOS lock-screen, reclamation and background reconnection remain device gates.
- Use direct host P2P for one or two viewers, then the bounded controller for every room when `PEER_ASSISTED_MEDIA=true`. Room `1` is historical smoke, not a runtime gate; resource, quality, recovery, SFU/UDP, bounded-failure, and browser/mobile evidence remain separate.
- 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.
@@ -69,7 +70,7 @@ These are measurement gates, not performance claims.
- Sustainable count by hardware, quality, network, and route: finish instrumented `1/3/5/8`, then pass a 20-viewer matrix before changing the accepted target default to 20.
- Whether ADR-0004 passes fanout, re-encoding, depth-four latency, reparenting, silent-partition, and mobile-leaf gates.
- Selected-edge: active Host-ingress function passes; initial ingress, `peer-selected`, expiry/failure, mobile, resource and bandwidth gates remain. The bearer is non-revocable until expiry; performance follows later and Media TCP is out.
- Exact mobile Viewer lifecycle behavior across autoplay, rotation, backgrounding and network changes.
- Exact mobile Viewer lifecycle behavior across autoplay, rotation, iOS lock-screen/page reclamation, background reconnection and network changes.
- Project license and distribution model, which determines whether GPL/AGPL sources can move beyond study-only use.
- Initial deployment regions and expected mainland China, Hong Kong, and overseas network mix.
- Whether voice chat ever enters scope or Screener stays complementary to an existing voice application.
@@ -195,6 +195,14 @@ leaf-only。
- [MDN `getDisplayMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia)
- [W3C Screen Capture](https://w3c.github.io/mediacapture-screen-share/)
### Viewer 后台播放边界
当前 Viewer 使用一个持续存在、可听的 `<video autoplay playsinline>`,播放被浏览器拦截时保留显式用户手势入口;信令心跳由服务端 WebSocket ping 和浏览器原生 pong 完成。Chrome 把可听媒体、WebRTC 和 WebSocket 视为后台保留连接的活动,并允许隐藏页节流视觉更新;页面若被系统冻结或回收,Web 应用本身不能继续执行。WebKit 也会在页面可听时保留 iOS Web 进程。产品契约覆盖已经开始的音频和连接;隐藏页面的视频合成只代表呈现层。
一轮保留的 Chrome 151 双 Viewer 结果与该边界一致:后台标签页的 inbound、decoded 和 Opus RTP 计数继续增长,`requestVideoFrameCallback` 保持不变;前台 Viewer 的逐帧回调正常增长。这只证明该受控桌面样本的接收、解码和音频包连续性,不是可听性或手机生命周期证明。iOS 锁屏、页面回收,以及后台期间换父或重连后出现的新媒体仍进入真机矩阵;LiveKit 的 Safari issue 也区分了持续播放的既有音轨与后台新建音频元素。
来源(访问于 2026-08-21):[Chrome background tabs](https://developer.chrome.com/blog/background_tabs)、[Chrome Page Lifecycle](https://developer.chrome.com/docs/web-platform/page-lifecycle-api)、[WebKit audible-page process assertion](https://bugs.webkit.org/show_bug.cgi?id=173932)、[WHATWG media elements](https://html.spec.whatwg.org/multipage/media.html)、[LiveKit Safari background audio issue #1751](https://github.com/livekit/client-sdk-js/issues/1751)。
### Viewer 向电视输出边界
截至 2026-08-21,Remote Playback API 仍不能作为 live WebRTC 的可移植输出契约。
+3 -3
View File
@@ -37,13 +37,13 @@ Flagship; parallel; min run/smoke/rollback; benchmark later. Active UI/config/lo
- Access protocol/config/HTTP/storage/SQLite/signaling focused tests pass, including commit-first teardown and v1 rollback.
- Native wire/session tests enforce at most two authoritative children, no presence-created edge, stale-revision ignore, and one bounded unsupported-route failure per revision.
- Source caps pending/answered `peer-selected` at one per room, excluding Host ingress. Focused tests cover admission/release/rollback/STUN-only; exact-source Chrome proves active TURN/UDP media, Viewer progress, Host edge one and stop zero. Functional only.
- Host names/window audio/all-room routing/Host selected ingress are active. New AV stats pass 42 focused tests/typecheck; this is not audible proof.
- Exact `16f6eab` passed typecheck, both builds and 30 files/445 tests. Deploy preserved all recorded config/network/SQLite hashes; DB, routes, services, endpoints, site access, and old-endpoint 404 passed. It triggered no TURN/SFU session. Rollback is exact `22119b907d3cf03ce8b06d6fb4596ce1a26fedd7`; `fd76277b05d491af8840b28f3132b7ff445d3cbe` remains secondary.
- Host names/window audio/all-room routing/Host selected ingress are active. AV stats pass 42 tests/typecheck; a retained Chrome 151 dual-Viewer sample kept hidden-tab inbound/decode/Opus counters moving while its presentation callback stayed flat. Audible/mobile proof remains open.
- Exact `16f6eab` passed typecheck, builds and 445 tests; deploy preserved config/network/SQLite/services/routes. Rollback is `22119b9`; `fd76277` remains secondary.
## Unverified Boundaries
- The cutover is config evidence; the separate canary closes active Host-ingress relay/frame/cap/stop function. Initial ingress, peer last mile, external cohorts, admission rescue, quality/resources/performance, and game blur remain open.
- Mobile remains Viewer leaf-only. AirPlay/system mirroring is local output; live WebRTC `srcObject` has no portable in-app TV-output contract.
- Mobile is Viewer-only. Its persistent audible media element keeps media/signaling active while the page lives; iOS lock-screen, reclamation and background reconnection remain device gates. AirPlay/system mirroring is local output; live WebRTC `srcObject` has no portable in-app TV-output contract.
- Silent partitions can wait 30 to 60 seconds for heartbeat detection before the default 5-second grace; this remains unverified.
- The former release reportedly sustained bandwidth-limited blur on a capable LAN; Host refresh recovered while Viewer refresh did not. The new deployment has not yet reproduced or cleared it.
- ADR-0006 has one Viewer proof; two-edge/FIFO, hardware, endurance, public/downloaded-package, and browser-diversity proof remain open.
+1
View File
@@ -121,6 +121,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 Viewer 已通过浏览器要求的用户手势开始可听播放,When 页面切到后台且浏览器仍保留该页面,Then 同一个媒体元素、信令和 WebRTC 连接继续承载音频,返回前台后沿当前直播恢复画面而无需重新加入;后台视频合成或逐帧回调增长不作为连续播放承诺。Given iOS 锁屏、系统回收页面或后台期间产生新的媒体连接,Then 以当前真机行为为准,恢复时继续使用已有重连和显式播放入口。
- Given 用户在本机设置显示名,When 以 Host 或 Viewer 加入房间,Then 所有在线参与者看到同一份服务端权威 roster、对应房间标题和“名称 + room-scoped peer 后缀”;刷新后本机名称仍在,清除站点数据后恢复未命名默认值,数据库中不存在显示名或成员记录,展示身份不参与授权或路由。
- Given 手机从 Wi-Fi 切换到蜂窝网络或页面从后台恢复,When 原候选对失效,Then 客户端执行 ICE restart 或重建连接,并显示恢复进度而不是永久黑屏。
- Given Viewer 尝试把直播输出到电视,When 浏览器/系统提供已验证的 Remote Playback、AirPlay 或屏幕镜像能力,Then 该动作只改变本机输出设备,现有 upstream PeerConnection、TURN/SFU/peer route 和其他参与者保持不变。Given live `srcObject` 未经目标设备证明或 API 缺失,Then 产品不显示伪可用 Cast/AirPlay 按钮,也不创建自有 receiver 或转码服务器。