Files
Piik/docs/standards/media-status.md
T
AAA 01821ae7ac fix(connection): retry startup and clarify sharing status
Public invitations could stop after an early tunnel-process exit, and connection progress and Viewer status did not consistently describe the current attempt or Host state. This maintenance release adds bounded startup retries, aligns enhanced NAT retry feedback across entry paths, and fixes camera-preview and room-entry layout.

The existing route owner and published contracts remain in place. Four-attempt progress is advertised and opted into; older readers retain supported messages. Interaction/chat experiments are outside this PR.

Validation: npm run check (74 files, 1072 tests and production build), npm run check:go (including Windows capture compile), documentation/repository hygiene, 10 production Viewer-entry discovery cases, and a real public-link gate with remote HTTP/WebSocket access and shutdown cleanup all passed. Existing device/network evidence limits remain documented.

## Release notes

### 中文

这是一次维护更新,重点改善公网邀请启动、连接重试反馈和分享状态提示,并修正两处界面布局问题。

- 公网邀请服务在连接就绪前意外退出时,会自动重试,最多重试 3 次;所有尝试仍共用 30 秒启动预算。
- 增强穿透连接在首次尝试失败后最多重试 3 次,重试进度显示为 1/3、2/3、3/3。邀请链接和房间号加入都支持新版进度提示。
- 修正观众状态提示:房主离线时不再误报“没有可用的媒体线路”,服务器连接恢复与媒体恢复也会分别呈现。
- 修正电视内房间号输入界面的居中位置,以及摄像头选择预览被裁切的问题。
- 尚未确认来源声音状态时,不再提前提示“未分享来源声音”。

本次保持现有版本兼容;新版重试进度需要页面与服务端均支持。额外重试不能保证所有网络都能直连。

### English

This maintenance update improves public invitation startup, connection retry feedback, and sharing status messages, with two layout fixes.

- If the public invitation service exits before connecting, Piik retries up to three times within the existing shared 30-second startup budget.
- Enhanced NAT traversal now allows up to three retries after the initial attempt, shown as 1/3, 2/3, and 3/3. Both invitation links and room-code entry support the updated progress display.
- Viewer status now distinguishes an offline host from an unavailable media route, and reports server reconnection separately from media recovery.
- Fixed the alignment of room-code entry inside the TV and cropping in camera-selection previews.
- The missing-source-audio notice now waits until the source's audio availability is known.

Existing version compatibility is preserved. Updated retry progress requires support from both the page and server. Additional retries cannot guarantee a direct connection on every network.
2026-09-23 22:27:56 +08:00

8.4 KiB

Media Status

src/client/ui/media-status.ts owns the shared visual projection, demonstrated by /__status-preview. It is not a routing or quality controller. The existing presentation reducer continues to own playback facts; roster and quality evidence retain their own authority. Overlay, indicators, notices and title are consumers, not truth sources.

Frontend controls, names and details share Tooltip, following the visual language. Its native Popover top layer escapes scrolling containers, with viewport-relative placement. Hover, keyboard focus and touch hold share one visibility owner; Escape dismisses even a mouse-only hint. /__tooltip-preview shows the catalogue. Playback actions and their local audio ownership are defined in presentation lifecycle; /__playback-preview exercises the actual control bar with generated local media.

Status Meaning

Keep three questions separate: is the media path available, is this picture playing, and is this particular stream limited? An available path does not prove excellent quality. One weak child does not make its parent's received picture or a healthy sibling unhealthy.

The shared visual language owns colours, cast, shapes, panel accents and motion. This document owns the evidence and scope that select those meanings. Current StatusDescriptor tone and progress take precedence over a reused comic's default; text and pure-visual tooltips retain that context.

