fix(sfu): isolate Browser ICE servers (#235)

fix(sfu): isolate Browser ICE servers
This commit is contained in:
AAA authored and GitHub committed 2026-08-24 20:29:36 +08:00
commit 246e9cc596
15 files changed
+57 -40

No files matched your search

+2 -2
View File
@@ -14,8 +14,8 @@ rtc:
allow_tcp_fallback: false
# Use the deployment-owned STUN listener for server public-IP discovery and
# avoid LiveKit substituting a public default in its join response. The
# accepted Screener Browser SFU connect contract uses an empty ICE-server list;
# ordinary peer edges receive this listener through application signaling.
# Screener Browser SFU connects use an empty ICE-server list; ordinary peer
# edges receive this listener through application signaling.
stun_servers:
- stun.example.com:3478
use_external_ip: true
+1 -1
View File
@@ -25,7 +25,7 @@
- [ADR-0001](./adr/0001-p2p-first-media-topology.md): historical P2P-first baseline; later access and automatic-routing decisions supersede its stale current-state details.
- [ADR-0002](./adr/0002-memory-resident-protected-rooms.md): four-digit leased in-memory rooms, local Host defaults, scoped Viewer grants, and orthogonal code entry.
- [ADR-0004](./adr/0004-peer-assisted-media-experiment.md): historical standard-WebRTC peer-assisted experiment and reusable evidence.
- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted P2P-first single-reconcile route model; its core is deployed, while the accepted Browser SFU ICE-server-isolation amendment remains pending and real-network validation is tracked in verification status.
- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted P2P-first single-reconcile route model; its core is deployed, Browser SFU ICE-server isolation is source-complete and production-pending, and real-network validation is tracked in verification status.
- [ADR-0006](./adr/0006-fixed-high-native-sender-canary.md): proposed fixed-`HIGH` native canary, current no-go result, and staged revalidation boundary.
- [ADR-0007](./adr/0007-demand-driven-dual-representation-quality.md): accepted path-isolated `HIGH + at most one LOW` policy, optional idle-layer stop, evidence contract, and SVC boundary.
- [ADR-0008](./adr/0008-window-scoped-audio-capture.md): browser window-audio hint and the Windows WASAPI process-loopback boundary.
@@ -362,15 +362,17 @@ deployment-wide.
## Current Source And Deployment Boundary
Production runs exact deployed application/runtime revision
`679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`; canonical
`main` contains the same runtime code. Current source and production run the
`679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`. Current source
adds exact Browser SFU ICE-server-isolation implementation
`ae09c760adec76fd26da611d4928486d105c6d3b`; both source and production run the
strict `screener-v11` Browser wire and use the direct/STUN peer and
LiveKit SFU/UDP route model, including the route, first-frame, typed-status, and
Host-only diagnostic contract described above. The operation owner is only
`route`. They still inherit LiveKit-provided STUN on Browser SFU PCs and do not
yet implement the accepted Browser SFU ICE-server isolation. Exact operational
evidence is owned by the deployment document; real heterogeneous-network and
SFU media validation remains open.
`route`. Current source uses empty external ICE-server lists on Browser SFU PCs;
production still inherits LiveKit-provided STUN and remains held until the
application cutover and physical Host/Viewer proof. Exact operational evidence
is owned by the deployment document; real heterogeneous-network and SFU media
validation remains open.
## Acceptance Boundary
+7 -6
View File
@@ -12,9 +12,10 @@ process provides the built Web client, room API, and WebSocket signaling behind
Caddy or nginx; ordinary peer ICE advertises only STUN, while Browser LiveKit
PCs configure no external ICE server and retain LiveKit-signaled UDP candidates.
LiveKit supplies bounded SFU fallback capacity. Normal media remains distributed
through direct or peer edges whenever those paths work. Exact production release
`679fe3e` still inherits the LiveKit join response's STUN endpoint and has not
implemented this Browser SFU ICE-server isolation.
through direct or peer edges whenever those paths work. Current source
implementation `ae09c760adec76fd26da611d4928486d105c6d3b` supplies that Browser
override; exact production release `679fe3e` still inherits the LiveKit join
response's STUN endpoint.
A deployment may additionally provide one dedicated single-node LiveKit process
as the current controller's automatic final media fallback. This capacity is
@@ -462,9 +463,9 @@ webhook, external-TURN, and embedded-TURN service. It explicitly sets
`tcp_port: 0` and `allow_tcp_fallback: false`, and points `stun_servers` at the
deployment's self-hosted STUN listener for server-side public-IP discovery and
to prevent pinned LiveKit from substituting a public default in its join
response. The accepted Screener Browser publisher/subscriber connect override is
an explicit empty list, so those SFU PCs do not use either response after that
pending application change is deployed. Do not add Redis for this one-node workload.
response. Current Screener source gives Browser publisher/subscriber connects an
explicit empty list, so those SFU PCs do not use either response after the
pending application cutover. Do not add Redis for this one-node workload.
The service journal is the diagnostic log; keep its retention finite and access
restricted. Pinned LiveKit 1.13.5 includes raw PublisherOffer SDP in info-level
join records, so the tracked production baseline uses `logging.level: warn` and
+4 -4
View File
@@ -28,18 +28,18 @@ Last updated: 2026-08-24
## Current Source And Production
- Production runs exact deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`, on the single strict `screener-v11` Browser wire; canonical `main` contains the same v11 runtime code, and auxiliary branches or older worktrees do not supersede it.
- Current source and production admit up to `20` Viewers and implement the uniform `1/2/3` endpoint cap, exact prepare candidate, first-decoded-frame commit, strict rollback revision, decoded-progress stall, a two-stage direct/SFU operation deadline, and one event-driven room controller. A short-lived exact-generation decoded-frame observer proves only the pending candidate inside the existing total deadline; the periodic stats sampler remains responsible for active-path diagnostics and stalls. Ordinary peer ICE is STUN-only and the sole application fallback is SFU/UDP; stale TURN environment keys fail startup. SFU admission uses exact publication and Viewer-subscription handles with explicit no-default ingress/egress capacities and a listener-fenced dedicated LiveKit owner. The deployed Browser still inherits LiveKit-provided STUN on its SFU PCs and therefore does not yet implement the accepted Browser SFU ICE-server isolation.
- Production runs exact deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`, on the single strict `screener-v11` Browser wire. Current source retains that v11 contract and adds exact implementation `ae09c760adec76fd26da611d4928486d105c6d3b`; auxiliary branches or older worktrees do not supersede canonical `main`.
- Current source and production admit up to `20` Viewers and implement the uniform `1/2/3` endpoint cap, exact prepare candidate, first-decoded-frame commit, strict rollback revision, decoded-progress stall, a two-stage direct/SFU operation deadline, and one event-driven room controller. A short-lived exact-generation decoded-frame observer proves only the pending candidate inside the existing total deadline; the periodic stats sampler remains responsible for active-path diagnostics and stalls. Ordinary peer ICE is STUN-only and the sole application fallback is SFU/UDP; stale TURN environment keys fail startup. SFU admission uses exact publication and Viewer-subscription handles with explicit no-default ingress/egress capacities and a listener-fenced dedicated LiveKit owner. Current source applies fresh empty ICE-server options to Browser SFU publisher/subscriber connects; deployed release `679fe3e` still inherits LiveKit-provided STUN and remains under the route hold.
- Current source and production use the memory-resident room model: random free four-digit codes, the configurable dormant lease, exact-Host resume, restart loss, local creation-preference replay, orthogonal Viewer grants and `open | password | disabled` code entry, and direct invitation/policy controls. SQLite room persistence, `ROOM_DATABASE_PATH`, `ROOM_TTL_SECONDS`, and a writable room StateDirectory are absent from the current runtime.
- Exact production artifacts, services, ports, and any change-scoped infrastructure recovery boundary are owned by [deployment](./deployment.md) and indexed by [status](./status.md).
- Current source and production require v11, fix Browser direct, browser-relay, and SFU media to VP8, leave video `contentHint` unset, and contain no codec UI, quality state, wire field, fallback media codec, or share-lifetime codec branch. Both use `shareGeneration`-fenced Pause/Resume and implement live 64/128/256 kbps audio-ceiling mutation, typed first-frame Viewer presentation, privacy-safe on-demand route diagnostics, neutral room-code denial, responsive entry controls, exactly three recommended profiles with `1080p30` as default and advanced-only `854x480`.
- Browser SFU subscribers reconcile eligible Host screen publications across connect/activate event ordering, participant/track arrival, and reconnect. Production LiveKit logs only warn/error, and the application service has a bounded same-host LiveKit readiness preflight.
- Exact v11 implementation `f5a295c52e0ac7d18e5a7949217861c7aa74e9c9` passed the current automated source gates and is integrated into deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09` and canonical `main`; deployment postflight passed. It still has no physical direct, browser-relay, or SFU codec evidence. Retained v10 evidence remains bounded to its tested revisions. Exact results are owned by [verification status](./verification-status.md), while current artifacts and operations are owned by [deployment](./deployment.md).
- Browser SFU ICE-server isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b` passed TypeScript, all 605 Web tests in 45 files, both production builds, repository hygiene, and independent review. Production deployment and exact Host/Viewer physical media proof remain pending.
- Chrome loopback, cap2/cap3, short resource, recovery, MBB, and A/V fixtures are bounded evidence only. They do not establish quality, resource limits, or product policy.
## Current Priority
1. Implement and deploy Browser SFU ICE-server isolation, then prove Host publication and Viewer first-frame media under the reproducing TUN path and a mobile network.
1. Deploy Browser SFU ICE-server isolation, then prove Host publication and Viewer first-frame media under the reproducing TUN path and a mobile network.
2. Diagnose the screen-audio `1 kbps` readout and physically validate live audio ceilings.
3. Then physically validate exact direct, browser-relay, and SFU codec behavior on deployed Browser v11, refine the invitation UI, and finish real-network route acceptance. Browser VP8 hardware acceleration and mobile Viewer lifecycle remain Accepted Later; Native/executable, distribution, and repository-wide simplification remain later phases.
+4 -3
View File
@@ -7,9 +7,10 @@
transport roles are in [ADR-0005](../adr/0005-automatic-hybrid-media-routing.md).
Production runs exact deployed application/runtime revision
`679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`; canonical
`main` contains the same runtime code. Current Browser source and production
implement the route transaction and diagnostics on strict `screener-v11`.
Real-network validation remains in
`main` adds Browser SFU ICE-server-isolation implementation
`ae09c760adec76fd26da611d4928486d105c6d3b`; production does not yet include
it. Source and production retain the route transaction and diagnostics on
strict `screener-v11`. Real-network validation remains in
[verification status](../verification-status.md).
## Current Transport Conclusion
+4 -3
View File
@@ -37,9 +37,10 @@ Current high-signal boundary:
public SFU candidate directly; ordinary peers and LiveKit server-side public
IP discovery retain deployment STUN. Production exact deployed
application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`,
release `679fe3e`, uses strict `screener-v11`; canonical `main` contains the
same v11 runtime code but has not implemented or deployed that accepted
Browser SFU ICE-server isolation. The route uses one short-lived
release `679fe3e`, uses strict `screener-v11`; current source adds exact
Browser SFU ICE-server-isolation implementation
`ae09c760adec76fd26da611d4928486d105c6d3b`, while production has not deployed
it. The route uses one short-lived
exact-generation decoded-frame observer only for the pending candidate inside
the existing total deadline; the periodic stats sampler still owns active-path
diagnostics and stalls. Real external-network and SFU media evidence remains
+7 -6
View File
@@ -17,19 +17,20 @@ This is the current execution index. Git history owns completed timelines; [veri
## Current Source
- Canonical root `main` is the integration truth; auxiliary branches and older worktrees do not supersede it. Current canonical `main` contains the same strict Browser `screener-v11` runtime code as deployed application revision `679fe3e7af634309322bea83b316641f51ad3d09`, rejecting every other wire before room authority.
- Canonical root `main` is the integration truth; auxiliary branches and older worktrees do not supersede it. Current source keeps strict Browser `screener-v11`, rejects every other wire before room authority, and adds Browser SFU ICE-server isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b` beyond deployed application revision `679fe3e7af634309322bea83b316641f51ad3d09`.
- Current source implements one Host plus up to `20` Viewers, one steady outbound media-copy cap for every non-server endpoint (default `2`, static `1/2/3`), and the process-memory room model with random four-digit codes, a default 24-hour dormant lease, exact-Host resume, restart loss, local Host preference replay, independent token invitations, `open | password | disabled` code entry, and no SQLite runtime.
- One event-driven controller owns the committed graph and at most one room-serial child operation. It uses one deterministic candidate list/cursor and one total direct-then-SFU deadline; exact admission and physical resources remain charged through drain, and the pending candidate commits only after an exact-generation decoded-frame proof. A short-lived 100 ms stats observer proves only that candidate inside the existing deadline, while the 2-second sampler remains responsible for active-path diagnostics and decoded-frame stalls. Healthy edges remain sticky and current-path quality does not authorize reparenting.
- Ordinary peer ICE is STUN-only and the only application fallback is the dedicated LiveKit SFU over UDP. SFU generations use explicit no-default ingress/egress capacities, exact `reserved | committed | draining` accounting, delete-plus-absence release, one Host publication, and exact Viewer subscription handles. No Screener TURN, ICE/TCP, media TCP, or TLS-relayed media route exists.
- Current Browser SFU publisher and subscriber connects do not yet supply the accepted empty ICE-server override. Isolated Host A/B evidence passed `8/8` when external client ICE servers were absent and standard ICE used LiveKit-signaled SFU candidates, without TURN, another port, or a longer deadline.
- Current Browser SFU publisher and subscriber connects supply fresh `autoSubscribe: false` plus `rtcConfig: { iceServers: [] }` options. Ordinary peers retain deployment STUN; LiveKit signaling candidates, server-side public-IP discovery, route deadlines, ports, and retry behavior are unchanged.
- Current source leaves video `contentHint` unset and keeps audio `contentHint = "music"`. Browser direct and browser-relay offers contain VP8 as their only media codec, and SFU publication explicitly uses VP8 with no backup codec. Codec UI, quality state, wire fields, fallback media codecs, and share-lifetime codec branches are absent. Live 64/128/256 kbps audio-ceiling mutation and ordinary `shareGeneration`-fenced Pause/Resume remain unchanged.
- Current source implements typed first-frame Viewer presentation and recovery, Chinese user-facing route/access failures, privacy-safe failed-page export, authenticated Host-only on-demand route snapshots, neutral `ROOM_ACCESS_DENIED` room-code admission, and responsive entry controls.
- Recommended quality remains exactly `1080p60`, `1080p30`, and `720p30`; current source defaults to `1080p30`. Advanced resolution adds `480p` as `854x480` without adding a fourth preset, and advanced FPS and bitrate remain independent.
- Exact v11 implementation `f5a295c52e0ac7d18e5a7949217861c7aa74e9c9`, integrated into deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09` and canonical `main`, passed the current automated source gates. Deployment postflight passed, but no physical direct, browser-relay, or SFU codec path was exercised; retained v10 loopback evidence applies only to that older source. Exact results are owned by [verification status](./verification-status.md).
- Exact SFU isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b` passed repository hygiene, TypeScript, all 605 Web tests in 45 files, client/server production builds, and three independent code reviews with no finding. It is not deployed and has no exact product Viewer first-frame evidence.
## Current Milestone
1. Implement and deploy the accepted Browser SFU ICE-server isolation, then prove exact Host publication and Viewer first-frame media under the reproducing TUN path and a mobile network.
1. Deploy the source-complete Browser SFU ICE-server isolation, then prove exact Host publication and Viewer first-frame media under the reproducing TUN path and a mobile network.
2. Diagnose the reported screen-audio `1 kbps` readout and physically validate live audio ceilings.
3. Physically verify the deployed `screener-v11` fixed-VP8/no-video-hint direct, browser-relay, and SFU paths from actual codec, capture, outbound, and decoded stats.
4. Refine the Host invitation controls without changing grant semantics implicitly.
@@ -41,14 +42,14 @@ This is the current execution index. Git history owns completed timelines; [veri
- The desktop Host background/minimized report is deferred until a current-production real-game reproduction supplies synchronized media and CPU/GPU evidence. Mobile Viewer background playback and relay survival remain a separate Accepted Later lifecycle gate.
- Open PR #192 and the Native stack are evidence/research, not pending product releases. Native senders, capture helpers, shared-encode executables, and their test binaries are outside the current Browser milestone and are not built or run.
- Deployed surfaces and retained candidates that still need product decisions are indexed only in [the TODO ledger](./todo.md); do not extend or roll them back automatically.
- Room lifetime, authorization/storage semantics, restart loss, entry/presentation, and the Browser v11 contract are aligned between source and production. This application-only cutover reused unchanged infrastructure and configuration and does not maintain a full rollback/configuration backup; any future infrastructure or irreversible-state change requires recovery scoped to the surfaces it actually changes.
- Room lifetime, authorization/storage semantics, restart loss, entry/presentation, and the Browser v11 wire remain aligned between source and production; Browser SFU ICE-server isolation is source-only until the next application release. The prior application-only cutover reused unchanged infrastructure and configuration and does not maintain a full rollback/configuration backup; any future infrastructure or irreversible-state change requires recovery scoped to the surfaces it actually changes.
- Real SFU recovery, heterogeneous networks, mobile lifecycle, audio/A-V device behavior, and endurance/resource measurements remain external acceptance evidence, not blockers for unrelated reversible work.
## Current Hold
Production has an active P1 core-route hold: Browser SFU initial ICE is
intermittent under the reproduced Mihomo TUN path; the best-supported cause is
the PC's external-STUN/SFU association conflict. The accepted Browser SFU
ICE-server isolation must be source-validated, deployed, and physically proven before
the PC's external-STUN/SFU association conflict. Browser SFU ICE-server
isolation is source-validated but must be deployed and physically proven before
the route hold closes. Native/executable work and broad repository cleanup
remain outside the current evidence boundary.
+1 -1
View File
@@ -6,7 +6,7 @@ Only items in **Now** are executable after their stated decision gate. A branch
## Now
1. **Restore reliable Browser SFU initial ICE.** Apply `rtcConfig: { iceServers: [] }` to both pinned LiveKit publisher and subscriber connects so each SFU PC retains only LiveKit-signaled remote candidates as standard ICE inputs. Keep ordinary peer STUN and LiveKit server-side public-IP discovery unchanged; do not restore TURN, add a port, constrain candidate type/count, extend the route deadline, or add another recovery stage. Add focused connect-option tests, deploy one immutable application artifact, and close the P1 hold only after exact Host publication plus Viewer first-frame media passes under the reproducing TUN path and a separate mobile network.
1. **Deploy and physically prove Browser SFU ICE-server isolation.** Source implementation `ae09c760adec76fd26da611d4928486d105c6d3b` and its focused/full automated gates are complete. Deploy one immutable application artifact without changing LiveKit, coturn, nginx, systemd, firewall, ports, route deadline, or retry behavior. Close the P1 hold only after exact Host publication plus Viewer first-frame media passes under the reproducing TUN path and a separate mobile network; do not gate on candidate type/count or restore TURN.
2. **Diagnose and physically validate live screen audio.** First reproduce the Host diagnostic remaining at `1 kbps` after switching the shared source, and distinguish stale/reset statistics from an actual RTP bitrate problem. The app already requests audio and supplies system/window audio hints; record the selected surface, returned audio track, sender/receiver counters, and audible result because the browser owns the picker and may still return video only. Then switch the 64/128/256 kbps ceilings across direct, browser-relay, and SFU paths, create a new edge, and switch source while checking route continuity and A/V synchronization. Do not infer fidelity or room-wide atomic convergence from configuration alone.
3. **Physically validate fixed Browser VP8 with no video hint.** Production exact deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`, release `679fe3e`, already runs the strict v11 wire, VP8-only direct/browser-relay offers, VP8 SFU publication with no backup codec, unset video `contentHint`, and no codec UI/state/wire. Confirm actual codec, capture, outbound, and decoded stats on direct, browser-relay, and SFU paths; deployment postflight alone does not close this gate.
4. **Redesign the Host invitation controls.** Replace the current raw-link-heavy block with a compact copy-first layout while preserving the accepted copy-link, copy-room-code, code-entry policy, rotate, and revoke actions. Keep the credential out of logs and request URLs; changing the copied credential length is blocked on the explicit product decision below.
+2 -1
View File
@@ -19,6 +19,7 @@ Capacity and routing entries below describe the exact tested source or release o
## Retained Functional Evidence
- Exact v11 implementation `f5a295c52e0ac7d18e5a7949217861c7aa74e9c9`, integrated into deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09` and canonical `main`, passed TypeScript typecheck, all 605 Web tests in 45 files, client and server production builds, the 254-test SFU gate in 10 files, and the access/privacy gate with explicit Chrome. This validates source structure, strict-wire behavior, fixed-VP8 path configuration, build output, and the covered Browser gate only; it provides no physical direct, browser-relay, or SFU codec evidence.
- Exact Browser SFU ICE-server-isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b` passed repository hygiene, TypeScript typecheck, all 605 Web tests in 45 files, client and server production builds, and three independent code reviews with no finding. Focused publisher/subscriber and ordinary-peer isolation coverage passed 95 tests in three files. This proves source option propagation and unchanged peer STUN behavior; production application deployment and exact Host/Viewer first-frame media remain open.
- Exact v10 runtime source `fdd5a4a529ff297f41c05ea3388bf484d76afe8f` passed repository hygiene, TypeScript typecheck, client and server production builds, all 610 Web tests in 45 files, the 257-test SFU admission gate, the access/privacy Browser gate, and the production-dependency audit with zero vulnerabilities. Its one-Host/20-Viewer Chrome 151 direct-loopback report passed all seven assertions: all Viewers decoded, the selected VP8 settings reached every participant, Host and relay media edges stayed within cap `2`, no orphan SFU publication appeared, and all four current-child timing distributions contained 20 values. The report SHA-256 is `802CBB7632E9AEA3C39FE831A7F7880D24140B2E83942CE0DFDA05DE4B408EED`. This validates the v10 source boundary, not H.264 quality, hardware attribution, physical capture, public-network behavior, or SFU packet flow.
- Chrome 151 synthetic `1/3/5/8` and 720p30 runs preserved bounded fanout and decoding. A `9461e20`-era three-Viewer rerun kept Host2/Browser Viewer1, decoded every Viewer, and recovered a hard first-level relay departure in 5,380 ms; it did not exercise quality-triggered MBB. Sixteen-Viewer cap2/cap3 loopbacks decoded all Viewers and a ten-second follow-up recorded guarded sender and aggregate Chromium CPU evidence, but resolution/FPS remained low and the ordinary-PC data cannot rank caps, select product policy, or prove sustainable heterogeneous-network quality. See [peer-assisted media](./research/peer-assisted-media.md).
- Chrome 151 with local LiveKit 1.13.5/client 2.22.0 proved one SFU/UDP root after `q,f` -> `q,h`: decoded frames advanced 3 -> 23, rendered frames reached 26, Host used one edge, and leaves were clean. This is functional evidence only. See [low-server media routes](./research/low-server-media-routes.md).
@@ -35,7 +36,7 @@ Capacity and routing entries below describe the exact tested source or release o
- Host background: deferred until the report reproduces on exact production with a continuously changing real game or replay, a separate direct wired Viewer, synchronized capture/outbound/inbound plus CPU/GPU evidence, and repeated focused/unfocused/hidden/minimized windows. The current-Chrome Browser `getDisplayMedia()` WPF-window screening did not observe an immediate Host-page media drop, and the old harmful `contentHint = "motion"` release remains a plausible confound rather than a proven background cause. Current evidence authorizes no keepalive, Wake Lock, timer, codec switch, route change, or Native fallback.
- Relay resources: current v11 source and production expose the authenticated `1/2/3` endpoint-cap boundary, and retained v10 local loopback evidence covers 20 Viewers at cap `2` only for that source. CPU/GPU/upload and heterogeneous-network measurements remain diagnostics, not authority to change the contract.
- Room scale: current source and production admit 20 Viewers plus one Host, and the retained v10 local Browser convergence gate covers that bound on direct loopback. A real public-network 1:20 session, quality, and sustained resource matrix remain open.
- SFU: production uses one Host publication with exact Viewer subscriptions and no fixed root-count or room-wide lease rule, but deployed Browser SFU PCs still mix the LiveKit-provided STUN endpoint with the public SFU candidate and are held on the reproduced TUN failure. After the accepted empty-ICE-server client rule is deployed, exact Host publication plus Viewer first-frame media must pass on that TUN path and a separate mobile network. Real LiveKit lifecycle/JWT replay, shaped packet-flow, BWE downshift/recovery, resource use, and SFU-fed first-child evidence remain open. Use Linux `tc` or an authorized public canary for per-leaf shaping, never CDP throttling.
- SFU: production uses one Host publication with exact Viewer subscriptions and no fixed root-count or room-wide lease rule, but deployed Browser SFU PCs still mix the LiveKit-provided STUN endpoint with the public SFU candidate and are held on the reproduced TUN failure. Source now implements the accepted empty-ICE-server client rule; after deployment, exact Host publication plus Viewer first-frame media must pass on that TUN path and a separate mobile network. Real LiveKit lifecycle/JWT replay, shaped packet-flow, BWE downshift/recovery, resource use, and SFU-fed first-child evidence remain open. Use Linux `tc` or an authorized public canary for per-leaf shaping, never CDP throttling.
- Audio: verify the 64/128/256 kbps Share settings, negotiated/observed bitrate, audible music quality, route changes, and game A/V synchronization. Bitrate settings are ceilings, not quality proof.
- Observability: the current v11 Viewer stage, local stats/export plumbing, identity-bound relayed-detail retention, export freshness guards, and on-demand Host route snapshot are deployed. Target-browser availability and actual values remain unverified for Host SFU sender evidence, codec/fmtp and encoder implementation/power efficiency, media-source and encoded FPS, A/V playout/jitter/concealment, selected candidate endpoints, and bounded same-pair STUN-response observation. All fields diagnose and have no recovery authority; they do not by themselves prove hardware encode, synchronization quality, or route quality.
- Mobile: Android/iOS remain Viewer-only. Autoplay, rotation, iOS lock-screen/page reclamation, background reconnection, and network changes need device evidence. AirPlay/system mirroring is Viewer-local output, not a portable in-app WebRTC output contract.
+3 -3
View File
@@ -2,7 +2,7 @@
## 2026-08-18 14:45
状态:production 运行精确 deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`、release `679fe3e`;canonical `main` 包含同一套 v11 runtime code。两者使用严格单一 `screener-v11`;Browser display video 不设置 `contentHint`、audio 保留 `music`,唯一视频媒体 codec 为 VP8,UI、quality state/wire 和分享生命周期均没有 codec 分支。Pause/Resume 继续由当前 Host session 和 `shareGeneration` 约束。
状态:production 运行精确 deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`、release `679fe3e`;current source 在同一严格 `screener-v11` runtime 上增加 Browser SFU ICE-server-isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b`,尚未部署。Browser display video 不设置 `contentHint`、audio 保留 `music`,唯一视频媒体 codec 为 VP8,UI、quality state/wire 和分享生命周期均没有 codec 分支。Pause/Resume 继续由当前 Host session 和 `shareGeneration` 约束。
## 目标与边界
@@ -13,7 +13,7 @@
- 分享者主动选择屏幕、窗口或标签页,并请求可用音频;
- 创建四位随机数字房间;production site access 密码严格控制建房/发布和 code-only 观看,默认 room-scoped capability link 让受邀 Viewer 直接观看,房间控制状态只驻留当前进程内存;
- 每名观看者拥有独立的 `RTCPeerConnection`;
- 当前 production 要求 STUN,普通 peer ICE 只发 STUN servers;已接受但尚未实现/部署的 Browser SFU target 使用空 ICE-server 列表、保留 LiveKit signaling 的 UDP candidates 并由标准 ICE 选择;
- 当前 production 要求 STUN,普通 peer ICE 只发 STUN servers;current source Browser SFU PC 使用空 ICE-server 列表、保留 LiveKit signaling 的 UDP candidates 并由标准 ICE 选择,该改动尚未部署;
- 展示连接状态、direct/relay、RTT、实际码率、帧率和丢包等数据;
- 超过部署配置上限的观看者被明确拒绝,不静默超载;
- 在代码、测试和真实浏览器验证完成前,不宣称达到延迟或画质目标。
@@ -360,7 +360,7 @@ Token-free SFU standby prewarm 保持可选且不创建 participant、publicatio
## 当前交付边界
- Production 运行精确 deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`、release `679fe3e`;canonical `main` 包含同一套 v11 runtime code。Current source 与 production 使用严格单一 `screener-v11` wire;Browser 固定 VP8 且 video 不设置 `contentHint`,codec selector、quality-state/wire 字段与分享生命周期 codec 分支不存在。
- Production 运行精确 deployed application/runtime revision `679fe3e7af634309322bea83b316641f51ad3d09`、release `679fe3e`;current source 增加 Browser SFU ICE-server-isolation implementation `ae09c760adec76fd26da611d4928486d105c6d3b`,尚未部署。两者使用严格单一 `screener-v11` wire;Browser 固定 VP8 且 video 不设置 `contentHint`,codec selector、quality-state/wire 字段与分享生命周期 codec 分支不存在。
- Pause/Resume 由当前 Host session 和 `shareGeneration` 约束。Host 后台性能和 VP8 hardware acceleration 分别按受控根因证据诊断;标准 ICE/SFU 按真实异构网络验收。
- 当前发布面只包含 Web Host、Viewer 和 browser relay。Native sender、capture helper、shared-encode executable 与两个分发包仍由各自后续决策和物理证据驱动,不属于当前 Browser release。
+8
View File
@@ -0,0 +1,8 @@
import type { RoomConnectOptions } from "livekit-client";
export function sfuRoomConnectOptions(): RoomConnectOptions {
return {
autoSubscribe: false,
rtcConfig: { iceServers: [] },
};
}
+2 -3
View File
@@ -29,6 +29,7 @@ import {
createStatsAccumulator,
type StatsAccumulator,
} from "../webrtc/stats";
import { sfuRoomConnectOptions } from "./connection-options";
export interface SfuConnectionConfig {
url: string;
@@ -141,9 +142,7 @@ export class SfuPublisher {
}
});
await room.connect(config.url, config.token, {
autoSubscribe: false,
});
await room.connect(config.url, config.token, sfuRoomConnectOptions());
if (!this.owns(room, generation)) {
await safeDisconnect(room);
return false;
+2 -1
View File
@@ -16,6 +16,7 @@ import {
type StatsAccumulator,
} from "../webrtc/stats";
import { observeDecodedFrameProof } from "../media/decoded-frame-proof";
import { sfuRoomConnectOptions } from "./connection-options";
interface SubscriberEvents {
onStream: (stream: MediaStream | null) => void;
@@ -92,7 +93,7 @@ export class SfuSubscriber {
this.sdk = sdk;
this.bindRoomEvents(room, sdk, generation);
await room.connect(config.url, config.token, { autoSubscribe: false });
await room.connect(config.url, config.token, sfuRoomConnectOptions());
if (!this.owns(room, generation)) {
await safeDisconnect(room);
return false;
+2
View File
@@ -569,6 +569,7 @@ describe("SfuPublisher", () => {
expect(room.options).toEqual({ dynacast: false });
expect(room.connect).toHaveBeenCalledWith(connection.url, connection.token, {
autoSubscribe: false,
rtcConfig: { iceServers: [] },
});
expect(room.localParticipant.publishTrack).not.toHaveBeenCalled();
@@ -1478,6 +1479,7 @@ describe("SfuSubscriber", () => {
await expect(connecting).resolves.toBe(true);
expect(room.connect).toHaveBeenCalledWith(connection.url, connection.token, {
autoSubscribe: false,
rtcConfig: { iceServers: [] },
});
expect(hostVideo.setSubscribed).not.toHaveBeenCalled();
expect(streams).toEqual([]);