Piik now has one public presentation and a coordinated App/Server release path. This phase unifies the room UI, rewrites the bilingual README and guides, adds a static website with an inline product film, and prepares matching GitHub/Gitee packages and update links. The film uses the current homepage and shared product controls on one seekable timeline. Runtime fixes preserve presentation when the App opens a room, normalize Site origins, and keep capture and media-recovery status in the television indicator. New visits use Chinese for a Chinese system language and English otherwise; explicit language and visual-mode choices remain available. An optional site passphrase controls site entry, while room authorization remains enforced. GitHub is the release authority. Gitee mirrors verified packages and provides update metadata when GitHub is unavailable. Reviewed PR release notes become the GitHub Release description. The separate public demo uses P2P only, with HTTPS and STUN verified. Validation: 756 Web tests, TypeScript and production build; Go core tests, formatting, vet and available target builds; bounded Windows capture and App/Site interoperability; browser film checks, audible playback and narrow layouts; anonymous Gitee Windows-package download, checksum and launcher/update-link checks. Public demo acceptance covers authenticated WebSocket signaling, synthetic P2P video and room cleanup on one network. macOS/Linux physical capture and the wider device/network/endurance matrix remain explicitly deferred. Publication builds every package from the merged source SHA. The repository is public, main protection is active, and Pages is configured for piik.tv. CI/publisher and Pages deployment records own publication results. ## Release notes ### 中文 Piik 是免费开源的屏幕共享工具。开个房间,发出邀请,最多 20 位朋友就能用浏览器加入观看。 - 使用浏览器或 Piik App 分享游戏、窗口和整个屏幕。 - 优先建立直连;自托管站点可开启媒体转发作为备用线路。 - Piik App 支持本地房间、临时公网邀请和已有站点。 - Piik Server 内置网页界面、房间管理和连接服务,方便自行部署。 - 提供中英文界面与使用指南,以及 GitHub、Gitee 两条下载线路。 [官网](https://piik.tv) · [在线体验](https://demo.piik.tv) · [使用指南](https://github.com/TNTcraftHIM/Piik/blob/main/docs/guide/getting-started.zh-CN.md) · [自行部署](https://github.com/TNTcraftHIM/Piik/blob/main/docs/operations/self-hosting.zh-CN.md) · [Gitee 下载](https://gitee.com/TNTcraftHIM/Piik/releases) Windows App 和桌面浏览器是本次主要验证的平台。macOS 和 Linux 尚未经过实机测试,欢迎有设备的朋友测试并反馈。演示站和 App 公网邀请使用 P2P,受限网络下可能无法连接;自托管站点可开启媒体转发。 ### English Piik is free, open-source screen sharing for you and up to 20 viewers. Start a room, send an invitation, and your friends can join in a browser. - Share games, windows or a whole screen from your browser or Piik App. - Direct connections come first, with optional media forwarding on self-hosted sites. - Piik App supports local rooms, temporary public invitations and existing sites. - Piik Server includes the web interface, rooms and connection services for self-hosting. - English and Chinese interfaces and guides are available, with GitHub and Gitee downloads. [Website](https://piik.tv) · [Online demo](https://demo.piik.tv) · [User guide](https://github.com/TNTcraftHIM/Piik/blob/main/docs/guide/getting-started.md) · [Self-hosting](https://github.com/TNTcraftHIM/Piik/blob/main/docs/operations/self-hosting.md) · [Gitee downloads](https://gitee.com/TNTcraftHIM/Piik/releases) Windows App and desktop browsers are the primary validated paths. macOS and Linux have not yet been tested on physical devices; testing and feedback are welcome. The demo and App public invitations rely on P2P and may not connect on restrictive networks. Self-hosted sites can enable media forwarding.
12 KiB
Cross-Platform App Runtime Research
- Reviewed: 2026-09-04
- Scope: loopback control and self-contained packaging boundary
- Status: App and Local composition implemented; Windows native Host video and a cross-NAT media gate proved
Reusable Evidence
| Project | Observed boundary | Applicable lesson |
|---|---|---|
| Discord RPC | Bounded local endpoints and an explicit handshake | Discovery and session negotiation can stay small |
| OBS WebSocket | Versioned Hello/Identify before commands |
Reject unknown protocol shapes instead of adding compatibility readers |
| Syncthing | Go process with a loopback Browser GUI by default | A native entry and system-Browser UI are a practical cross-platform pair |
| Sunshine | Native streaming host configured through a localhost Browser UI | Native media does not require a second desktop UI |
| LocalSend | One peer exposes a local HTTP service without an external server | LAN operation can be self-contained, while network reachability remains physical |
These are architecture references only. No implementation or copyleft source is copied.
A read-only inventory of locally installed streaming clients adds one practical constraint. GameViewer separates its UI, supervised media service, codec capability detector, streamer, health process, and updater. Discord keeps its Chromium UI separate from a native voice/media module and updater. Oopz ships Flutter, a second WebView, FFmpeg, Agora RTC, and Tencent LiteAV together; that stack is substantially larger and duplicates media ownership. Piik follows the first two products' process separation but not their UI runtimes, and avoids Oopz's parallel RTC stacks: one Go process, one Pion media core, and one thin system capture sidecar per platform remain sufficient. No binary code or private application data was copied or inspected.
Current Control Boundary
The App binds IPv4 loopback on a bounded range (39721-39730). /health
returns the protocol version, service identity, selected port, and an
instanceToken. /control admits one WebSocket session whose subprotocol
contains that same value. The first frame must be hello; subsequent requests
are limited to capability discovery, source preview, and one generation-fenced
share's media controls.
The instance token distinguishes a newly discovered process from a stale or unrelated listener. It is visible through health and stdout and is not an authentication secret. Host and Origin checks plus Chromium's Local Network Access permission form the Browser boundary.
The current protocol advertises only the native capabilities and generation-fenced media commands that have consumers. It carries no room credentials or route policy; those stay in the Browser/server protocol.
App Composition
The App and Hosted Piik run the same server core, so the local package is one executable carrying the built Browser assets plus the optional capture and tunnel sidecars; the App README owns that layout. In Local mode the App runs the server in its own process with explicit local configuration. In Site mode it starts no server, and the system Browser opens the saved Site while the same process remains its loopback native-media owner. The system Browser remains the UI.
Official Go process APIs require every started child to be waited and provide a
bounded WaitDelay for cancellation and stuck I/O. That guidance now covers the
capture and cloudflared sidecars only: the room authority is no longer a child
process, and Local shutdown is one bounded in-process sequence that ends rooms
before closing signaling and HTTP. Windows is physically exercised; macOS and
Linux remain package gates.
Local And Hosted Reachability
A local page completed discovery and the full control exchange in Chromium
151.0.7922.138. The hosted Piik origin completed it after Chromium received
its loopback-network permission; without that permission the cross-origin
request was blocked. The gate checks both expected outcomes.
Run npm run probe:client-loopback with PIIK_CLIENT_LOOPBACK_GATE=true,
CHROME_PATH, PIIK_CLIENT_EXE, and PIIK_CLIENT_GATE_SITE_URL pointing to
the reachable HTTPS Site being tested. Use PIIK_CLIENT_GATE_GRANT_LOOPBACK=true
for the permission-granted run; omit it for the permission-blocked run. The gate
uses an isolated App configuration and Browser profile, and rejects navigation
failures or redirects to another origin as acceptance evidence.
A self-contained LAN room uses a localhost Host URL and a selected LAN IPv4
Viewer URL backed by the same local App process. The App persists an
optional user-chosen access password and passes it only to its Host page in a
consumed fragment; a blank value leaves the Local site open. Explicit --link
mode launches the packaged Cloudflare Quick
Tunnel against that same local HTTP server and supplies its random HTTPS origin
to the local server configuration before it starts listening. The public path
therefore reuses the exact frontend,
WebSocket signaling, RoomStore, and Viewer grant instead of adding a rendezvous
or second client protocol. Cloudflare carries control traffic; WebRTC media uses
public STUN and remains P2P-only.
UI Runtime Boundary
The current App opens the system Browser rather than embedding another Web runtime. A lightweight launcher chooses the authority mode, then navigates to the same Host page, where an App-launched Host can select an exact native window. This keeps the existing UI, Site cookies, WebRTC behavior, Browser updates, and permission model intact. Syncthing and Sunshine establish this as a practical native-process plus Browser-UI deployment shape.
An embedded shell remains a decision gate rather than a rejected category.
Current WebView2 exposes getDisplayMedia screen-capture events and its
Evergreen runtime updates independently; WebKitGTK exposes display capture and
uses GStreamer for WebRTC. Electron instead bundles one Chromium and Node but
makes the App responsible for shipping those updates and adds substantial
package size. These facts do not prove equivalent Piik media behavior.
Only a reproduced Browser-launch failure should open a comparative physical gate for Electron, Tauri, Wails, Neutralino, or another shell. That gate must compare actual capture, audio, H.264/VP8 sender implementation, 1080p cadence, relay, background behavior, and resource use on every target platform. The result selects one UI runtime; it does not create parallel products.
Current Evidence
The runs below are pre-port evidence: they exercised the package that bundled a Node runtime and an extracted application tree. Their capture, discovery, media, and network results still apply; every package composition, startup, and shutdown claim must be re-verified on the single-binary App before that build is accepted.
On Windows with Chrome for Testing 151.0.7922.138:
- the Local App started its built static application and reached
/healthz; - the Host fragment was removed, existing SiteAccess became authenticated, and the ordinary Host page loaded;
- the room API generated an invitation from the selected LAN origin;
- one synthetic Host and three Viewers formed a P2P-only tree with one relay, every Viewer advanced decoded frames, and no SFU publication appeared; and
- Enter-driven App shutdown released the Browser, App, Node, loopback and application ports, and disposable profile.
- the immutable App release was assembled with Node 24.19.0 and the Go App
from the same full revision; that packaged directory passed the Local and Site
gates, while a deliberately mismatched
app/REVISIONwas rejected before a listener started. - the explicit target assembler produced Windows amd64, Linux amd64, and macOS arm64 outputs from one clean revision. The Linux package ran its bundled Node Local authority on Ubuntu, and its full package exposed and then closed a public link reachable from another network. The macOS App and Node inputs are both Mach-O arm64; execution there remains unproved.
- the native Host path created a Local room and a remote Pion Viewer received
30 packets over a selected
srflx-to-srflxpair; the reverse SSH link in that gate carried signaling only. - a Windows App created an accountless Quick Tunnel, generated its ordinary
invitation on that origin, and served the Viewer page plus
/signalWebSocket upgrade to an independent Linux host; a native Host then repeatedly delivered 30+ H.264 RTP packets to a Linux Pion Viewer over selected direct paths using a reflexive candidate. Stopping the App closed the URL.
The one-link gate used the official Windows amd64 cloudflared 2026.8.3 asset
with SHA-256 83e726ed18ea78c5ad5213c4c3a3a27051393950d2bc8ed4de69bec12d14eaae.
The sidecar remains an explicit package input rather than a linked App
dependency.
The peer topology gate now treats native getStats() RTP identity and frame
totals as its portable core proof. Detailed Piik quality metrics enrich a
development run when its source module is served, but their absence on a static
deployment no longer erases valid native RTCStats.
Remaining Gates
- Run the exact clean-revision package on macOS; Linux amd64 is proved.
- Prove a physical second-device LAN Viewer on desktop, Android, and iOS.
- Prove first-run Browser local-network permission outside CDP automation.
- Record no-STUN mDNS behavior on ordinary and AP-isolated LANs.
- Exercise the native Host on a configured Site and representative Browsers; the local SFU bridge is proved in isolation, while full Site recovery, representative audio, and non-Windows capture remain undefined.
- Exercise one-link Browser media on a physical second device; the current gate proves the complete public control path and independent Pion media, not decoded Browser frames.
Sources
- Go
os/exec - WebRTC peer connections
- Cloudflare public STUN endpoint
- Cloudflare Quick Tunnels
- Cloudflare Tunnel WebSockets
- cloudflared releases
- RFC 6455
- W3C Screen Capture
- Microsoft Windows Graphics Capture
- Apple SCContentSharingPicker
- XDG ScreenCast portal
- OBS window-capture source
- Chrome Local Network Access
- Discord RPC
- OBS WebSocket
- LocalSend protocol
- Sunshine
- Syncthing GUI configuration
- GameViewer product
- Discord desktop architecture
- WebView2 Evergreen runtime
- WebView2 screen capture
- WebKitGTK multimedia
- WebKitGTK display capture
- Electron architecture