Projection Rules

  • Overlay: appears when there is no usable picture, an intentional Host pause, or a required user action. Ordinary quality warnings never cover playback. Initial connection guidance is not an error even though it occupies the stage.
  • Television: one media-status icon sits inside the lower television frame (lr-tv-chin). Every mode explains it with the same comic tooltip; text modes add the specific localized status beneath the scene. Both reuse Tooltip for hover, keyboard focus, touch hold and viewport placement; no native title competes with the custom status hint. There is no permanent text bubble, additional round lamp, or repeated control-menu caption. The Host television describes its local source, not an arbitrary outbound child. A confirmed limitation may colour the relevant icon amber while the page title still says watching.
  • Host couch: each Viewer has one round lamp. Grey means waiting for the share, blue means waiting for the media path, green means committed mediaReady, and amber means a recent receive freeze. The Host's own pawn has no duplicate lamp. deriveParticipantStatus supplies both the couch and Host overview; neither stores another copy of the status.
  • Viewer couch: pawns have no round lamps. While awaiting media readiness a pawn's body breathes gently; it becomes still when ready. This expresses the same roster fact without claiming to know other Viewers' quality.
  • Header: the page's connection to the room server. Its control-link comics show a Browser and server, not a failed video path. A media-route failure can coexist with a healthy server connection, and vice versa.
  • Connection notice: signaling recovery may coexist with healthy media. It cannot convert proved playback into waiting or hide media recovery. The presentation stage owns the primary media status; a coexisting notice never selects that status or asserts another connection's health.
  • Notices: necessary coexisting issues and operation feedback use the existing pills near the stage; they are not another primary media status. Raw PeerConnection errors remain diagnostic observations, not persistent red warnings after media recovers. The control menu does not repeat the television status or aggregate the first weak outbound edge into a global quality warning. The operation supplies its outcome tone and matching scene together. Neither the presence of an illustration nor a default checkmark proves success; partial application retains a limitation instead of claiming completion.
  • Source sound: every capture source with confirmed absent source audio keeps the same neutral notice and detail, including camera capture. This describes the captured input, not a failure or the mixed output's sound. The microphone control owns voice state separately; do not hide facts by source category or infer missing audio while capture details are unknown.
  • Host absence: without a proved current picture, a stopped/unknown Host means waiting for sharing, and an offline Host means waiting for return. A failed route does not override those facts. Retain route evidence so reconnection alone cannot claim media recovery; independent playback/server errors retain their meaning. An authenticated snapshot with an absent Host does not identify why the Host is absent: use neutral waiting. Only the explicit sharing-stop event establishes an intentional stop; do not reconstruct it from a retained share generation or remembered messages.
  • Topology: unready edges use the blue pending treatment. Readiness alone cannot distinguish initial connection from recovery, so this view does not invent a warning. Confirmed interruption remains owned by the status projection.
  • Title: keeps the primary activity, with a compact warning for an applicable problem. Losing focus alone never means waiting for media.
  • Recovery: every projection is recomputed from current facts. A warning requires current evidence; an expired or mismatched sample becomes unknown, not healthy or disconnected. A ready participant can therefore return to a green readiness lamp without claiming that its quality has recovered. No warning latch or additional timer is needed.

Evidence And Integration Boundary

Use WebRTC connectionState for transport explanation, not first-frame proof. disconnected may recover; failed is terminal for that connection. Closing a retired connection is not an error in the replacement connection. qualityLimitationReason describes an outbound encoder. A relay's sender warning must never become a warning about its own inbound picture. Low FPS, resolution or bitrate alone does not prove poor quality; a static screen or a small source can legitimately need little data. Do not introduce UI thresholds or a new quality score.

Current roster messages expose committed mediaReady to both roles, not a complete remote quality/failure state. Missing readiness means waiting or recovery, not confirmed disconnection; departed participants leave the roster. Viewer receive evidence is shared with its parent and the Host, not with every other Viewer. No additional remote-quality broadcast is needed.

The Host's amber participant lamp requires an active share, committed readiness, fresh receive evidence for the current upstream, and a positive freezeCountDelta or freezeDurationMsDelta. The existing evidence-expiry path clears stale warnings. Hidden, paused and other diagnostic-only windows provide no freeze proof; low FPS, resolution or bitrate is not a substitute.

All *Delta metrics describe one observation window and never inherit an older non-null value. Non-window fields retain the existing details-display cache. Participant status reads the current evidence directly; it adds no stored status, timer, threshold or score. Detailed sender/receiver metrics remain available in connection details and Debug with their original scope.

Previews render the production projection and metric components with explicit sample inputs. They do not add quality facts absent from the real workflow.

References

We reuse these distinctions and the existing Piik owners, not a new SDK, scoring algorithm or transport policy.