## Problem and outcome / 问题与结果 This phase adds lightweight room interaction without making media depend on chat, and adds Windows source-audio exclusion and optional SFU-only hosting at their existing owners. It also corrects confirmed encoder/capture ownership and native color-conversion defects. Host microphone commentary remains on the shared media path; room voice and 4K are outside this phase. ## Release notes ### 中文 这是一次功能更新:Piik 加入了文字聊天与表情互动,并完善了 Windows 声音采集、画面颜色和自部署选项。 #### 新功能 - **边看边聊。** 在可移动、可缩放的聊天窗口中发送消息,或开启弹幕。停止分享后,房间中的朋友仍可继续聊天。 - **表情互动。** 点击沙发上的人物,给自己发表情,或把番茄等表情送给朋友;各端按同一事件显示动画。 - **排除应用声音。** Windows App 分享整个屏幕时,可排除一个应用及其子进程的声音,适合同时使用语音软件。所选应用退出后,来源声音停止,避免恢复为未过滤的系统声音。 - **可选的纯 SFU 模式。** 自部署管理员可让共享画面和声音统一通过媒体服务器转发。默认仍为优先 P2P;App 公网邀请保持纯 P2P。 - **Windows HDR 转 SDR。** 原生采集与缩略图自动将 HDR 来源转换为 SDR,沿用现有观看链路。 #### 修复与改进 - 修复原生颜色转换的范围与矩阵处理,避免已复现的暗部丢失、高光裁切和颜色偏差。 - 修复共享编码器切换时使用过期需求或过期帧信息的问题,保护正在观看的画面;修复换源后旧采集事件可能影响新来源的问题。 - 统一新控件、浮窗与来源选择文案,补充中英文使用说明。 #### 使用与升级 聊天与表情需要新版站点页面和 Server;声音排除需要新版页面与支持此能力的 Windows App。聊天只保留本页最近收到的消息,刷新后清空,不补发历史,且不提供端到端加密。 HDR 转换输出为 SDR,不代表端到端 HDR 或多声道支持。既有房主麦克风与立体声能力保留。 ### English This feature update brings text chat and reactions to Piik, alongside improvements to Windows audio capture, picture colors and self-hosting options. #### New features - **Chat while watching.** Send messages in a movable, resizable window, or enable on-screen chat. Friends can keep chatting after the host stops sharing. - **Reactions.** Select a person on the sofa to react above yourself or send a tomato and other reactions to a friend. Participants animate the same shared event. - **Exclude application audio.** When sharing a whole screen with Windows App, exclude one application and its child processes, useful when using a separate voice app. Source audio stops if the selected app exits, preventing a return to unfiltered system sound. - **Optional SFU-only hosting.** Site operators can require shared video and audio to pass through the media server. P2P-first remains the default; App Public invite remains P2P-only. - **Windows HDR-to-SDR conversion.** Native capture and source thumbnails automatically convert HDR sources to SDR for the existing viewing path. #### Fixes and improvements - Correct native color-conversion ranges and matrices, addressing reproduced crushed shadows, clipped highlights and color shifts. - Correct stale demand and frame evidence during shared-encoder handoffs to protect the current picture. Prevent events from a replaced capture from affecting its successor. - Align new controls, floating panels and source-picker copy, with updated Chinese and English guides. #### Using this update Chat and reactions require updated site pages and Server. Audio exclusion requires updated pages and a Windows App that supports the capability. Chat retains only recent messages received by the current page, clears on refresh and does not replay history. It is not end-to-end encrypted. HDR conversion produces SDR; it does not add end-to-end HDR or surround sound. Existing host microphone commentary and stereo support remain available. ## Verification / 验证 - Web type checks, 78 test files / 1275 tests and production build: PASS. - Go core tests, formatting/vet and target builds: PASS; Darwin cgo remains platform-limited on this Windows runner. - Native build/check/color probes and synthetic HDR-to-SDR H.264/VP8 browser reception: PASS. - Access/privacy gate, Native H.264 SFU-only media gate and local Auto/H.264 Host gate: PASS. - Three real production pages: chat/reactions, stop/resume, idle-room join, host departure/return, offline draft recovery and invitation revocation: PASS. - Synthetic parent/child process-audio exclusion and target lifetime: PASS; no raw audio retained. - Windows candidate archive extraction and packaged Local startup/shutdown: PASS. - Documentation and website build: PASS. - [Candidate CI](https://github.com/TNTcraftHIM/Piik/actions/runs/36873766646) at `f26cd208d03bc0dcbe353f8cac217f993216b0a3`: Go core and race checks, Web tests, Server/container checks and Windows/macOS/Linux App packaging all PASS. Publication was skipped as intended. The owner accepted the UI/model and bounded local walkthrough for phase closure. Physical HDR/mixed displays, mobile keyboard, real voice applications across output devices and macOS/Linux capture remain unverified. Existing field reports without matched evidence are not claimed resolved. The owner authorized v1.7.0 publication on 2026-10-02. The final documentation-only commit records that authorization; product code matches the verified candidate above. ## Impact / 影响 Authorized version: **v1.7.0**, matching the local release planner. Current wire contracts remain Browser/server 23, Native control 9 and capture 7. Optional capabilities gate new functionality; existing room/media authority remains owned by the existing services. No new ports, message persistence, room voice or automatic room creation on page visit. Updated README, guides, standards, research evidence and TODO stay with the candidate phase.
281 lines
18 KiB
Markdown
281 lines
18 KiB
Markdown
# Configuration And Ports
|
|
|
|
The tracked [`.env.example`](../../.env.example) is the executable schema
|
|
companion; `internal/server/config` is validation truth. Keep real values in the
|
|
service secret store or an untracked access-restricted environment file.
|
|
|
|
## Ownership
|
|
|
|
- Deployment configuration owns listeners, advertised origins, persistence,
|
|
admission, capacity and optional services. Change it before starting the process.
|
|
- The Host owns share settings and the available per-share route switches in the
|
|
shared Web UI. Server and App use the same controls, order and semantics;
|
|
configuration changes availability, not which controls exist. A fixed switch
|
|
remains visible and explains the reason in text or its pure-visual hint.
|
|
- Protocol versions, queue bounds and routing/adaptation constants stay in code.
|
|
They are not deployment tuning knobs. Debug and report destinations are
|
|
explicit diagnostic options, not normal share settings.
|
|
|
|
## Application Environment
|
|
|
|
| Variable | Contract |
|
|
| --- | --- |
|
|
| `PIIK_ENV` | `development` or `production`, default `development`; required for every server deployment: `production` enables production-only validation and the `Secure` site-access cookie. |
|
|
| `LISTEN_HOST` | Defaults to `0.0.0.0`; bare-metal production normally uses `127.0.0.1`. |
|
|
| `PORT` | Positive TCP port, default `8787`; the tracked release wrapper supports only that default. |
|
|
| `PUBLIC_BASE_URL` | Exact public HTTP(S) origin; production requires HTTPS. |
|
|
| `ALLOWED_ORIGINS` | Unset or empty follows `PUBLIC_BASE_URL`. A non-empty comma-separated list replaces that default; include every trusted browser origin (scheme, host and port). Wildcard is invalid. |
|
|
| `SITE_ACCESS_PASSWORD` | Optional in every environment. Unset or empty allows entry without a site password. A configured value is matched exactly, including spaces and Unicode; there are no password length or character rules. General HTTP request limits still apply. Room ownership and Viewer admission remain independent. |
|
|
| `ROOM_DATABASE_PATH` | Hosted defaults to `rooms.sqlite` in its working directory when unset or blank. An explicit absolute file path selects another SQLite file; `:memory:` opts into process-memory room authority. App Local remains in memory. |
|
|
| `MAX_VIEWERS_PER_ROOM` | `1..20`, default `20`; excludes the Host. |
|
|
| `ENDPOINT_MEDIA_COPY_CAPACITY` | Shared endpoint steady-copy cap `1..3`, default `2`. |
|
|
| `STUN_URLS` | Comma-separated advertised `stun:` discovery URLs; at least one is required in production. These are not local bind addresses and may use an unproxied DNS name separate from the Web origin. |
|
|
| `STUN_LISTEN_HOST` | Hosted IPv4 STUN bind address, default `0.0.0.0` when `STUN_URLS` is configured; independent of HTTP `LISTEN_HOST`. Local App construction creates no STUN listeners. |
|
|
| `NAT_PREDICTION_ENABLED` | Optional bounded NAT prediction capability, default `false`; requires an ordinary `STUN_URLS` endpoint on UDP 3478. Hosted startup binds UDP 3479/3480 before advertising the capability. When unavailable, the visible NAT switch is locked off; ordinary ICE remains. Firewall reachability remains an operator requirement. |
|
|
|
|
### Room capacity
|
|
|
|
`MAX_VIEWERS_PER_ROOM` counts authenticated Viewers per room, excluding the Host.
|
|
Self-hosted Server accepts `1..20` and defaults to `20`, matching the App and
|
|
deployment examples. Apply changes by restarting the
|
|
Server (with Compose, run `docker compose up -d` to recreate it after editing
|
|
`.env`). Restart interrupts active connections; excess Viewers receive `ROOM_FULL`
|
|
when joining again. App Local and public-invite modes stay fixed at `20`.
|
|
|
|
Values above `20` are rejected at startup. This is also a wire-contract bound,
|
|
so increasing it in source requires a compatibility and capacity review. More
|
|
Viewers can add relay hops, routing wait and total media load. The setting does
|
|
not increase the per-endpoint copy cap or guarantee available bandwidth.
|
|
|
|
### Media fallback
|
|
|
|
Automatic SFU fallback runs inside the Hosted process when `SFU_UDP_PORT` is set:
|
|
|
|
| Variable | Contract |
|
|
| --- | --- |
|
|
| `SFU_UDP_PORT` | Optional UDP media port `1..65535`; unset or blank disables SFU and fixes Privacy mode on for every room. Set `7882` for the standard public listener and allow the Host to choose Privacy mode. |
|
|
| `SFU_LISTEN_HOST` | IPv4 bind address, default `0.0.0.0`; independent of HTTP `LISTEN_HOST`. Read only when SFU is enabled. |
|
|
| `SFU_PUBLIC_IP` | Optional explicit IPv4 advertised-address override for a host behind NAT. Read only when SFU is enabled. |
|
|
| `SFU_ONLY` | `false` by default. `true` requires `SFU_UDP_PORT` and sends every room through SFU, without Peer candidates or background P2P convergence. Applies after Server restart. |
|
|
|
|
SFU control uses the application's authenticated signaling connection. No
|
|
separate control origin or infrastructure credentials are configured. Local and
|
|
public-link App construction create no SFU listener. The relay does not
|
|
provide application E2EE.
|
|
|
|
For a P2P-only Server, leave `SFU_UDP_PORT` blank. Room authority, signaling,
|
|
configured STUN and peer relays remain; no media-server fallback is possible.
|
|
The server enforces this even if a Host requests hybrid mode. There is no
|
|
separate `SFU_ENABLED` flag to conflict with the listener configuration.
|
|
|
|
With `SFU_ONLY=true`, the page shows a locked **Server media** policy in place of
|
|
P2P settings. An older page requesting Privacy mode is refused before sharing;
|
|
refresh it or turn Privacy mode off. Capacity exhaustion and connection failure
|
|
use the existing bounded SFU admission/recovery path, never a P2P escape.
|
|
This policy needs sufficient server bandwidth and a working UDP route; it is not
|
|
a TURN/TCP fallback. App Local/public-link and the public Demo remain P2P-only.
|
|
|
|
The SQLite parent directory must exist and be writable. The systemd template
|
|
sets `/var/lib/piik/rooms.sqlite` under its managed state directory; the
|
|
container image sets `/home/nonroot/rooms.sqlite` under its writable data
|
|
directory. Keep the existing database path and data across application updates.
|
|
Room authority has no idle expiry; the separate site-access cookie keeps its
|
|
24-hour idle lifetime within one service run. Restarting the App or Server
|
|
requires site-password entry again; saved rooms and invitation grants are unaffected.
|
|
|
|
Removed access, room TTL/lease, endpoint-tier, room-rollout, and TURN variables fail
|
|
startup even when blank. A present `NODE_ENV` fails the same way, so a stale
|
|
environment file cannot silently drop a deployment out of production. The
|
|
private deployment uses its scoped atomic updater. Supported public upgrades and
|
|
any compatibility handling follow the active [versioning contract](./versioning.md).
|
|
|
|
## Piik App Configuration
|
|
|
|
Piik App stores `Piik/client.json` under the operating system's user configuration
|
|
directory (`%APPDATA%` on Windows, `~/Library/Application Support` on macOS,
|
|
and `$XDG_CONFIG_HOME` or `~/.config` on Linux). The App manages its `version`
|
|
schema field. The user settings are:
|
|
|
|
| Setting | Contract |
|
|
| --- | --- |
|
|
| `site` | Saved Piik Site origin. The launcher or `--site` updates it. |
|
|
| `localAccessPassword` | Empty by default. Optional password for the App's Local room authority, with the same exact-match behavior as `SITE_ACCESS_PASSWORD`. It is separate from a hosted site's password. |
|
|
|
|
The launcher remembers the last mode confirmed with the launch button. This
|
|
optional preference lives beside the configuration as `client.json.mode` (or
|
|
`<custom-config-path>.mode`); removing it restores the initial selection without
|
|
changing saved settings. Older App versions ignore this file. Without a valid
|
|
preference, a saved Site is selected when present; otherwise the public
|
|
invitation link is selected. Choosing a mode does not start it until confirmed.
|
|
Local mode remains available for the same network.
|
|
Selecting Local or Public Link, including through the CLI, preserves the saved
|
|
Site and its allowed App origin; only an explicit Site edit replaces it.
|
|
For Local mode, the launcher selects a sole active address or sole private IPv4
|
|
address automatically. With several choices it shows interface names and IPs;
|
|
an ambiguous choice must be selected before launch. `--lan-address` preselects
|
|
an active address. Selection applies to this launch and is revalidated at startup.
|
|
It sets the local invitation origin; HTTP still listens on the existing wildcard
|
|
listener and ICE remains free to use available media interfaces. Public Link and
|
|
Site mode require no local address selection.
|
|
|
|
Command-line options select entry and local runtime behavior:
|
|
|
|
| Option | Purpose |
|
|
| --- | --- |
|
|
| `--site <origin>` / `--local` | Save and use a Site, or select the self-contained Local mode. Mutually exclusive. |
|
|
| `--link` | Create a public Viewer invitation for Local mode. |
|
|
| `--config <path>` | Select another App configuration file. |
|
|
| `--lan-address <IPv4>` / `--port <port>` | Override the Local invitation address or HTTP port (default `8787`). |
|
|
| `--capture-process <path>` / `--tunnel-process <path>` | Override packaged native capture or public tunnel helpers. Ordinary installations use the packaged paths. |
|
|
| `--debug` / `--log-dir <path>` | Enable diagnostics or choose their destination as described below. |
|
|
|
|
Share quality, room access policy, language and theme are configured in
|
|
the shared Web UI. Decorative motion follows the system's reduced-motion preference.
|
|
|
|
## Diagnostics
|
|
|
|
Normal Server logs record startup identity, listener and enabled services,
|
|
unexpected failures, orderly shutdown and any available release found by the
|
|
single background startup check. Detailed room/ICE/media traces require Debug.
|
|
|
|
Diagnostics are local and opt-in. Enable them **before** reproducing the problem:
|
|
|
|
| Surface | Enable | Export |
|
|
| --- | --- | --- |
|
|
| App | Enable **Debug launch** with the small chip icon after the theme control in the mode selector, or start with `--debug` / `PIIK_DEBUG=client` | Press `D` in the terminal for a ZIP |
|
|
| Browser Host/Viewer | Click the **Debug** chip icon after the theme control and confirm the reload, or add `?debug=1` before any invitation fragment | The same control becomes a download arrow for the web report |
|
|
| Hosted Server | Start with `--debug`, `PIIK_DEBUG=server` or `PIIK_DEBUG=route` | On Unix, `kill -USR1 <pid>`; also exported at orderly shutdown |
|
|
|
|
App **Debug launch** enables App and Browser collection for that run before
|
|
starting the selected mode. It records Native capability results and subsequent
|
|
capture, connection and local-server activity. Use `--debug` for failures before
|
|
the mode selector opens. This choice does not change the saved App configuration.
|
|
When bypassing the mode selector, `--debug` and `PIIK_DEBUG=client` enable backend
|
|
collection; enable the Browser control separately for browser-side diagnosis.
|
|
|
|
The Browser entry reloads the current page so collection includes connection
|
|
startup. The opt-in follows App launch and room entry. Enabling it keeps the
|
|
current URL parameters and any invitation fragment, but interrupts active
|
|
sharing/viewing; enable it before reproducing the problem. Reports remain local
|
|
until exported and shared by the user.
|
|
|
|
Server Debug is controlled by its startup environment or CLI, never by a remote
|
|
page or room role. Browser `?debug=1` only enables that page's local collection;
|
|
it does not enable App Native/capture or Server logging, or download their
|
|
reports. The Server exposes no HTTP diagnostic export or pprof endpoint.
|
|
|
|
App/Server ZIP and Browser JSON reports are separate: when investigating
|
|
Browser/App cooperation, include both from the same reproduction. Exporting
|
|
either report does not stop an active share or upload anything. Browser export
|
|
also remains available as `await window.__PIIK_DEBUG__.export()` in DevTools.
|
|
|
|
App logs go to `logs` beside the executable, falling back to `Piik/logs`
|
|
in the OS user-cache directory when that default is unwritable. The TUI shows
|
|
the actual path and the exported ZIP. `--log-dir` overrides
|
|
`PIIK_LOG_DIR`; an explicit directory must be writable. Choosing a
|
|
directory alone does not enable collection. Non-interactive Apps export at
|
|
orderly shutdown; a returned App error also exports before the terminal closes.
|
|
On App, `PIIK_DEBUG=route` alone retains console route
|
|
tracing; use `--debug` for file collection and the `D` action.
|
|
|
|
Hosted logs use `PIIK_LOG_DIR`, otherwise systemd `LOGS_DIRECTORY`,
|
|
otherwise `logs` under the working directory. The service unit supplies
|
|
`/var/log/piik` with mode `0700`. Normal service notices remain in the
|
|
journal; detailed dependency records go into the report. Windows Server has no
|
|
Unix signal trigger; forced process termination cannot create a final snapshot.
|
|
|
|
The report combines operation history and existing runtime evidence:
|
|
|
|
- Native request IDs connect start/completion, duration, requested/applied
|
|
profiles, source kind, codec/adapter selection and cancellation or failure.
|
|
Async quality preparation retains that ID until its actual completion.
|
|
- Capture process start/exit/EOF and streamed stderr include useful failure
|
|
causes and system/HRESULT codes. Windows samples its existing WebRTC encoder
|
|
observer during processing: input/output FPS, actual size, bitrate, encode
|
|
time/usage, QP when available, drops, limitation flags and adaptation counts.
|
|
Those are VSE counters, not a complete account of WGC mailbox overwrites.
|
|
- Pion connection/ICE/DTLS and media-component diagnostics are included.
|
|
Existing RTP/BWE/allocation observations, packet queue/drop counters,
|
|
group demand/attachment changes and gateway/STUN outcomes explain delivery
|
|
without adding a media-control loop or a new per-connection polling timer.
|
|
- Browser records capture settings and sender readbacks, signaling and Native
|
|
operations, meaningful error messages/stacks/causes and existing RTCStats.
|
|
Pool observations distinguish native carrier reports, actual output and its
|
|
assigned producer. Export adds Browser/platform metadata; diagnostic collection
|
|
does not replace media APIs or control transport.
|
|
Each RTC sample includes a compact ICE summary ahead of the bounded raw stats:
|
|
reported pair states and selected-path type, prediction provenance, check
|
|
responses and RTT when available. Pair counts describe that sample, not route
|
|
attempts or a connection-success rate.
|
|
|
|
Each Go component keeps an 8 MiB current log and one 8 MiB backup. ZIPs contain
|
|
these retained logs, a report marker, selected startup context, build/module and
|
|
platform metadata, Go memory counters, sampled allocation profile
|
|
(`heap.pprof`) and aggregate goroutine stacks. These are not raw process-memory
|
|
or C++ memory dumps. A failed optional collector leaves useful files available;
|
|
`metadata.json` lists included files, errors and partial status. ZIP write/disk
|
|
failure still reports an export failure. Rotation and preexisting history are
|
|
identified; retained logs do not claim a complete session history.
|
|
|
|
Exported ZIPs remain until the user moves or deletes them; rotation manages only
|
|
the current logs. Repeated exports and Debug-mode error exits accumulate archives,
|
|
so manage that directory's disk usage separately.
|
|
|
|
Browser retains up to 8,192 events and 8 MiB of compact event data in the current
|
|
page. Reports identify retained sequence/time ranges, evicted/truncated events
|
|
and collector failures. Field/record limits are explicit in the report.
|
|
Browser reload/close loses that in-page history; export before closing it.
|
|
|
|
Credentials, authorization/cookies, invitation secrets, ICE passwords/fragments
|
|
and private keys are filtered before persistence/export. Application media
|
|
identities use diagnostic hashes where applicable; Browser/library technical
|
|
identifiers, IP addresses, device information and file paths may remain.
|
|
Do not treat a report as anonymous. Review it before sharing. Raw screen/audio
|
|
payloads, arbitrary config/environment files and raw process-memory contents
|
|
are not collected. Browser window titles and participant display names are
|
|
omitted. Debug detail has CPU/I/O cost and should be enabled for investigation.
|
|
|
|
The [research comparison](../research/diagnostic-feedback.md) records the mature
|
|
project references and the reasons for this collection boundary.
|
|
|
|
## Public And Private Ports
|
|
|
|
| Port | Scope | Owner |
|
|
| ---: | --- | --- |
|
|
| TCP 80/443 | public | HTTP redirect and HTTPS/WSS reverse proxy |
|
|
| UDP 3478 | public | in-process STUN-only Piik listener |
|
|
| UDP 3479/3480 | public when NAT prediction is enabled | in-process auxiliary STUN-only Piik listeners |
|
|
| UDP 7882 (or `SFU_UDP_PORT`) | public when SFU enabled | in-process Piik WebRTC media |
|
|
| TCP 8787 | private | Piik application |
|
|
|
|
TCP 3478, TCP/TLS 5349, TURN relay ranges, media TCP, and other media
|
|
ports remain closed. HTTPS/WSS transport is independent of the UDP-only media
|
|
contract.
|
|
|
|
When `NAT_PREDICTION_ENABLED=true`, the server derives
|
|
`stun:<same-hostname>:3479` and `:3480` from the first ordinary STUN authority
|
|
on UDP 3478. The Host sees a pre-share switch that defaults on and may disable
|
|
it. The capability adds no media route or third-party service. It needs both
|
|
cloud security-group rules and the host's `/etc/nftables.conf` rule. Piik
|
|
binds every required UDP listener before opening room persistence or accepting
|
|
signaling; a bind failure rolls back all newly owned sockets. Close and End
|
|
retire these listeners with the application. Existing coturn listeners must
|
|
be retired in the coordinated deployment because two processes cannot own the
|
|
same ports. Opening a cloud port without a listener has no effect, and local
|
|
binding alone does not prove external reachability. Disable the capability
|
|
before removing firewall rules. Same-IP ports
|
|
expose destination-port allocation behavior; a full RFC 5780 alternate-address
|
|
test requires a second public IPv4.
|
|
|
|
## Bounds
|
|
|
|
- Site-access requests are rate-limited at the reverse proxy and use constant-
|
|
time secret comparison in the application.
|
|
- HTTP body, WebSocket payload, total/unauthed connections, room count, Viewer
|
|
count, output buffers, endpoint copies, and SFU resources are bounded.
|
|
- The four-digit code space fixes the maximum managed Host publications at
|
|
9,000; maximum subscription admission is that capacity times the configured
|
|
per-room Viewer limit. These are admission bounds, not throughput claims.
|
|
- One application process owns room authority and SFU admission. Multiple
|
|
processes require a new shared atomic owner.
|