feat: rename product and runtime to Piik
Rename the active product, Go module, binaries, configuration, protocols and documentation to Piik while retaining the TV mascot and existing media/room behavior. Use one current private contract without old-name aliases. Preserve SQLite authority and copy compatible local settings once; other settings start fresh. Git-message cleanup and the infrastructure name cutover are coordinated with this phase, with original history and deployment data archived externally. Validated locally with Web and Go checks, Windows capture compilation, matched Client/Server builds, packaged Client control handshake and history-rewrite integrity checks. Skip duplicate hosted CI for this owner-authorized local release. [skip ci]
This commit is contained in:
1 parent
35f9251088
commit
1332473513
254 files changed
+1443
-1321
No files matched your search
+3
-3
@@ -20,7 +20,7 @@ MAX_VIEWERS_PER_ROOM=8
|
||||
# A peer child or Host SFU publication consumes one copy. Valid values: 1, 2, 3.
|
||||
ENDPOINT_MEDIA_COPY_CAPACITY=2
|
||||
# During pre-release route canaries, this enables sanitized room/ordinal events.
|
||||
# SCREENER_DEBUG=route
|
||||
# PIIK_DEBUG=route
|
||||
|
||||
# Optional in-process automatic SFU fallback. Set SFU_UDP_PORT=7882 to enable;
|
||||
# unset or empty keeps it disabled. Local Client modes never create this listener.
|
||||
@@ -50,11 +50,11 @@ NAT_PREDICTION_ENABLED=false
|
||||
# Development example (two processes): Vite serves the Browser on 8787 and
|
||||
# proxies /api, /healthz and /signal to the Go server on 8788. Keep
|
||||
# PUBLIC_BASE_URL and ALLOWED_ORIGINS on the Browser origin above.
|
||||
# SCREENER_ENV=development
|
||||
# PIIK_ENV=development
|
||||
# PORT=8788
|
||||
|
||||
# Minimal production example (use independent untracked secrets):
|
||||
# SCREENER_ENV=production
|
||||
# PIIK_ENV=production
|
||||
# SITE_ACCESS_PASSWORD=replace-with-an-independent-access-key
|
||||
# STUN_URLS=stun:stun.example.com:3478
|
||||
# NAT_PREDICTION_ENABLED=true
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
client_checks:
|
||||
description: Run the optional Screener Client checks
|
||||
description: Run the optional Piik Client checks
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Validate tracked project state
|
||||
run: sh scripts/check-project-state.sh
|
||||
env:
|
||||
SCREENER_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
||||
PIIK_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
# The Go build embeds internal/server/webassets/dist, so Vite runs first.
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
- name: Upload application release
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: screener-app-${{ github.sha }}
|
||||
name: piik-app-${{ github.sha }}
|
||||
path: ${{ runner.temp }}/app-release/*
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
@@ -142,7 +142,7 @@ jobs:
|
||||
- name: Download application release
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: screener-app-${{ github.sha }}
|
||||
name: piik-app-${{ github.sha }}
|
||||
path: ${{ runner.temp }}/app-release
|
||||
- name: Build and verify Client candidate
|
||||
run: >-
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
- name: Upload Client release candidate
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: screener-client-${{ matrix.target }}-${{ github.sha }}
|
||||
name: piik-client-${{ matrix.target }}-${{ github.sha }}
|
||||
path: ${{ runner.temp }}/client-release/*
|
||||
if-no-files-found: error
|
||||
compression-level: 0
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
## Product Contract
|
||||
|
||||
- Screener is private game screen sharing for one Host and up to 20 authenticated
|
||||
- Piik is private game screen sharing for one Host and up to 20 authenticated
|
||||
Viewers, with Web Host/Viewer/relay as the current product surface.
|
||||
- Current product truth is split by owner:
|
||||
[rooms/access](./docs/product/rooms-access.md),
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ Clean up worktrees and branches only after semantic review and integration are c
|
||||
- Use current community issues and operational reports to identify real compatibility failures, but label anecdotal evidence as such.
|
||||
- Include a date and direct URLs. Separate verified facts, measurements, assumptions, and recommendations.
|
||||
- Review licenses before copying implementation code. A useful reference is not automatically a compatible dependency.
|
||||
- Screener-owned code is [MIT-licensed](./LICENSE); third-party components retain
|
||||
- Piik-owned code is [MIT-licensed](./LICENSE); third-party components retain
|
||||
their own licenses and notices. GPL/AGPL implementation sources remain
|
||||
study-only unless a separate distribution decision accepts their obligations.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 TNTcraft and Screener contributors
|
||||
Copyright (c) 2026 TNTcraft and Piik contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ The authoritative license is the English [LICENSE](./LICENSE).
|
||||
This translation is for convenience and adds no terms or restrictions.
|
||||
|
||||
本文件为方便阅读提供中文参考译文,不替代英文 [LICENSE](./LICENSE),
|
||||
也不增加条件或限制。Screener 自有代码的 MIT 许可不替代
|
||||
也不增加条件或限制。Piik 自有代码的 MIT 许可不替代
|
||||
[第三方组件的许可与声明](./licenses/README.md)。
|
||||
|
||||
版权所有 (c) 2026 TNTcraft 和 Screener 贡献者
|
||||
版权所有 (c) 2026 TNTcraft 和 Piik 贡献者
|
||||
|
||||
特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,
|
||||
不受限制地处置本软件的权利,包括但不限于使用、复制、修改、合并、出版、
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<img src="./public/favicon.svg" width="64" height="64" alt="Screener TV logo">
|
||||
<img src="./public/favicon.svg" width="64" height="64" alt="Piik TV logo">
|
||||
|
||||
# Screener
|
||||
# Piik
|
||||
|
||||
English | [简体中文](./README.zh-CN.md)
|
||||
|
||||
Share your screen. Bring your friends.
|
||||
|
||||
Screener is private screen sharing for one Host and up to 20 invited friends.
|
||||
Piik is private screen sharing for one Host and up to 20 invited friends.
|
||||
Friends watch in their browsers, with no installation.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Browser[Browser] --> Host[Host a room]
|
||||
Client[Screener Client] --> Host
|
||||
Client[Piik Client] --> Host
|
||||
Host -->|Invite link| Friends[Friends watch in browsers]
|
||||
```
|
||||
|
||||
@@ -21,12 +21,12 @@ flowchart LR
|
||||
1. Open the invitation your friend sent.
|
||||
2. Press Play if your browser asks. Use the video's sound and fullscreen controls.
|
||||
|
||||
Got a room code instead? Open the same Screener site and choose **Join a room**.
|
||||
Got a room code instead? Open the same Piik site and choose **Join a room**.
|
||||
Site access and the room's password settings still apply.
|
||||
|
||||
## Share from your browser
|
||||
|
||||
1. Open the Screener site your group uses. Enter its site password if asked.
|
||||
1. Open the Piik site your group uses. Enter its site password if asked.
|
||||
2. Choose **Start sharing**, pick a screen, window or tab, and check the sound switch.
|
||||
3. Send the room's invitation link to your friends. Keep the sharing tab open.
|
||||
|
||||
@@ -39,20 +39,20 @@ same controls, with light and dark themes.
|
||||
With a Client package for your platform:
|
||||
|
||||
1. Extract the whole package, keeping `runtime` beside the executable.
|
||||
2. Open `screener-client.exe` on Windows, `Screener Client.app` on macOS, or
|
||||
`./screener-client` on Linux.
|
||||
2. Open `piik-client.exe` on Windows, `Piik Client.app` on macOS, or
|
||||
`./piik-client` on Linux.
|
||||
3. Choose a mode, pick what to share, and send the invitation. Keep Client running.
|
||||
|
||||
| Mode | Use it for |
|
||||
| --- | --- |
|
||||
| **Local room** | Friends on the same local network. An optional site password controls access. |
|
||||
| **Public invite** | A temporary Internet invitation. The link lasts for this Client run; media remains P2P. |
|
||||
| **Connect to Site** | An existing Screener site, with Client capture and media capabilities available in the same browser UI. |
|
||||
| **Connect to Site** | An existing Piik site, with Client capture and media capabilities available in the same browser UI. |
|
||||
|
||||
Client opens your system browser. Its package includes the Go application and
|
||||
capture/link helpers; running it needs no Node.js, npm or Go installation.
|
||||
Linux native capture uses the system Portal, PipeWire and GStreamer stack.
|
||||
See the [Client guide](./cmd/screener-client/README.md) for platform details.
|
||||
See the [Client guide](./cmd/piik-client/README.md) for platform details.
|
||||
|
||||
Temporary public links use Cloudflare Quick Tunnel, which has no uptime guarantee.
|
||||
Media needs a working UDP path; restrictive networks or browser/OS suspension
|
||||
@@ -75,9 +75,9 @@ Include your version, OS/browser, expected result and steps to reproduce.
|
||||
For a local report, start Client with `--debug` and press `D`, or add `?debug=1`
|
||||
before any `#` in the Browser page URL and use its header download button. Review reports before
|
||||
sharing; see [diagnostics and export](./docs/reference/configuration.md#diagnostics).
|
||||
Connection trouble? Try the [Chromium WebRTC FAQ](./cmd/screener-client/README.md#chromium-webrtc-connections).
|
||||
Connection trouble? Try the [Chromium WebRTC FAQ](./cmd/piik-client/README.md#chromium-webrtc-connections).
|
||||
|
||||
## License
|
||||
|
||||
Screener-owned code is [MIT licensed](./LICENSE). Third-party components retain
|
||||
Piik-owned code is [MIT licensed](./LICENSE). Third-party components retain
|
||||
their own licenses and notices: [licensing guide](./licenses/README.md).
|
||||
+12
-12
@@ -1,18 +1,18 @@
|
||||
<img src="./public/favicon.svg" width="64" height="64" alt="Screener 小电视标志">
|
||||
<img src="./public/favicon.svg" width="64" height="64" alt="Piik 小电视标志">
|
||||
|
||||
# Screener
|
||||
# Piik
|
||||
|
||||
[English](./README.md) | 简体中文
|
||||
|
||||
分享你的屏幕,叫上朋友一起看。
|
||||
|
||||
Screener 是一个私密屏幕分享工具:一位房主,最多 20 位受邀好友。
|
||||
Piik 是一个私密屏幕分享工具:一位房主,最多 20 位受邀好友。
|
||||
朋友用浏览器就能观看,无须安装。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Browser[浏览器] --> Host[开房分享]
|
||||
Client[Screener Client] --> Host
|
||||
Client[Piik Client] --> Host
|
||||
Host -->|邀请链接| Friends[好友用浏览器观看]
|
||||
```
|
||||
|
||||
@@ -21,12 +21,12 @@ flowchart LR
|
||||
1. 打开朋友发来的邀请链接。
|
||||
2. 如果浏览器提示,点击播放。声音和全屏由视频控件控制。
|
||||
|
||||
只有房间号?打开同一个 Screener 站点,选择 **加入房间**。
|
||||
只有房间号?打开同一个 Piik 站点,选择 **加入房间**。
|
||||
站点访问权限和房间密码设置仍然适用。
|
||||
|
||||
## 用浏览器分享
|
||||
|
||||
1. 打开你们使用的 Screener 站点,按提示输入站点密码。
|
||||
1. 打开你们使用的 Piik 站点,按提示输入站点密码。
|
||||
2. 点击 **开始分享**,选择屏幕、窗口或标签页,并检查声音开关。
|
||||
3. 把房间邀请链接发给朋友,保持分享标签页打开。
|
||||
|
||||
@@ -38,19 +38,19 @@ flowchart LR
|
||||
拿到对应平台的 Client 程序包后:
|
||||
|
||||
1. 完整解压,保留可执行文件旁的 `runtime` 目录。
|
||||
2. Windows 打开 `screener-client.exe`,macOS 打开 `Screener Client.app`,
|
||||
Linux 运行 `./screener-client`。
|
||||
2. Windows 打开 `piik-client.exe`,macOS 打开 `Piik Client.app`,
|
||||
Linux 运行 `./piik-client`。
|
||||
3. 选择模式和分享来源,发出邀请。分享期间保持 Client 运行。
|
||||
|
||||
| 模式 | 适合什么情况 |
|
||||
| --- | --- |
|
||||
| **本地房间** | 与同一局域网内的好友分享,可设置站点访问密码。 |
|
||||
| **公网邀请** | 生成本次 Client 运行期间有效的临时邀请链接;媒体仍走 P2P。 |
|
||||
| **连接站点** | 使用已有 Screener 站点,并在同一浏览器界面使用 Client 的采集与媒体能力。 |
|
||||
| **连接站点** | 使用已有 Piik 站点,并在同一浏览器界面使用 Client 的采集与媒体能力。 |
|
||||
|
||||
Client 会打开系统浏览器。程序包包含 Go 应用和采集、临时链接辅助程序,
|
||||
运行时无须安装 Node.js、npm 或 Go。Linux 原生采集使用系统的 Portal、PipeWire
|
||||
和 GStreamer,平台细节见 [Client 指南](./cmd/screener-client/README.md)。
|
||||
和 GStreamer,平台细节见 [Client 指南](./cmd/piik-client/README.md)。
|
||||
|
||||
临时公网链接使用 Cloudflare Quick Tunnel,不保证持续可用。
|
||||
媒体需要可用的 UDP 路径;网络限制、浏览器或系统挂起都可能中断分享。
|
||||
@@ -71,9 +71,9 @@ SFU 后备路径。搭建自己的站点,请看 [自托管指南](./docs/opera
|
||||
Client 可用 `--debug` 启动后按 `D` 导出本地报告;浏览器网址加上 `?debug=1`
|
||||
后(放在 `#` 之前),可点击顶部下载按钮。分享前请检查报告内容,详见
|
||||
[诊断与导出](./docs/reference/configuration.md#diagnostics)。
|
||||
连接不上时,也可以查看 [Chromium WebRTC 常见问题](./cmd/screener-client/README.md#chromium-webrtc-connections)。
|
||||
连接不上时,也可以查看 [Chromium WebRTC 常见问题](./cmd/piik-client/README.md#chromium-webrtc-connections)。
|
||||
|
||||
## 许可
|
||||
|
||||
Screener 自有代码采用 [MIT 许可](./LICENSE),提供 [中文参考译文](./LICENSE.zh-CN.md)。
|
||||
Piik 自有代码采用 [MIT 许可](./LICENSE),提供 [中文参考译文](./LICENSE.zh-CN.md)。
|
||||
第三方组件保留各自的许可与声明,详见 [许可说明](./licenses/README.md)。
|
||||
@@ -1,14 +1,14 @@
|
||||
# Screener Client
|
||||
# Piik Client
|
||||
|
||||
Screener Client is the self-contained and native-capability runtime for the same
|
||||
Browser application used by Hosted Screener. It does not implement another UI,
|
||||
Piik Client is the self-contained and native-capability runtime for the same
|
||||
Browser application used by Hosted Piik. It does not implement another UI,
|
||||
room store, signaling protocol, or route controller.
|
||||
|
||||
## Run A Package
|
||||
|
||||
Extract the matching platform bundle in full and keep `runtime` beside the
|
||||
Client executable. Run `screener-client.exe` on Windows, `./screener-client` on
|
||||
Linux, or `Screener Client.app` on macOS. The launcher opens in the system Browser;
|
||||
Client executable. Run `piik-client.exe` on Windows, `./piik-client` on
|
||||
Linux, or `Piik Client.app` on macOS. The launcher opens in the system Browser;
|
||||
the Client does not embed a browser UI. Packaged execution needs no Node.js, npm,
|
||||
or Go installation. Linux native capture uses the system dependencies described
|
||||
in the [Linux capture guide](../../native/capture/linux/README.md).
|
||||
@@ -111,7 +111,7 @@ to one Browser brand or to VPN use.
|
||||
|
||||
Check the Browser's WebRTC/IP-handling policy and any extension's WebRTC or
|
||||
IP-leak protection setting. Restore a policy that permits WebRTC UDP, reload
|
||||
Screener, and verify that another extension or managed policy has not overridden
|
||||
Piik, and verify that another extension or managed policy has not overridden
|
||||
the choice. Setting names and availability differ between Browsers. For example,
|
||||
Vivaldi exposes **Settings > Privacy and Security > WebRTC IP Handling >
|
||||
Broadcast IP for Best WebRTC Performance**. Changing this policy can expose
|
||||
@@ -139,7 +139,7 @@ The binary embeds the Browser assets, so build them before running it:
|
||||
npm run build:client
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go run ./cmd/screener-client
|
||||
go run ./cmd/piik-client
|
||||
```
|
||||
|
||||
The repository-level entry used locally and by CI is:
|
||||
@@ -200,11 +200,11 @@ explicit CI packaging, Release publication and updates are documented in
|
||||
The extracted bundle contains:
|
||||
|
||||
```text
|
||||
screener-client[.exe]
|
||||
piik-client[.exe]
|
||||
REVISION
|
||||
LICENSE
|
||||
THIRD-PARTY-NOTICES.txt
|
||||
runtime/native/screener-client-capture[.exe] # supported native-media packages
|
||||
runtime/native/piik-client-capture[.exe] # supported native-media packages
|
||||
runtime/tunnel/cloudflared[.exe] # packages that support --link
|
||||
```
|
||||
|
||||
@@ -212,11 +212,11 @@ The executable embeds the Browser assets of the consumed application release and
|
||||
carries that same full Git revision as the package `REVISION`. No compatibility
|
||||
reader accepts a mismatched private build.
|
||||
|
||||
The Windows Client embeds the shared Screener mark through the
|
||||
`cmd/screener-client/screener_windows_amd64.syso` resource; the platform
|
||||
The Windows Client embeds the shared Piik mark through the
|
||||
`cmd/piik-client/piik_windows_amd64.syso` resource; the platform
|
||||
suffix keeps that Windows resource out of Linux and macOS builds.
|
||||
Linux packages include the standard `share/applications` desktop entry and
|
||||
hicolor icon. macOS packages include a thin `Screener Client.app` launcher
|
||||
hicolor icon. macOS packages include a thin `Piik Client.app` launcher
|
||||
with an ICNS resource; the raw Go executable remains available beside it.
|
||||
|
||||
For a native Host smoke run, launch the Client and select a window in the Host
|
||||
@@ -235,53 +235,53 @@ and without Chromium Local Network Access permission. Environment syntax below
|
||||
is POSIX; use equivalent variables on Windows.
|
||||
|
||||
```sh
|
||||
SCREENER_CLIENT_LOCAL_GATE=true \
|
||||
PIIK_CLIENT_LOCAL_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_CLIENT_EXE=/path/to/screener-client \
|
||||
SCREENER_CLIENT_GATE_LAN_ADDRESS=192.168.1.10 \
|
||||
PIIK_CLIENT_EXE=/path/to/piik-client \
|
||||
PIIK_CLIENT_GATE_LAN_ADDRESS=192.168.1.10 \
|
||||
npm run gate:client-local
|
||||
|
||||
SCREENER_CLIENT_LOOPBACK_GATE=true \
|
||||
PIIK_CLIENT_LOOPBACK_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_CLIENT_EXE=/path/to/screener-client \
|
||||
PIIK_CLIENT_EXE=/path/to/piik-client \
|
||||
npm run probe:client-loopback
|
||||
|
||||
SCREENER_CLIENT_MEDIA_GATE=true \
|
||||
PIIK_CLIENT_MEDIA_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_CLIENT_GATE_STUN_URLS=stun:<stun-host>:3478 \
|
||||
PIIK_CLIENT_GATE_STUN_URLS=stun:<stun-host>:3478 \
|
||||
npm run gate:client-media
|
||||
|
||||
SCREENER_CLIENT_NATIVE_HOST_GATE=true \
|
||||
PIIK_CLIENT_NATIVE_HOST_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_GO=/path/to/go \
|
||||
PIIK_GO=/path/to/go \
|
||||
npm run gate:client-native-host
|
||||
|
||||
SCREENER_CLIENT_NATIVE_HOST_GATE=true \
|
||||
SCREENER_CLIENT_CROSS_NAT_GATE=true \
|
||||
PIIK_CLIENT_NATIVE_HOST_GATE=true \
|
||||
PIIK_CLIENT_CROSS_NAT_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_GO=/path/to/go \
|
||||
SCREENER_REMOTE_HOST=<public-test-host> \
|
||||
SCREENER_REMOTE_USER=<ssh-user> \
|
||||
SCREENER_REMOTE_SSH_KEY=/path/to/key \
|
||||
SCREENER_CLIENT_GATE_STUN_URLS=stun:<stun-host>:3478 \
|
||||
PIIK_GO=/path/to/go \
|
||||
PIIK_REMOTE_HOST=<public-test-host> \
|
||||
PIIK_REMOTE_USER=<ssh-user> \
|
||||
PIIK_REMOTE_SSH_KEY=/path/to/key \
|
||||
PIIK_CLIENT_GATE_STUN_URLS=stun:<stun-host>:3478 \
|
||||
npm run gate:client-native-host
|
||||
|
||||
SCREENER_CLIENT_NATIVE_HOST_GATE=true \
|
||||
SCREENER_CLIENT_LINK_MEDIA_GATE=true \
|
||||
PIIK_CLIENT_NATIVE_HOST_GATE=true \
|
||||
PIIK_CLIENT_LINK_MEDIA_GATE=true \
|
||||
CHROME_PATH=/path/to/chrome \
|
||||
SCREENER_GO=/path/to/go \
|
||||
SCREENER_CLOUDFLARED=/path/to/cloudflared \
|
||||
SCREENER_REMOTE_HOST=<public-test-host> \
|
||||
SCREENER_REMOTE_USER=<ssh-user> \
|
||||
SCREENER_REMOTE_SSH_KEY=/path/to/key \
|
||||
PIIK_GO=/path/to/go \
|
||||
PIIK_CLOUDFLARED=/path/to/cloudflared \
|
||||
PIIK_REMOTE_HOST=<public-test-host> \
|
||||
PIIK_REMOTE_USER=<ssh-user> \
|
||||
PIIK_REMOTE_SSH_KEY=/path/to/key \
|
||||
npm run gate:client-native-host
|
||||
|
||||
SCREENER_CLIENT_LINK_GATE=true \
|
||||
SCREENER_GO=/path/to/go \
|
||||
SCREENER_CLOUDFLARED=/path/to/cloudflared \
|
||||
SCREENER_REMOTE_HOST=<public-test-host> \
|
||||
SCREENER_REMOTE_USER=<ssh-user> \
|
||||
SCREENER_REMOTE_SSH_KEY=/path/to/key \
|
||||
PIIK_CLIENT_LINK_GATE=true \
|
||||
PIIK_GO=/path/to/go \
|
||||
PIIK_CLOUDFLARED=/path/to/cloudflared \
|
||||
PIIK_REMOTE_HOST=<public-test-host> \
|
||||
PIIK_REMOTE_USER=<ssh-user> \
|
||||
PIIK_REMOTE_SSH_KEY=/path/to/key \
|
||||
npm run gate:client-link
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Command screener-client is the self-contained Screener Client: it opens a
|
||||
// configured Screener Site, or runs the Local room authority in-process
|
||||
// Command piik-client is the self-contained Piik Client: it opens a
|
||||
// configured Piik Site, or runs the Local room authority in-process
|
||||
// (--local / --link) together with the loopback capability service and the
|
||||
// native media edge. Flags select the mode; clientapp owns every mode's
|
||||
// lifecycle.
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/clientapp"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/clientapp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var options clientapp.Options
|
||||
flag.Func("site", "save and open a Screener Site origin", func(value string) error {
|
||||
flag.Func("site", "save and open a Piik Site origin", func(value string) error {
|
||||
options.Site = value
|
||||
options.SiteSet = true
|
||||
return nil
|
||||
@@ -26,14 +26,14 @@ func main() {
|
||||
flag.BoolVar(&options.Local, "local", false, "use the self-contained Local room authority")
|
||||
flag.BoolVar(&options.Link, "link", false, "create one public Viewer invitation link")
|
||||
flag.BoolVar(&options.Debug, "debug", false, "save opt-in Client diagnostics to rotated files")
|
||||
flag.StringVar(&options.LogDir, "log-dir", "", "diagnostic directory (overrides SCREENER_LOG_DIR)")
|
||||
flag.StringVar(&options.LogDir, "log-dir", "", "diagnostic directory (overrides PIIK_LOG_DIR)")
|
||||
flag.StringVar(&options.CaptureProcess, "capture-process", "", "path to the platform native capture process")
|
||||
flag.StringVar(&options.TunnelProcess, "tunnel-process", "", "path to the packaged public tunnel process")
|
||||
flag.StringVar(&options.ConfigPath, "config", "", "path to the Client configuration file")
|
||||
flag.StringVar(&options.LANAddress, "lan-address", "", "LAN IPv4 address used in Local invitations")
|
||||
flag.IntVar(&options.Port, "port", clientapp.DefaultLocalPort, "Local Screener server port")
|
||||
flag.IntVar(&options.Port, "port", clientapp.DefaultLocalPort, "Local Piik server port")
|
||||
flag.Parse()
|
||||
options.DisableBrowser = os.Getenv("SCREENER_CLIENT_GATE_NO_BROWSER") == "true"
|
||||
options.DisableBrowser = os.Getenv("PIIK_CLIENT_GATE_NO_BROWSER") == "true"
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
File renamed without changes.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
File renamed without changes.
@@ -13,7 +13,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/server/protocol"
|
||||
"github.com/TNTcraftHIM/Piik/internal/server/protocol"
|
||||
"github.com/coder/websocket"
|
||||
"github.com/coder/websocket/wsjson"
|
||||
"github.com/pion/interceptor"
|
||||
File renamed without changes.
@@ -7,7 +7,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
)
|
||||
|
||||
func watchDiagnosticExport(recorder *diagnostics.Recorder) func() {
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
import "github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
|
||||
// Windows exports at orderly shutdown; it has no SIGUSR1 equivalent.
|
||||
func watchDiagnosticExport(*diagnostics.Recorder) func() { return func() {} }
|
||||
@@ -1,4 +1,4 @@
|
||||
// Command screener-server is the Hosted Screener entry point: it loads the
|
||||
// Command piik-server is the Hosted Piik entry point: it loads the
|
||||
// environment, serves the embedded Browser UI together with the signaling and
|
||||
// room API, and stops on SIGINT or SIGTERM. It replaces src/server/index.ts.
|
||||
//
|
||||
@@ -23,10 +23,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Screener/internal/server/app"
|
||||
"github.com/TNTcraftHIM/Screener/internal/server/config"
|
||||
"github.com/TNTcraftHIM/Screener/internal/server/webassets"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/server/app"
|
||||
"github.com/TNTcraftHIM/Piik/internal/server/config"
|
||||
"github.com/TNTcraftHIM/Piik/internal/server/webassets"
|
||||
)
|
||||
|
||||
// shutdownTimeout bounds the ordered stop (signaling, listener, room store).
|
||||
@@ -81,11 +81,11 @@ func fail(err error) {
|
||||
func serve(debug bool) (returnedErr error) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ReplaceAttr: diagnostics.ReplaceAttr}))
|
||||
var recorder *diagnostics.Recorder
|
||||
if debug || serverDebugEnabled(os.Getenv("SCREENER_DEBUG")) {
|
||||
if debug || serverDebugEnabled(os.Getenv("PIIK_DEBUG")) {
|
||||
var err error
|
||||
recorder, err = diagnostics.Open(serverLogDirectory(), "server", BuildRevision)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Screener server diagnostics are unavailable: %w", err)
|
||||
return fmt.Errorf("Piik server diagnostics are unavailable: %w", err)
|
||||
}
|
||||
logger = slog.New(slog.NewMultiHandler(logger.Handler(), recorder.Logger().Handler()))
|
||||
previous, previousWriter, previousFlags := slog.Default(), log.Writer(), log.Flags()
|
||||
@@ -93,18 +93,18 @@ func serve(debug bool) (returnedErr error) {
|
||||
dependencyLog := diagnostics.Writer("stdlib")
|
||||
log.SetOutput(dependencyLog)
|
||||
log.SetFlags(previousFlags)
|
||||
fmt.Fprintln(os.Stderr, "Screener diagnostic log:", recorder.LogPath())
|
||||
fmt.Fprintln(os.Stderr, "Piik diagnostic log:", recorder.LogPath())
|
||||
stopExport := watchDiagnosticExport(recorder)
|
||||
defer func() {
|
||||
stopExport()
|
||||
_ = dependencyLog.Close()
|
||||
logger.Info("screener-server", "event", "stopped", "failed", returnedErr != nil, diagnostics.Error(returnedErr))
|
||||
logger.Info("piik-server", "event", "stopped", "failed", returnedErr != nil, diagnostics.Error(returnedErr))
|
||||
returnedErr = errors.Join(returnedErr, exportServerDiagnostics(recorder), recorder.Close())
|
||||
slog.SetDefault(previous)
|
||||
log.SetOutput(previousWriter)
|
||||
log.SetFlags(previousFlags)
|
||||
}()
|
||||
logger.Info("screener-server", "event", "start", "revision", BuildRevision)
|
||||
logger.Info("piik-server", "event", "start", "revision", BuildRevision)
|
||||
}
|
||||
configuration, err := config.Load(environment())
|
||||
if err != nil {
|
||||
@@ -133,7 +133,7 @@ func serve(debug bool) (returnedErr error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Screener %s is listening on %s:%d; public URL %s\n",
|
||||
fmt.Printf("Piik %s is listening on %s:%d; public URL %s\n",
|
||||
BuildRevision, configuration.ListenHost, port, config.Origin(configuration.PublicBaseURL))
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
@@ -155,7 +155,7 @@ func serverDebugEnabled(value string) bool {
|
||||
}
|
||||
|
||||
func serverLogDirectory() string {
|
||||
if directory := strings.TrimSpace(os.Getenv("SCREENER_LOG_DIR")); directory != "" {
|
||||
if directory := strings.TrimSpace(os.Getenv("PIIK_LOG_DIR")); directory != "" {
|
||||
return directory
|
||||
}
|
||||
if directories := filepath.SplitList(os.Getenv("LOGS_DIRECTORY")); len(directories) > 0 && directories[0] != "" {
|
||||
@@ -167,10 +167,10 @@ func serverLogDirectory() string {
|
||||
func exportServerDiagnostics(recorder *diagnostics.Recorder) error {
|
||||
path, err := recorder.Export()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Screener diagnostic export failed:", err)
|
||||
fmt.Fprintln(os.Stderr, "Piik diagnostic export failed:", err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "Screener diagnostic bundle:", path)
|
||||
fmt.Fprintln(os.Stderr, "Piik diagnostic bundle:", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,27 +7,27 @@ import (
|
||||
)
|
||||
|
||||
func TestLoadEnvironmentFileFillsOnlyAbsentVariables(t *testing.T) {
|
||||
t.Setenv("SCREENER_TEST_PRESET", "from-the-service")
|
||||
t.Setenv("PIIK_TEST_PRESET", "from-the-service")
|
||||
path := filepath.Join(t.TempDir(), ".env")
|
||||
content := "# Application\n" +
|
||||
"SCREENER_TEST_PRESET=from-the-file\n" +
|
||||
"export SCREENER_TEST_EXPORTED=exported\n" +
|
||||
" SCREENER_TEST_QUOTED = \"a b#c\" \n" +
|
||||
"SCREENER_TEST_SINGLE=' padded '\n" +
|
||||
"SCREENER_TEST_EMPTY=\n" +
|
||||
"SCREENER_TEST_MARK=has#hash\n" +
|
||||
"PIIK_TEST_PRESET=from-the-file\n" +
|
||||
"export PIIK_TEST_EXPORTED=exported\n" +
|
||||
" PIIK_TEST_QUOTED = \"a b#c\" \n" +
|
||||
"PIIK_TEST_SINGLE=' padded '\n" +
|
||||
"PIIK_TEST_EMPTY=\n" +
|
||||
"PIIK_TEST_MARK=has#hash\n" +
|
||||
"\n" +
|
||||
"not an assignment\n" +
|
||||
"#SCREENER_TEST_COMMENTED=never\r\n" +
|
||||
"SCREENER_TEST_LAST=tail"
|
||||
"#PIIK_TEST_COMMENTED=never\r\n" +
|
||||
"PIIK_TEST_LAST=tail"
|
||||
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Setenv registers the restore, Unsetenv makes the name absent for the run.
|
||||
for _, name := range []string{
|
||||
"SCREENER_TEST_EXPORTED", "SCREENER_TEST_QUOTED", "SCREENER_TEST_SINGLE",
|
||||
"SCREENER_TEST_EMPTY", "SCREENER_TEST_MARK", "SCREENER_TEST_COMMENTED",
|
||||
"SCREENER_TEST_LAST",
|
||||
"PIIK_TEST_EXPORTED", "PIIK_TEST_QUOTED", "PIIK_TEST_SINGLE",
|
||||
"PIIK_TEST_EMPTY", "PIIK_TEST_MARK", "PIIK_TEST_COMMENTED",
|
||||
"PIIK_TEST_LAST",
|
||||
} {
|
||||
t.Setenv(name, "absent")
|
||||
os.Unsetenv(name)
|
||||
@@ -38,19 +38,19 @@ func TestLoadEnvironmentFileFillsOnlyAbsentVariables(t *testing.T) {
|
||||
}
|
||||
for name, want := range map[string]string{
|
||||
// A variable the service already supplies is never replaced.
|
||||
"SCREENER_TEST_PRESET": "from-the-service",
|
||||
"SCREENER_TEST_EXPORTED": "exported",
|
||||
"SCREENER_TEST_QUOTED": "a b#c",
|
||||
"SCREENER_TEST_SINGLE": " padded ",
|
||||
"SCREENER_TEST_EMPTY": "",
|
||||
"SCREENER_TEST_MARK": "has#hash",
|
||||
"SCREENER_TEST_LAST": "tail",
|
||||
"PIIK_TEST_PRESET": "from-the-service",
|
||||
"PIIK_TEST_EXPORTED": "exported",
|
||||
"PIIK_TEST_QUOTED": "a b#c",
|
||||
"PIIK_TEST_SINGLE": " padded ",
|
||||
"PIIK_TEST_EMPTY": "",
|
||||
"PIIK_TEST_MARK": "has#hash",
|
||||
"PIIK_TEST_LAST": "tail",
|
||||
} {
|
||||
if got, present := os.LookupEnv(name); !present || got != want {
|
||||
t.Errorf("%s = %q, present %t; want %q", name, got, present, want)
|
||||
}
|
||||
}
|
||||
if value, present := os.LookupEnv("SCREENER_TEST_COMMENTED"); present {
|
||||
if value, present := os.LookupEnv("PIIK_TEST_COMMENTED"); present {
|
||||
t.Errorf("commented assignment was applied as %q", value)
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func TestServerDiagnosticSelection(t *testing.T) {
|
||||
t.Fatalf("serverDebugEnabled(%q) = %v, want %v", value, got, want)
|
||||
}
|
||||
}
|
||||
t.Setenv("SCREENER_LOG_DIR", "")
|
||||
t.Setenv("PIIK_LOG_DIR", "")
|
||||
t.Setenv("LOGS_DIRECTORY", "")
|
||||
if got := serverLogDirectory(); got != "logs" {
|
||||
t.Fatalf("default directory = %q", got)
|
||||
@@ -84,7 +84,7 @@ func TestServerDiagnosticSelection(t *testing.T) {
|
||||
if got := serverLogDirectory(); got != "service-logs" {
|
||||
t.Fatalf("systemd directory = %q", got)
|
||||
}
|
||||
t.Setenv("SCREENER_LOG_DIR", "explicit-logs")
|
||||
t.Setenv("PIIK_LOG_DIR", "explicit-logs")
|
||||
if got := serverLogDirectory(); got != "explicit-logs" {
|
||||
t.Fatalf("explicit directory = %q", got)
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
// defaultReleaseAPIURL is DEFAULT_RELEASE_API_URL: the same published release
|
||||
// contract the Browser update notice uses (src/client/lib/release-update.ts).
|
||||
const defaultReleaseAPIURL = "https://api.github.com/repos/TNTcraftHIM/Screener/releases/latest"
|
||||
const defaultReleaseAPIURL = "https://api.github.com/repos/TNTcraftHIM/Piik/releases/latest"
|
||||
|
||||
// Exit codes are UPDATE_EXIT_CODES. deploy/check-release.sh forwards them, so a
|
||||
// checker failure stays distinguishable from "an update exists".
|
||||
@@ -31,13 +31,13 @@ const (
|
||||
|
||||
// releaseUsage is the usage string parseArguments threw, with this binary's
|
||||
// name in place of the script's.
|
||||
const releaseUsage = "Usage: screener-server --check-release --current-file <REVISION> [--api-url <URL>]"
|
||||
const releaseUsage = "Usage: piik-server --check-release --current-file <REVISION> [--api-url <URL>]"
|
||||
|
||||
const (
|
||||
// releaseTimeout bounds the whole check; an operator runs it interactively.
|
||||
releaseTimeout = 5 * time.Second
|
||||
// releasePathPrefix is RELEASE_PATH_PREFIX: the only accepted release page.
|
||||
releasePathPrefix = "/TNTcraftHIM/Screener/releases/tag/"
|
||||
releasePathPrefix = "/TNTcraftHIM/Piik/releases/tag/"
|
||||
releaseHost = "github.com"
|
||||
releaseAPIHost = "api.github.com"
|
||||
)
|
||||
@@ -116,7 +116,7 @@ func checkRelease(ctx context.Context, currentRevision, apiURL, token string) re
|
||||
}
|
||||
request.Header.Set("Accept", "application/vnd.github+json")
|
||||
request.Header.Set("X-GitHub-Api-Version", "2022-11-28")
|
||||
request.Header.Set("User-Agent", "Screener-release-check")
|
||||
request.Header.Set("User-Agent", "Piik-release-check")
|
||||
if authorizesGitHub(endpoint, token) {
|
||||
request.Header.Set("Authorization", "Bearer "+strings.TrimSpace(token))
|
||||
}
|
||||
@@ -203,7 +203,7 @@ type releaseMetadata struct {
|
||||
|
||||
// parseReleaseMetadata ports parseReleaseMetadata. It accepts one shape only: a
|
||||
// published, non-draft release whose tag is a full commit revision and whose
|
||||
// page is exactly https://github.com/TNTcraftHIM/Screener/releases/tag/<that
|
||||
// page is exactly https://github.com/TNTcraftHIM/Piik/releases/tag/<that
|
||||
// revision> with no credentials, port, query or fragment. The returned URL is
|
||||
// rebuilt from the validated parts so nothing unverified reaches the operator.
|
||||
func parseReleaseMetadata(payload []byte) (revision string, releaseURL string, ok bool) {
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
const (
|
||||
deployedRevision = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
latestRevision = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
latestReleaseURL = "https://github.com/TNTcraftHIM/Screener/releases/tag/" + latestRevision
|
||||
latestReleaseURL = "https://github.com/TNTcraftHIM/Piik/releases/tag/" + latestRevision
|
||||
latestRelease = `{"tag_name":"` + latestRevision + `","html_url":"` + latestReleaseURL + `"}`
|
||||
)
|
||||
|
||||
@@ -40,29 +40,29 @@ func TestParseReleaseMetadataAcceptsOnlyTheStrictReleaseIdentity(t *testing.T) {
|
||||
{"other host", tagged("https://evil.example"), "", ""},
|
||||
{
|
||||
"userinfo",
|
||||
tagged("https://user@github.com/TNTcraftHIM/Screener/releases/tag/" + latestRevision),
|
||||
tagged("https://user@github.com/TNTcraftHIM/Piik/releases/tag/" + latestRevision),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"port",
|
||||
tagged("https://github.com:8443/TNTcraftHIM/Screener/releases/tag/" + latestRevision),
|
||||
tagged("https://github.com:8443/TNTcraftHIM/Piik/releases/tag/" + latestRevision),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"plaintext page",
|
||||
tagged("http://github.com/TNTcraftHIM/Screener/releases/tag/" + latestRevision),
|
||||
tagged("http://github.com/TNTcraftHIM/Piik/releases/tag/" + latestRevision),
|
||||
"", "",
|
||||
},
|
||||
{"query", tagged(latestReleaseURL + "?asset=1"), "", ""},
|
||||
{"fragment", tagged(latestReleaseURL + "#assets"), "", ""},
|
||||
{
|
||||
"encoded path separator",
|
||||
tagged("https://github.com/TNTcraftHIM%2FScreener/releases/tag/" + latestRevision),
|
||||
tagged("https://github.com/TNTcraftHIM%2FPiik/releases/tag/" + latestRevision),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"page tag disagrees with the release tag",
|
||||
tagged("https://github.com/TNTcraftHIM/Screener/releases/tag/" + deployedRevision),
|
||||
tagged("https://github.com/TNTcraftHIM/Piik/releases/tag/" + deployedRevision),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
@@ -144,7 +144,7 @@ func TestCheckReleaseReportsTheDeployedComparison(t *testing.T) {
|
||||
if got := request.Header.Get("X-GitHub-Api-Version"); got != "2022-11-28" {
|
||||
t.Errorf("X-GitHub-Api-Version = %q", got)
|
||||
}
|
||||
if got := request.Header.Get("User-Agent"); got != "Screener-release-check" {
|
||||
if got := request.Header.Get("User-Agent"); got != "Piik-release-check" {
|
||||
t.Errorf("User-Agent = %q", got)
|
||||
}
|
||||
writer.WriteHeader(testCase.status)
|
||||
@@ -6,6 +6,6 @@ if [ "$#" -gt 1 ]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
current_file="${1:-/opt/screener/current/REVISION}"
|
||||
current_file="${1:-/opt/piik/current/REVISION}"
|
||||
|
||||
exec /opt/screener/current/screener-server --check-release --current-file "$current_file"
|
||||
exec /opt/piik/current/piik-server --check-release --current-file "$current_file"
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM gcr.io/distroless/static-debian13:nonroot-amd64@sha256:e754765ad9e167b0677b41c617fd44afb7b9818a477f48f17bda08e12cfb98cb
|
||||
WORKDIR /app
|
||||
COPY --chmod=0555 screener-server /app/
|
||||
COPY --chmod=0555 piik-server /app/
|
||||
COPY --chmod=0444 LICENSE THIRD-PARTY-NOTICES.txt REVISION /app/
|
||||
ENV LISTEN_HOST=0.0.0.0 SCREENER_LOG_DIR=/home/nonroot/logs ROOM_DATABASE_PATH=/home/nonroot/rooms.sqlite
|
||||
ENV LISTEN_HOST=0.0.0.0 PIIK_LOG_DIR=/home/nonroot/logs ROOM_DATABASE_PATH=/home/nonroot/rooms.sqlite
|
||||
USER 65532:65532
|
||||
EXPOSE 8787/tcp 3478/udp 3479/udp 3480/udp 7882/udp
|
||||
ENTRYPOINT ["/app/screener-server"]
|
||||
ENTRYPOINT ["/app/piik-server"]
|
||||
@@ -1,9 +1,9 @@
|
||||
map $http_upgrade $screener_connection_upgrade {
|
||||
map $http_upgrade $piik_connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
limit_req_zone $binary_remote_addr zone=screener_site_access:10m rate=5r/m;
|
||||
limit_req_zone $binary_remote_addr zone=piik_site_access:10m rate=5r/m;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
@@ -30,8 +30,8 @@ server {
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
access_log /var/log/nginx/screener.access.log;
|
||||
error_log /var/log/nginx/screener.error.log warn;
|
||||
access_log /var/log/nginx/piik.access.log;
|
||||
error_log /var/log/nginx/piik.error.log warn;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
@@ -48,7 +48,7 @@ server {
|
||||
}
|
||||
|
||||
location = /api/site-access {
|
||||
limit_req zone=screener_site_access burst=5 nodelay;
|
||||
limit_req zone=piik_site_access burst=5 nodelay;
|
||||
limit_req_status 429;
|
||||
proxy_pass http://127.0.0.1:8787;
|
||||
proxy_http_version 1.1;
|
||||
@@ -65,7 +65,7 @@ server {
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $screener_connection_upgrade;
|
||||
proxy_set_header Connection $piik_connection_upgrade;
|
||||
proxy_read_timeout 5h;
|
||||
proxy_send_timeout 5h;
|
||||
proxy_buffering off;
|
||||
|
||||
+31
-31
@@ -3,15 +3,15 @@ set -Eeuo pipefail
|
||||
umask 022
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
printf 'usage: SCREENER_PUBLIC_ORIGIN=https://share.example.com %s /opt/screener/uploads/<release>.release.json\n' "$0" >&2
|
||||
printf 'usage: PIIK_PUBLIC_ORIGIN=https://share.example.com %s /opt/piik/uploads/<release>.release.json\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
upload_root='/opt/screener/uploads'
|
||||
release_root='/opt/screener/releases'
|
||||
current='/opt/screener/current'
|
||||
lock='/opt/screener/deploy.lock'
|
||||
public_origin="${SCREENER_PUBLIC_ORIGIN:-}"
|
||||
upload_root='/opt/piik/uploads'
|
||||
release_root='/opt/piik/releases'
|
||||
current='/opt/piik/current'
|
||||
lock='/opt/piik/deploy.lock'
|
||||
public_origin="${PIIK_PUBLIC_ORIGIN:-}"
|
||||
descriptor="$(realpath -e -- "$1")"
|
||||
stage=''
|
||||
release_owned=0
|
||||
@@ -39,8 +39,8 @@ main_asset="$(descriptor_text mainAsset)"
|
||||
[[ "$revision" =~ ^[0-9a-f]{40}$ ]]
|
||||
[[ "$release_id" =~ ^[0-9a-f]{7}$ ]]
|
||||
test "$release_id" = "${revision:0:7}"
|
||||
test "$artifact_name" = "screener-${release_id}-runtime.tar.gz"
|
||||
test "$manifest_name" = "screener-${release_id}.manifest.tsv"
|
||||
test "$artifact_name" = "piik-${release_id}-runtime.tar.gz"
|
||||
test "$manifest_name" = "piik-${release_id}.manifest.tsv"
|
||||
[[ "$artifact_sha" =~ ^[0-9a-f]{64}$ ]]
|
||||
[[ "$manifest_sha" =~ ^[0-9a-f]{64}$ ]]
|
||||
[[ "$file_count" =~ ^[1-9][0-9]*$ ]]
|
||||
@@ -105,7 +105,7 @@ recover() {
|
||||
trap - ERR HUP INT TERM EXIT
|
||||
set +e
|
||||
if [ "$cutover_started" -eq 1 ]; then
|
||||
systemctl stop screener.service || ok=0
|
||||
systemctl stop piik.service || ok=0
|
||||
if [ "$(readlink -f -- "$current" 2>/dev/null)" != "$old_release" ]; then
|
||||
link="${current}.recover-${release_id}-$$"
|
||||
if [ -e "$link" ] || [ -L "$link" ]; then
|
||||
@@ -115,7 +115,7 @@ recover() {
|
||||
fi
|
||||
fi
|
||||
test "$(readlink -f -- "$current" 2>/dev/null)" = "$old_release" || ok=0
|
||||
systemctl start screener.service || ok=0
|
||||
systemctl start piik.service || ok=0
|
||||
wait_for_health || ok=0
|
||||
fi
|
||||
rm -f -- "${current}.${release_id}-$$" "${current}.recover-${release_id}-$$" || ok=0
|
||||
@@ -126,7 +126,7 @@ recover() {
|
||||
printf 'deployment_failed=%s recovery_ok=%s current=%s active=%s\n' \
|
||||
"$code" "$ok" \
|
||||
"$(readlink -f -- "$current" 2>/dev/null || true)" \
|
||||
"$(systemctl show screener.service -p ActiveState --value 2>/dev/null || true)" >&2
|
||||
"$(systemctl show piik.service -p ActiveState --value 2>/dev/null || true)" >&2
|
||||
if [ "$ok" -ne 1 ]; then
|
||||
exit 90
|
||||
fi
|
||||
@@ -150,15 +150,15 @@ test -f "$artifact"
|
||||
test -f "$manifest"
|
||||
test "$(sha256sum "$artifact" | awk '{print $1}')" = "$artifact_sha"
|
||||
test "$(sha256sum "$manifest" | awk '{print $1}')" = "$manifest_sha"
|
||||
for service in screener nginx; do
|
||||
for service in piik nginx; do
|
||||
test "$(systemctl show "${service}.service" -p ActiveState --value)" = 'active'
|
||||
test "$(systemctl show "${service}.service" -p NRestarts --value)" = '0'
|
||||
done
|
||||
# The first Go/embedded-media cutover owns its infrastructure recovery separately.
|
||||
test -x "$old_release/screener-server"
|
||||
old_pid="$(systemctl show screener.service -p MainPID --value)"
|
||||
test -x "$old_release/piik-server"
|
||||
old_pid="$(systemctl show piik.service -p MainPID --value)"
|
||||
test "$old_pid" -gt 1
|
||||
test "$(readlink -f "/proc/${old_pid}/exe")" = "$old_release/screener-server"
|
||||
test "$(readlink -f "/proc/${old_pid}/exe")" = "$old_release/piik-server"
|
||||
|
||||
while IFS= read -r raw_entry; do
|
||||
entry="$raw_entry"
|
||||
@@ -170,7 +170,7 @@ while IFS= read -r raw_entry; do
|
||||
esac
|
||||
case "$entry" in
|
||||
/*|*\\*) printf 'invalid archive entry: %s\n' "$raw_entry" >&2; exit 41 ;;
|
||||
LICENSE|REVISION|THIRD-PARTY-NOTICES.txt|screener-server) ;;
|
||||
LICENSE|REVISION|THIRD-PARTY-NOTICES.txt|piik-server) ;;
|
||||
*) printf 'unexpected archive entry: %s\n' "$raw_entry" >&2; exit 42 ;;
|
||||
esac
|
||||
done < <(tar -tzf "$artifact")
|
||||
@@ -183,7 +183,7 @@ tar --no-same-owner --no-same-permissions -xzf "$artifact" -C "$stage"
|
||||
tab=$'\t'
|
||||
if [ -n "$(tail -c 1 "$manifest")" ]; then exit 61; fi
|
||||
if grep -qEv "^[0-9a-f]{64}${tab}[0-9]+${tab}[^${tab}]*$" "$manifest"; then exit 62; fi
|
||||
if grep -qEv "^[0-9a-f]{64}${tab}[0-9]+${tab}(LICENSE|REVISION|THIRD-PARTY-NOTICES\.txt|screener-server)$" "$manifest"; then exit 63; fi
|
||||
if grep -qEv "^[0-9a-f]{64}${tab}[0-9]+${tab}(LICENSE|REVISION|THIRD-PARTY-NOTICES\.txt|piik-server)$" "$manifest"; then exit 63; fi
|
||||
if [ -n "$(cut -f3 "$manifest" | sort | uniq -d)" ]; then exit 64; fi
|
||||
if [ "$(wc -l < "$manifest")" -ne "$file_count" ]; then exit 65; fi
|
||||
if [ -n "$(find "$stage" -type l)" ]; then exit 66; fi
|
||||
@@ -199,23 +199,23 @@ printf 'artifact_manifest=ok files=%s revision=%s\n' "$file_count" "$revision"
|
||||
|
||||
# Set the mode before testing it: an archive packaged on a host without an
|
||||
# executable bit (Windows) records 0644, and the release owns the bit here.
|
||||
chmod 0755 "$stage/screener-server"
|
||||
test -x "$stage/screener-server"
|
||||
chmod 0755 "$stage/piik-server"
|
||||
test -x "$stage/piik-server"
|
||||
chmod 0644 "$stage/LICENSE" "$stage/REVISION" "$stage/THIRD-PARTY-NOTICES.txt"
|
||||
|
||||
# Runs as the service user under the manager (no sudo/polkit round trip) so a
|
||||
# binary or environment file the service cannot use fails here, before cutover.
|
||||
systemd-run \
|
||||
--uid=screener \
|
||||
--gid=screener \
|
||||
--uid=piik \
|
||||
--gid=piik \
|
||||
--wait \
|
||||
--collect \
|
||||
--quiet \
|
||||
--service-type=exec \
|
||||
--property='EnvironmentFile=/etc/screener/screener.env' \
|
||||
--property='Environment=SCREENER_ENV=production' \
|
||||
--property='EnvironmentFile=/etc/piik/piik.env' \
|
||||
--property='Environment=PIIK_ENV=production' \
|
||||
--property='RuntimeMaxSec=20s' \
|
||||
"$stage/screener-server" --check-config
|
||||
"$stage/piik-server" --check-config
|
||||
|
||||
if [ -n "$(comm -12 <(find "$old_release" -type f -printf '%D:%i\n' | sort -u) <(find "$stage" -type f -printf '%D:%i\n' | sort -u))" ]; then
|
||||
exit 80
|
||||
@@ -237,21 +237,21 @@ nginx_restarts="$(systemctl show nginx.service -p NRestarts --value)"
|
||||
cutover_since="$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
cutover_start="$(date +%s%3N)"
|
||||
cutover_started=1
|
||||
systemctl stop screener.service
|
||||
test "$(systemctl show screener.service -p ActiveState --value)" = 'inactive'
|
||||
systemctl stop piik.service
|
||||
test "$(systemctl show piik.service -p ActiveState --value)" = 'inactive'
|
||||
ln -s "$release" "${current}.${release_id}-$$"
|
||||
mv -Tf "${current}.${release_id}-$$" "$current"
|
||||
test "$(readlink -f -- "$current")" = "$release"
|
||||
systemctl start screener.service
|
||||
systemctl start piik.service
|
||||
wait_for_health
|
||||
health_ready="$(date +%s%3N)"
|
||||
|
||||
test "$(systemctl show screener.service -p ActiveState --value)" = 'active'
|
||||
test "$(systemctl show screener.service -p NRestarts --value)" = '0'
|
||||
test "$(systemctl show piik.service -p ActiveState --value)" = 'active'
|
||||
test "$(systemctl show piik.service -p NRestarts --value)" = '0'
|
||||
test "$(systemctl show nginx.service -p NRestarts --value)" = "$nginx_restarts"
|
||||
test "$(nft list table inet bonfire_filter | sha256sum | awk '{print $1}')" = "$firewall_before"
|
||||
test "$(readlink -f -- "$current")" = "$release"
|
||||
pid="$(systemctl show screener.service -p MainPID --value)"
|
||||
pid="$(systemctl show piik.service -p MainPID --value)"
|
||||
test "$pid" -gt 1
|
||||
test "$(readlink -f "/proc/${pid}/cwd")" = "$release"
|
||||
test "$(curl -fsS --max-time 5 http://127.0.0.1:8787/healthz)" = '{"status":"ok"}'
|
||||
@@ -262,7 +262,7 @@ test "$(curl -sS -o /dev/null -w '%{http_code}' --max-time 8 "$public_origin/$ma
|
||||
if [ "$old_asset" != "$main_asset" ]; then
|
||||
test "$(curl -sS -o /dev/null -w '%{http_code}' --max-time 8 "$public_origin/$old_asset")" = '404'
|
||||
fi
|
||||
test -z "$(journalctl -u screener.service --since "$cutover_since" -p warning --no-pager --output=cat)"
|
||||
test -z "$(journalctl -u piik.service --since "$cutover_since" -p warning --no-pager --output=cat)"
|
||||
|
||||
asset_sha="$(curl -fsS --max-time 8 "$public_origin/$main_asset" | sha256sum | awk '{print $1}')"
|
||||
release_owned=0
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
[Unit]
|
||||
Description=Screener web, signaling, STUN and SFU application
|
||||
Description=Piik web, signaling, STUN and SFU application
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=screener
|
||||
Group=screener
|
||||
WorkingDirectory=/opt/screener/current
|
||||
Environment=SCREENER_ENV=production
|
||||
Environment=ROOM_DATABASE_PATH=/var/lib/screener/rooms.sqlite
|
||||
EnvironmentFile=/etc/screener/screener.env
|
||||
ExecStart=/opt/screener/current/screener-server
|
||||
User=piik
|
||||
Group=piik
|
||||
WorkingDirectory=/opt/piik/current
|
||||
Environment=PIIK_ENV=production
|
||||
Environment=ROOM_DATABASE_PATH=/var/lib/piik/rooms.sqlite
|
||||
EnvironmentFile=/etc/piik/piik.env
|
||||
ExecStart=/opt/piik/current/piik-server
|
||||
Restart=on-failure
|
||||
RestartSec=3s
|
||||
TimeoutStopSec=20s
|
||||
UMask=0077
|
||||
StateDirectory=screener
|
||||
StateDirectory=piik
|
||||
StateDirectoryMode=0700
|
||||
LogsDirectory=screener
|
||||
LogsDirectory=piik
|
||||
LogsDirectoryMode=0700
|
||||
|
||||
NoNewPrivileges=true
|
||||
+6
-6
@@ -2,12 +2,12 @@
|
||||
|
||||
[English Quick Start](../README.md) · [中文快速开始](../README.zh-CN.md)
|
||||
|
||||
## Use Screener
|
||||
## Use Piik
|
||||
|
||||
| What you need | Start here |
|
||||
| --- | --- |
|
||||
| Join a friend or share a screen | [Quick Start](../README.md) |
|
||||
| Run Client, choose a mode, or fix capture trouble | [Client guide](../cmd/screener-client/README.md) |
|
||||
| Run Client, choose a mode, or fix capture trouble | [Client guide](../cmd/piik-client/README.md) |
|
||||
| Collect a useful bug report | [Diagnostics and export](./reference/configuration.md#diagnostics) |
|
||||
| Host your own site | [Self-hosting](./operations/self-hosting.md) |
|
||||
| Configure ports, access or persistence | [Configuration reference](./reference/configuration.md) |
|
||||
@@ -33,7 +33,7 @@ npm run dev
|
||||
In a second terminal, start the server. For a POSIX shell:
|
||||
|
||||
```sh
|
||||
PORT=8788 PUBLIC_BASE_URL=http://localhost:8787 go run ./cmd/screener-server
|
||||
PORT=8788 PUBLIC_BASE_URL=http://localhost:8787 go run ./cmd/piik-server
|
||||
```
|
||||
|
||||
Or in PowerShell:
|
||||
@@ -41,8 +41,8 @@ Or in PowerShell:
|
||||
```powershell
|
||||
$env:PORT = '8788'
|
||||
$env:PUBLIC_BASE_URL = 'http://localhost:8787'
|
||||
go build -o build/dev/screener-server.exe ./cmd/screener-server
|
||||
./build/dev/screener-server.exe
|
||||
go build -o build/dev/piik-server.exe ./cmd/piik-server
|
||||
./build/dev/piik-server.exe
|
||||
```
|
||||
|
||||
The fixed Windows executable path avoids repeated firewall prompts from `go run`.
|
||||
@@ -87,7 +87,7 @@ Browse [all ADRs](./adr/) for their context and consequences.
|
||||
results, failed controls and limits; neither promises universal performance.
|
||||
- [Research directory](./research/): transport, capture, platform and backend evidence.
|
||||
- [Maintenance](./maintenance.md): document ownership and repository lifecycle.
|
||||
- [Licensing](../licenses/README.md): Screener's MIT scope and third-party notices.
|
||||
- [Licensing](../licenses/README.md): Piik's MIT scope and third-party notices.
|
||||
|
||||
Research distinguishes observations from assumptions. Product modules own
|
||||
accepted behavior, source and tests own implementation detail, and Git/PRs own
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
## Durable Rationale
|
||||
|
||||
Screener serves one broadcaster and a small group of trusted friends. Low
|
||||
Piik serves one broadcaster and a small group of trusted friends. Low
|
||||
latency, private access, browser viewing, and low server media cost matter more
|
||||
than public-broadcast scale. Direct WebRTC therefore remains the preferred
|
||||
media path, while centralized media is fallback infrastructure rather than the
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
## Context
|
||||
|
||||
Screener serves one Host and at most 20 trusted Viewers. The application server
|
||||
Piik serves one Host and at most 20 trusted Viewers. The application server
|
||||
owns a small room and authorization aggregate while WebRTC and LiveKit own live
|
||||
media sessions. Frequent application releases should not force the Host to
|
||||
create another room or redistribute invitations, but a database must not become
|
||||
|
||||
@@ -12,7 +12,7 @@ describe the earlier implementation and its production history.
|
||||
|
||||
## Context
|
||||
|
||||
Direct Browser WebRTC gives Screener its desired latency and distributed cost,
|
||||
Direct Browser WebRTC gives Piik its desired latency and distributed cost,
|
||||
but one Host cannot fan out to every Viewer and some endpoint pairs cannot
|
||||
establish usable direct media. The product needs automatic peer distribution and
|
||||
bounded server fallback without exposing topology choices to users or turning
|
||||
@@ -214,7 +214,7 @@ tokens. Replacement, abort, timeout, confirmed media-participant loss, share
|
||||
rollover, stop, and room deletion transfer the resources they own into the same typed drain path.
|
||||
Only successful room deletion plus an absence readback releases that generation,
|
||||
so a stale token cannot recreate off-ledger media. The deployment must dedicate
|
||||
the LiveKit namespace to Screener and complete startup ownership/cleanup before
|
||||
the LiveKit namespace to Piik and complete startup ownership/cleanup before
|
||||
accepting traffic; [self-hosting operations](../operations/self-hosting.md) owns
|
||||
that procedure.
|
||||
|
||||
@@ -236,7 +236,7 @@ capacity poll or second resource-specific controller.
|
||||
|
||||
Ordinary Peers use deployment STUN only. Browser SFU PeerConnections use an
|
||||
empty external ICE-server list while retaining LiveKit-signaled UDP candidates.
|
||||
Screener configures no TURN, ICE/TCP, media TCP, or TLS-relayed media. A future
|
||||
Piik configures no TURN, ICE/TCP, media TCP, or TLS-relayed media. A future
|
||||
strict-firewall transport must be accepted as a LiveKit-internal capability, not
|
||||
as another application route candidate.
|
||||
|
||||
@@ -270,7 +270,7 @@ they mean only one complete same-identity `qualityLimitationReason` delta in
|
||||
experiment; it does not locate the physical bottleneck or prove end-to-end
|
||||
quality. `other`, missing, reset, hidden, or stale evidence is unknown. SFU
|
||||
publication and subscription state remains owned by LiveKit plus the exact
|
||||
Viewer's continuing decoded progress. Screener does not combine loss, RTT,
|
||||
Viewer's continuing decoded progress. Piik does not combine loss, RTT,
|
||||
jitter, bitrate, FPS, resolution, or freezes into a weighted route score.
|
||||
|
||||
Routing degradation requires three consecutive complete degraded deltas for the
|
||||
|
||||
@@ -12,12 +12,12 @@ implementation; [media quality](../product/media-quality.md) owns current behavi
|
||||
|
||||
## Context
|
||||
|
||||
Screener sends one realtime game-screen source through independent P2P
|
||||
Piik sends one realtime game-screen source through independent P2P
|
||||
connections and, when needed, one shared LiveKit publication. WebRTC and
|
||||
LiveKit already own congestion control, encoder adaptation, retransmission,
|
||||
simulcast construction, subscriber bandwidth estimation, and layer selection.
|
||||
|
||||
Earlier experiments added a Screener-defined lower SFU encoding and treated
|
||||
Earlier experiments added a Piik-defined lower SFU encoding and treated
|
||||
quality preference as an application policy. Production evidence showed that
|
||||
an always-active lower encoding can compete with the highest encoding on a
|
||||
constrained Host-to-SFU path. It did not justify replacing LiveKit's native
|
||||
@@ -123,7 +123,7 @@ than claiming complete source isolation.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Screener owns fewer media mechanisms and follows the pinned frameworks'
|
||||
- Piik owns fewer media mechanisms and follows the pinned frameworks'
|
||||
supported control surfaces.
|
||||
- A capable Browser Host or relay can use H.264 hardware encoding while another
|
||||
sender remains on VP8 without a room-protocol branch; the Host can explicitly
|
||||
@@ -136,7 +136,7 @@ than claiming complete source isolation.
|
||||
outbound video sender but no additional capture or encoder beyond the sender
|
||||
that already exists.
|
||||
- A Host may need to lower its explicit share profile when encoder or uplink
|
||||
capacity is insufficient; Screener does not silently remove constrained
|
||||
capacity is insufficient; Piik does not silently remove constrained
|
||||
Viewer support.
|
||||
- ADR-0005's native-edge local convergence is deployed and performs bounded
|
||||
real-candidate comparisons without owning media adaptation. Weighted or global
|
||||
@@ -144,7 +144,7 @@ than claiming complete source isolation.
|
||||
|
||||
## Stop Lines
|
||||
|
||||
- No Screener resolution/FPS/bitrate ladder or representation formula.
|
||||
- No Piik resolution/FPS/bitrate ladder or representation formula.
|
||||
- No codec wire/state, GPU/MFT allowlist, persistent codec cache, parallel
|
||||
VP8/H.264 route, active-edge codec churn, or LiveKit backup publication. The
|
||||
local pre-share Host selector is the only manual codec surface.
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
## Context
|
||||
|
||||
The Browser is the current Screener interaction surface, but it cannot own native
|
||||
The Browser is the current Piik interaction surface, but it cannot own native
|
||||
capture, hardware encode, or reusable native sockets. A self-contained package
|
||||
must add those capabilities without creating another room model, signaling
|
||||
protocol, route controller, or UI.
|
||||
|
||||
Existing Screener room, admission, signaling, and routing behavior already has
|
||||
Existing Piik room, admission, signaling, and routing behavior already has
|
||||
one TypeScript implementation. Rewriting that behavior in the Helper would make
|
||||
Hosted and Local deployments diverge without improving the media path.
|
||||
|
||||
@@ -37,7 +37,7 @@ topologies and makes a saved Site unavailable while another room source runs.
|
||||
core and the same built Browser assets with local configuration; no
|
||||
deployment gets a second product core. Its implementation is owned by
|
||||
[ADR-0012](./0012-shared-go-backend-core.md).
|
||||
2. The packaged product is Screener Client. Its Go process is the cross-platform
|
||||
2. The packaged product is Piik Client. Its Go process is the cross-platform
|
||||
entry and native capability provider. It starts `/health` and one `/control`
|
||||
endpoint on IPv4 loopback within ports `39721` through `39730` before room-
|
||||
source selection and retains them until the process exits.
|
||||
@@ -61,7 +61,7 @@ topologies and makes a saved Site unavailable while another room source runs.
|
||||
with the page; a picker, share, or room source does not own the socket. The
|
||||
Browser forwards current signaling and remains the participant.
|
||||
5. A platform package contains one Go executable carrying the same core and
|
||||
embedded Browser assets used by Hosted Screener. It may also carry one
|
||||
embedded Browser assets used by Hosted Piik. It may also carry one
|
||||
process-isolated capture binary and the pinned `cloudflared` sidecar. Those
|
||||
sidecars are the only supervised children and keep their bounded lifetime.
|
||||
Platform packaging is metadata around that entry, not another long-running
|
||||
@@ -74,7 +74,7 @@ topologies and makes a saved Site unavailable while another room source runs.
|
||||
network permission. Clearing Site data simply requires opening it from the
|
||||
Client again.
|
||||
7. A self-contained Local deployment serves reachable LAN peers without a
|
||||
central Screener service. Its explicit `--link` mode starts one accountless
|
||||
central Piik service. Its explicit `--link` mode starts one accountless
|
||||
Cloudflare Quick Tunnel for the same HTTP/WebSocket surface. The Client
|
||||
reserves the exact IPv4 listener before creating that tunnel, then applies
|
||||
its HTTPS origin before the server starts serving that listener. It retains the same
|
||||
@@ -162,7 +162,7 @@ topologies and makes a saved Site unavailable while another room source runs.
|
||||
target and must start the assembled Local authority, pass `/healthz`, and
|
||||
stop it cleanly before the candidate is accepted.
|
||||
14. The root package manifest is the single dependency contract for the Browser
|
||||
bundle and repository tooling. No host installs packages to run Screener, so
|
||||
bundle and repository tooling. No host installs packages to run Piik, so
|
||||
the manifest has no runtime half, and no second Client dependency list or
|
||||
post-install package surgery is used.
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ the same Browser build.
|
||||
## Decision
|
||||
|
||||
1. One Go module at the repository root owns the product core.
|
||||
`cmd/screener-server` (Hosted) and `cmd/screener-client` (Client) are entry
|
||||
`cmd/piik-server` (Hosted) and `cmd/piik-client` (Client) are entry
|
||||
points over the same `internal/server` packages and own only their defaults,
|
||||
reachability, and lifecycle policy. Neither reimplements rooms, admission,
|
||||
signaling, or routing. The TypeScript server, its bundled runtime, the process
|
||||
@@ -65,7 +65,7 @@ the same Browser build.
|
||||
[ADR-0002](./0002-memory-resident-protected-rooms.md). Both storage modes,
|
||||
their validation, and their failure policy are unchanged, and no build
|
||||
requires a C toolchain.
|
||||
8. The port changes no contract. Signaling stays `screener-v21`, the Client
|
||||
8. The port changed no contract. Signaling stayed on its then-current v21 wire; the Client
|
||||
loopback stays v8, capture framing stays v4, and the HTTP API, cookies, error
|
||||
codes, and close codes keep their exact shapes. No compatibility alias, dual
|
||||
reader, or migration is added for a change of implementation language.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
## Context
|
||||
|
||||
The owner accepts one self-contained Screener process for the current STUN and
|
||||
The owner accepts one self-contained Piik process for the current STUN and
|
||||
SFU services, and one shared encoded-media model for capable Native P2P nodes
|
||||
and the SFU. Bundling or supervising coturn/LiveKit executables does not meet
|
||||
this requirement. The existing product uses coturn only as STUN, not TURN.
|
||||
@@ -28,7 +28,7 @@ acceptance. Mature simulcast implementations provide the starting model.
|
||||
produce the highest required output and its lower fallbacks, and stop upper
|
||||
outputs no child needs. This is not a promise of a single Host encode under
|
||||
all conditions. Representation settings come from the chosen media component
|
||||
within Host ceilings, not a new Screener quality score or arbitrary ladder.
|
||||
within Host ceilings, not a new Piik quality score or arbitrary ladder.
|
||||
4. Each child receives only its selected output. Multiple active encodings do
|
||||
not imply sending every output to every child. Preserve the original input,
|
||||
source clock and unaffected siblings. Playback quality, cadence and recovery
|
||||
|
||||
@@ -29,7 +29,7 @@ in [ADR-0011](./0011-browser-assisted-native-fanout.md) remains independently ow
|
||||
upstream subscription, room-wide minimum or topology operation is introduced.
|
||||
2. Each group uses stock WebRTC encoding and adaptation through an independent
|
||||
local producer. Each outgoing connection retains stock ICE, DTLS-SRTP,
|
||||
bandwidth estimation, RTP packetization, pacing and loss recovery. Screener
|
||||
bandwidth estimation, RTP packetization, pacing and loss recovery. Piik
|
||||
connects existing demand observations to group budgets and membership; it
|
||||
adds no congestion estimator, quality score or arbitrary resolution ladder.
|
||||
3. Reuse `HostPeer` and its existing signaling, sender-mutation and retirement
|
||||
|
||||
+20
-18
@@ -15,7 +15,7 @@ bootstrap/updater; do not call this wrapper generic.
|
||||
|
||||
## Release Boundary
|
||||
|
||||
A routine application release changes only the built Screener server binary and
|
||||
A routine application release changes only the built Piik server binary and
|
||||
the Browser assets it embeds. It does not change infrastructure,
|
||||
service units, proxy/firewall rules, secrets, media listener configuration, or
|
||||
persistent room state.
|
||||
@@ -42,16 +42,16 @@ The packager refuses a dirty tree, builds the Browser assets and the
|
||||
linux/amd64 server binary from that exact revision without cgo, records the
|
||||
full revision, emits a runtime archive plus path/size/SHA-256 manifest and release descriptor, and
|
||||
extracts its own artifact to verify it. The archive contains exactly
|
||||
`screener-server`, `LICENSE`, `THIRD-PARTY-NOTICES.txt`, and `REVISION`. Upload
|
||||
the archive, manifest, and descriptor together to `/opt/screener/uploads`.
|
||||
`piik-server`, `LICENSE`, `THIRD-PARTY-NOTICES.txt`, and `REVISION`. Upload
|
||||
the archive, manifest, and descriptor together to `/opt/piik/uploads`.
|
||||
|
||||
The same application descriptor is also the Client assembly input. On each
|
||||
target platform, provide that platform's Go toolchain:
|
||||
|
||||
```sh
|
||||
SCREENER_GO=/path/to/go node scripts/assemble-client.mjs \
|
||||
/outside/repository/app-release/screener-<revision>.release.json \
|
||||
/outside/repository/Screener-Client \
|
||||
PIIK_GO=/path/to/go node scripts/assemble-client.mjs \
|
||||
/outside/repository/app-release/piik-<revision>.release.json \
|
||||
/outside/repository/Piik-Client \
|
||||
--target windows-amd64 \
|
||||
--capture /path/to/platform-capture \
|
||||
--tunnel /path/to/cloudflared
|
||||
@@ -114,7 +114,7 @@ current CI workflow produces short-lived candidates but does not publish a
|
||||
GitHub Release; publication remains an explicit distribution decision.
|
||||
|
||||
The default Client launcher starts immediately, then performs one background
|
||||
request to the official Screener GitHub Releases API. It shows a link only when
|
||||
request to the official Piik GitHub Releases API. It shows a link only when
|
||||
the latest release has a valid full revision different from the packaged one.
|
||||
The request sends no current revision, credentials, room data, or media data;
|
||||
network errors, private-repository responses, and missing releases are treated
|
||||
@@ -127,7 +127,7 @@ bash deploy/check-release.sh
|
||||
```
|
||||
|
||||
The script runs the deployed binary's release check, which reads
|
||||
`/opt/screener/current/REVISION` and prints one JSON result.
|
||||
`/opt/piik/current/REVISION` and prints one JSON result.
|
||||
Exit status `0` means the deployed revision is current, `10` means a newer
|
||||
release is available, and `20` means the check could not establish a valid
|
||||
release identity. For a private repository, inject a short-lived `GITHUB_TOKEN`
|
||||
@@ -137,9 +137,11 @@ state. A different current-revision file may be supplied as its only argument.
|
||||
|
||||
## Permanent-Room Schema Cutover
|
||||
|
||||
Schema 2 / signaling `screener-v23` requires matching Web/Client/Server builds
|
||||
and an accepted active-session interruption. Native control stays v9; Browser
|
||||
credential keys stay unchanged. This is not an app-only release.
|
||||
The schema 2 / signaling v23 cutover required matching Web/Client/Server builds
|
||||
and an accepted active-session interruption. Native control stayed v9; that
|
||||
schema change preserved Browser credential keys. It was not an app-only release.
|
||||
The separate [brand cutover](./research/piik-rename-plan.md) must preserve this
|
||||
database rather than repeat the schema change.
|
||||
|
||||
1. Verify the candidate; record the current release, environment, absolute DB
|
||||
path and ownership. Stop ingress and the old application; take and retain a
|
||||
@@ -184,21 +186,21 @@ restore the previous infrastructure.
|
||||
Run the tracked server entry with the uploaded descriptor:
|
||||
|
||||
```sh
|
||||
sudo env SCREENER_PUBLIC_ORIGIN=https://share.example.com \
|
||||
sudo env PIIK_PUBLIC_ORIGIN=https://share.example.com \
|
||||
bash /path/to/repository/deploy/release-app.sh \
|
||||
/opt/screener/uploads/screener-<revision>.release.json
|
||||
/opt/piik/uploads/piik-<revision>.release.json
|
||||
```
|
||||
|
||||
The wrapper:
|
||||
|
||||
1. takes a deployment lock and validates the descriptor, revision, archive,
|
||||
manifest, current Go process, Screener/nginx service state, and public origin;
|
||||
manifest, current Go process, Piik/nginx service state, and public origin;
|
||||
2. rejects unexpected archive paths, links, file types, or duplicate inodes;
|
||||
3. extracts to a new release directory and verifies every file hash and size;
|
||||
4. validates production configuration by running the packaged binary's
|
||||
configuration check as the service user under a bounded runtime;
|
||||
5. proves the old and new releases share no regular-file inode;
|
||||
6. atomically switches `/opt/screener/current`, starts the service, and polls
|
||||
6. atomically switches `/opt/piik/current`, starts the service, and polls
|
||||
bounded local/public health; and
|
||||
7. restores the exact prior symlink and service when cutover or health fails.
|
||||
|
||||
@@ -225,8 +227,8 @@ Verify only the surfaces relevant to the release:
|
||||
|
||||
- local and public `/healthz` return `{"status":"ok"}`;
|
||||
- the public HTML references the new immutable main asset;
|
||||
- Screener and nginx have expected active/restart state;
|
||||
- Screener owns each configured STUN/SFU UDP listener and public reachability
|
||||
- Piik and nginx have expected active/restart state;
|
||||
- Piik owns each configured STUN/SFU UDP listener and public reachability
|
||||
matches the configuration;
|
||||
- the current symlink and served revision match the descriptor;
|
||||
- room creation, Host authentication, one direct Viewer, and configured SFU
|
||||
@@ -240,7 +242,7 @@ to [verification status](./verification-status.md), not routine postflight.
|
||||
## Recovery
|
||||
|
||||
Before cutover, the wrapper keeps the exact prior release path. On failure after
|
||||
the switch begins, it stops Screener, restores that path atomically, restarts the
|
||||
the switch begins, it stops Piik, restores that path atomically, restarts the
|
||||
service, and waits for health. A failed recovery exits distinctly and requires
|
||||
operator intervention; it must not silently report the new release as active.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This runbook owns initial single-host service setup. Application releases use
|
||||
|
||||
## Embedded Media Configuration
|
||||
|
||||
The current source embeds STUN and SFU in the Screener process under
|
||||
The current source embeds STUN and SFU in the Piik process under
|
||||
[ADR-0013](../adr/0013-embedded-node-local-media.md). Hosted `STUN_URLS`
|
||||
advertises ordinary discovery and enables the UDP 3478 listener on
|
||||
`STUN_LISTEN_HOST` (IPv4, default `0.0.0.0`). Enabling
|
||||
@@ -16,7 +16,7 @@ public-link Client modes use discovery without creating media-service listeners.
|
||||
Set `SFU_UDP_PORT=7882` to enable automatic embedded SFU fallback. Its IPv4 bind
|
||||
address is `SFU_LISTEN_HOST`, default `0.0.0.0`; `SFU_PUBLIC_IP` optionally
|
||||
overrides the advertised IPv4 address when the host is behind NAT. Unset or
|
||||
blank `SFU_UDP_PORT` keeps SFU disabled. SFU control uses authenticated Screener
|
||||
blank `SFU_UDP_PORT` keeps SFU disabled. SFU control uses authenticated Piik
|
||||
signaling through the Web origin. No separate media-service executable, control
|
||||
origin, or API credentials are needed by this source contract.
|
||||
|
||||
@@ -26,27 +26,27 @@ the active-session check, matching artifacts and public media verification below
|
||||
## Single-Host Topology
|
||||
|
||||
```text
|
||||
Browser -- HTTPS/WSS --> nginx :443 --> Screener :8787
|
||||
Browser -- HTTPS/WSS --> nginx :443 --> Piik :8787
|
||||
Browser <---------- DTLS-SRTP P2P ----------> Browser
|
||||
Browser -------- ordinary STUN/UDP --------> Screener :3478
|
||||
Browser -------- optional STUN/UDP --------> Screener :3479/3480
|
||||
Browser <--------- DTLS-SRTP/UDP ----------> Screener :7882
|
||||
Browser -------- ordinary STUN/UDP --------> Piik :3478
|
||||
Browser -------- optional STUN/UDP --------> Piik :3479/3480
|
||||
Browser <--------- DTLS-SRTP/UDP ----------> Piik :7882
|
||||
```
|
||||
|
||||
The public baseline uses one Screener Go binary, nginx, a valid Web TLS
|
||||
The public baseline uses one Piik Go binary, nginx, a valid Web TLS
|
||||
certificate, and time synchronization. nginx terminates Web HTTPS/WSS and
|
||||
proxies only to Screener's private application listener; media UDP reaches the
|
||||
proxies only to Piik's private application listener; media UDP reaches the
|
||||
Go process directly. There is no separate SFU token endpoint or TCP 7880 service.
|
||||
Web and STUN may use different DNS names on the same public IP. Another proxy or
|
||||
firewall owner needs its own matching updater and recovery checks.
|
||||
|
||||
Expose only the public listeners in
|
||||
[configuration reference](../reference/configuration.md). Screener TCP 8787 stays
|
||||
[configuration reference](../reference/configuration.md). Piik TCP 8787 stays
|
||||
private. STUN answers Binding requests only; TURN allocations remain unavailable.
|
||||
|
||||
## Templates
|
||||
|
||||
- [Screener systemd unit](../../deploy/systemd/screener.service.example)
|
||||
- [Piik systemd unit](../../deploy/systemd/piik.service.example)
|
||||
- [nginx site](../../deploy/nginx/share.bonfire.icu.conf.example)
|
||||
|
||||
Copy templates outside the repository, inject independent secrets through an
|
||||
@@ -56,16 +56,16 @@ domains, certificates, users, and resource limits required by the host.
|
||||
## Initial Setup
|
||||
|
||||
1. Configure DNS and TLS for the Web origin and STUN name.
|
||||
2. Install nginx. The Screener release is one static binary and needs no
|
||||
2. Install nginx. The Piik release is one static binary and needs no
|
||||
language runtime or separate media-service executable.
|
||||
3. Create an unprivileged `screener` service account, `/opt/screener/releases`,
|
||||
`/opt/screener/uploads`, and an access-restricted environment file.
|
||||
3. Create an unprivileged `piik` service account, `/opt/piik/releases`,
|
||||
`/opt/piik/uploads`, and an access-restricted environment file.
|
||||
4. Provision one verified initial immutable release and atomically point
|
||||
`/opt/screener/current` to it before enabling the unit. The tracked release
|
||||
`/opt/piik/current` to it before enabling the unit. The tracked release
|
||||
wrapper is upgrade-only and deliberately refuses a missing prior release;
|
||||
this repository does not provide a generic first-install transaction.
|
||||
5. SQLite is the Hosted default. The service template selects
|
||||
`/var/lib/screener/rooms.sqlite` in its service-owned StateDirectory; retain
|
||||
`/var/lib/piik/rooms.sqlite` in its service-owned StateDirectory; retain
|
||||
that absolute path in the environment file and include it in the host's
|
||||
backup/recovery policy. Use `ROOM_DATABASE_PATH=:memory:` only for intentional
|
||||
process-only rooms. Do not leave an empty override in a service environment.
|
||||
@@ -75,7 +75,7 @@ domains, certificates, users, and resource limits required by the host.
|
||||
preserve the private application boundary.
|
||||
7. Apply the public-port allowlist and confirm every retired TURN/TCP port
|
||||
is closed.
|
||||
8. Start Screener, then nginx. Screener binds its configured media listeners
|
||||
8. Start Piik, then nginx. Piik binds its configured media listeners
|
||||
before accepting signaling and closes them with the application; a listener
|
||||
bind failure rolls back startup. Verify public UDP reachability separately.
|
||||
|
||||
@@ -93,15 +93,15 @@ proxy/firewall configuration; verify those on the target deployment.
|
||||
|
||||
Verify the release archive against its descriptor and manifest using the
|
||||
[release procedure](../deployment.md), then extract its four files into a new
|
||||
build-context directory: `screener-server`, `LICENSE`, `THIRD-PARTY-NOTICES.txt`
|
||||
build-context directory: `piik-server`, `LICENSE`, `THIRD-PARTY-NOTICES.txt`
|
||||
and `REVISION`. Use that directory, not the repository or a secrets directory:
|
||||
|
||||
```sh
|
||||
docker build --platform linux/amd64 \
|
||||
-f /path/to/Screener/deploy/container/Dockerfile \
|
||||
-t screener:<full-revision> /path/to/extracted-runtime
|
||||
docker run --rm --env-file /path/to/screener.env \
|
||||
screener:<full-revision> --check-config
|
||||
-f /path/to/Piik/deploy/container/Dockerfile \
|
||||
-t piik:<full-revision> /path/to/extracted-runtime
|
||||
docker run --rm --env-file /path/to/piik.env \
|
||||
piik:<full-revision> --check-config
|
||||
```
|
||||
|
||||
Use the existing [production configuration](../reference/configuration.md).
|
||||
@@ -116,14 +116,14 @@ to a proxy running on the same host. Omit UDP publish options for disabled SFU
|
||||
or auxiliary STUN listeners; use the matching port if configuration changes it.
|
||||
|
||||
```sh
|
||||
docker run -d --name screener --restart unless-stopped --stop-timeout 20 \
|
||||
docker run -d --name piik --restart unless-stopped --stop-timeout 20 \
|
||||
--read-only --cap-drop ALL --security-opt no-new-privileges \
|
||||
--env-file /path/to/screener.env \
|
||||
--mount type=volume,source=screener-data,target=/home/nonroot \
|
||||
--env-file /path/to/piik.env \
|
||||
--mount type=volume,source=piik-data,target=/home/nonroot \
|
||||
-e ROOM_DATABASE_PATH=/home/nonroot/rooms.sqlite \
|
||||
-p 127.0.0.1:8787:8787/tcp \
|
||||
-p 3478:3478/udp -p 3479:3479/udp -p 3480:3480/udp -p 7882:7882/udp \
|
||||
screener:<full-revision>
|
||||
piik:<full-revision>
|
||||
```
|
||||
|
||||
The image's `/home/nonroot` is owned by UID/GID `65532:65532` with mode `0700`.
|
||||
@@ -132,7 +132,7 @@ must already be writable by that identity. Keep this volume when replacing the
|
||||
container. Set `ROOM_DATABASE_PATH=:memory:` for memory-only room authority. Diagnostics
|
||||
remain opt-in and use `/home/nonroot/logs`; [export and retention](../reference/configuration.md#diagnostics)
|
||||
remain the operator's responsibility. Do not mount application files writable.
|
||||
With diagnostics enabled, `docker kill --signal=USR1 screener` requests a local
|
||||
With diagnostics enabled, `docker kill --signal=USR1 piik` requests a local
|
||||
export without stopping the container; the ZIP remains in the mounted log directory.
|
||||
|
||||
Check `/healthz` from the host and public proxy, then verify configured STUN/SFU
|
||||
@@ -154,28 +154,28 @@ The routine application wrapper cannot perform or recover it.
|
||||
Client artifacts. Check active sessions and obtain the owner's acceptance of
|
||||
share interruption before cutover; old pages and Clients must reload or
|
||||
update together.
|
||||
2. Retain the exact prior release path, Screener unit and drop-ins, environment,
|
||||
2. Retain the exact prior release path, Piik unit and drop-ins, environment,
|
||||
nginx configuration, and external media-service units, configuration, secrets,
|
||||
and enabled/active state for rollback. Keep this material access-restricted
|
||||
outside the repository. Define recovery for any persistent-state or firewall
|
||||
surface the transaction actually changes.
|
||||
3. Stage the current unit with
|
||||
`ExecStart=/opt/screener/current/screener-server` and
|
||||
`SCREENER_ENV=production`. Remove retired `NODE_ENV`, `PEER_ASSISTED_MEDIA`
|
||||
`ExecStart=/opt/piik/current/piik-server` and
|
||||
`PIIK_ENV=production`. Remove retired `NODE_ENV`, `PEER_ASSISTED_MEDIA`
|
||||
and external `LIVEKIT_*` configuration; use the current
|
||||
[environment contract](../reference/configuration.md), including
|
||||
`SFU_UDP_PORT=7882` when fallback is enabled. Replace route `NODE_DEBUG` with
|
||||
`SCREENER_DEBUG=route` when needed. Validate the new binary's production
|
||||
`PIIK_DEBUG=route` when needed. Validate the new binary's production
|
||||
configuration as the service user before switching.
|
||||
4. Stop Screener and the old coturn/LiveKit services. Disable those old media
|
||||
services and remove the installed Screener LiveKit-readiness drop-in so they
|
||||
4. Stop Piik and the old coturn/LiveKit services. Disable those old media
|
||||
services and remove the installed Piik LiveKit-readiness drop-in so they
|
||||
cannot reclaim ports or delay startup. Verify that UDP 3478/3479/3480/7882
|
||||
are released before the new Go process binds them. Install the current unit,
|
||||
environment and nginx template, remove the old RTC proxy locations, validate
|
||||
nginx, and reload systemd. Preserve unrelated proxy headers, limits, TLS,
|
||||
asset handling, and firewall rules.
|
||||
5. Atomically point the current release at the verified candidate, start
|
||||
Screener, and reload nginx. Verify the actual unit command and environment,
|
||||
Piik, and reload nginx. Verify the actual unit command and environment,
|
||||
local/public health, the matching Web asset, UDP listener ownership, public
|
||||
STUN Binding and admitted SFU media, and the agreed active-session outcome.
|
||||
6. On failure, stop the new Go process and confirm it released its UDP sockets.
|
||||
@@ -196,11 +196,11 @@ Later application-only releases use the ordinary
|
||||
Allow UDP 3479 and 3480 in both the cloud security group and the existing
|
||||
nftables input rule, validating the complete ruleset with
|
||||
`nft -c -f /etc/nftables.conf`. Set `NAT_PREDICTION_ENABLED=true` and restart
|
||||
Screener within an accepted service window. Verify `ss -lunp` shows all three
|
||||
Screener STUN listeners and that a public Binding request succeeds on each.
|
||||
Piik within an accepted service window. Verify `ss -lunp` shows all three
|
||||
Piik STUN listeners and that a public Binding request succeeds on each.
|
||||
Do not add auxiliary URLs to `STUN_URLS`; enabled connections derive them from
|
||||
the ordinary STUN authority. Keep both firewall rules while the capability is
|
||||
enabled. Set `NAT_PREDICTION_ENABLED=false` and restart Screener before removing
|
||||
enabled. Set `NAT_PREDICTION_ENABLED=false` and restart Piik before removing
|
||||
the auxiliary firewall rules. Avoid verbose STUN/ICE logging because those
|
||||
requests contain client IP addresses.
|
||||
|
||||
@@ -211,15 +211,15 @@ public IPv4.
|
||||
## Operational Verification
|
||||
|
||||
- `/healthz` returns `{"status":"ok"}` locally and through the public origin.
|
||||
- Screener and nginx are active with expected restart counts and bounded
|
||||
logs/resources; Screener owns the configured STUN/SFU UDP listeners.
|
||||
- Piik and nginx are active with expected restart counts and bounded
|
||||
logs/resources; Piik owns the configured STUN/SFU UDP listeners.
|
||||
- The official Trickle ICE sample obtains an ordinary UDP `srflx` candidate from
|
||||
the configured STUN service and no relay candidate.
|
||||
- A direct room presents media on two networks when Peer ICE succeeds.
|
||||
- A constrained route creates one managed Host publication and only admitted
|
||||
subscriptions over embedded SFU UDP; Peer descendants remain ordinary P2P.
|
||||
- Blocking all UDP reaches a clear bounded failure.
|
||||
- Restarting Screener in stable mode retains room authority while Browser
|
||||
- Restarting Piik in stable mode retains room authority while Browser
|
||||
sessions and media reconnect from fresh process state.
|
||||
|
||||
Representative network, mobile, audio, 20-Viewer, and long-running evidence is
|
||||
|
||||
@@ -132,7 +132,7 @@ Each ordinary Browser PeerConnection owns stock WebRTC congestion control and
|
||||
sender adaptation. Clones share one underlying media source and therefore do not provide
|
||||
complete simultaneous isolation: framework source-wants aggregation may still
|
||||
partially reduce frames available to sibling clones. Sibling outputs may differ;
|
||||
Screener does not impose a room-wide minimum. The Host's one Browser SFU
|
||||
Piik does not impose a room-wide minimum. The Host's one Browser SFU
|
||||
publication uses the share-generation codec and selected ceilings. Its ordinary
|
||||
simulcast outputs follow pinned LiveKit screen-share construction: original and
|
||||
half size at the same frame rate, with a quarter-bitrate lower ceiling and its
|
||||
@@ -200,7 +200,7 @@ native source. This gives one difficult path stock per-sender adaptation without
|
||||
lowering the shared representation for healthy paths. It adds no quality score,
|
||||
timer, or room-wide media setting.
|
||||
|
||||
Screener does not maintain an application bitrate/resolution ladder, scene
|
||||
Piik does not maintain an application bitrate/resolution ladder, scene
|
||||
detector, periodic quality controller, manual SFU layer selector, or
|
||||
application-defined whole-room lowest-common-denominator target.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ room identity, current state, roster, and one manual media-reconnect action.
|
||||
Controls and text must remain usable without overlap or horizontal overflow on
|
||||
desktop and mobile viewports.
|
||||
|
||||
Screener Client opens this same application in the system Browser. Its small
|
||||
Piik Client opens this same application in the system Browser. Its small
|
||||
startup surface selects Local, temporary public invitation, or a configured
|
||||
Site before entering the Host workspace. Viewer links opened at that activated
|
||||
origin may use the same running Client without changing the Viewer UI. Starting a share offers the
|
||||
|
||||
@@ -128,9 +128,9 @@ SFU offer/answer, ICE and output demand use the existing authenticated room
|
||||
WebSocket. The server binds each physical connection to the current participant,
|
||||
share and publication; it issues no separate media token or room-service URL.
|
||||
Browser SFU PeerConnections use the server's UDP candidates and no external
|
||||
ICE-server list. Ordinary peer connections use deployment STUN. Hosted Screener
|
||||
ICE-server list. Ordinary peer connections use deployment STUN. Hosted Piik
|
||||
owns its configured Binding-only STUN listeners and optional SFU UDP listener in
|
||||
the same Go process. Screener
|
||||
the same Go process. Piik
|
||||
configures no TURN, ICE/TCP, media TCP, or TLS-relayed media path. HTTPS/WSS is a
|
||||
separate control transport and remains TLS/TCP.
|
||||
|
||||
@@ -151,7 +151,7 @@ the same bounded route recovery. Source capture remains Host-owned throughout.
|
||||
Browser WebRTC and the shared Pion/LiveKit media adapter own ICE, consent,
|
||||
congestion control, bitrate, frame rate, resolution, retransmission, pacing and
|
||||
layer selection. Direct-child media demand does not create a topology operation.
|
||||
When the per-share convergence gate is enabled, Screener uses an exact persistent native
|
||||
When the per-share convergence gate is enabled, Piik uses an exact persistent native
|
||||
sender limitation only to trigger one measured experiment through the existing
|
||||
serial operation. Three fresh complete limited deltas from one exact sender may
|
||||
trigger that experiment on a newly committed availability or direct-convergence
|
||||
@@ -181,7 +181,7 @@ frame rate, or bitrate across persistent complete windows and produces no
|
||||
freeze or pause; otherwise the old Peer route stays. The Host publication
|
||||
ingress and every Viewer subscription are separate quality paths. One Viewer's
|
||||
SFU proof never authorizes another Viewer. Disabling the gate leaves quality
|
||||
state diagnostic. Screener has no weighted route score, general parent-wide
|
||||
state diagnostic. Piik has no weighted route score, general parent-wide
|
||||
prediction, all-pairs probe, periodic rebalance, persistent parent blacklist,
|
||||
NAT classification, or independent depth cap.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Last updated: 2026-09-10
|
||||
|
||||
Screener is private, low-latency game screen sharing for one Host and up to 20
|
||||
Piik is private, low-latency game screen sharing for one Host and up to 20
|
||||
authenticated friends. The current product surface is Web Host, Web Viewer, and
|
||||
Browser relay; desktop and mobile Browsers are Viewer targets. It is not a
|
||||
public broadcast service. Hosted and Client run one shared Go core
|
||||
@@ -68,7 +68,7 @@ implementation and routine UI detail.
|
||||
available, and anonymous provenance distinguishes ordinary from predicted
|
||||
selected paths. The configuration default remains stock ICE. The only
|
||||
application fallback is one bounded embedded SFU/UDP
|
||||
publication; Screener configures no TURN or TCP media route. A pre-share
|
||||
publication; Piik configures no TURN or TCP media route. A pre-share
|
||||
peer-only policy can exclude that SFU suffix for one share generation.
|
||||
- Every endpoint shares one steady outbound-copy cap, default `2` and limited to
|
||||
`1..3`. One room controller owns one committed graph, one reconcile loop, and
|
||||
@@ -94,12 +94,12 @@ implementation and routine UI detail.
|
||||
|
||||
## Current Snapshot
|
||||
|
||||
The permanent-room candidate uses strict `screener-v23` Browser/server signaling,
|
||||
The current contract uses strict `piik-v23` Browser/server signaling,
|
||||
Native control v9 and capture v7 together. Embedded SFU SDP/ICE and demand travel over the
|
||||
authenticated room WebSocket, without an external room service or media token.
|
||||
Committed first-frame readiness, bounded candidate-relative progress, durable
|
||||
room authority and the H.264/VP8 sender gate remain. [Status](./status.md)
|
||||
separates this source from last known production; protocol rollback requires
|
||||
indexes source and deployment evidence; protocol rollback requires
|
||||
matching Browser and Client artifacts, not only an application symlink.
|
||||
|
||||
Current work is owned by the [TODO ledger](./todo.md). Open physical evidence is
|
||||
|
||||
@@ -8,7 +8,7 @@ service secret store or an untracked access-restricted environment file.
|
||||
|
||||
| Variable | Contract |
|
||||
| --- | --- |
|
||||
| `SCREENER_ENV` | `development` or `production`, default `development`; required for every server deployment: `production` enables production-only validation and the `Secure` site-access cookie. |
|
||||
| `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. |
|
||||
@@ -35,7 +35,7 @@ public-link Client construction create no SFU listener. The relay does not
|
||||
provide application E2EE.
|
||||
|
||||
The SQLite parent directory must exist and be writable. The systemd template
|
||||
sets `/var/lib/screener/rooms.sqlite` under its managed state directory; the
|
||||
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
|
||||
@@ -53,26 +53,26 @@ Diagnostics are local and opt-in. Enable them **before** reproducing the problem
|
||||
|
||||
| Surface | Enable | Export |
|
||||
| --- | --- | --- |
|
||||
| Client | Start with `--debug` or `SCREENER_DEBUG=client` | Press `D` in the terminal for a ZIP |
|
||||
| Client | Start with `--debug` or `PIIK_DEBUG=client` | Press `D` in the terminal for a ZIP |
|
||||
| Browser Host/Viewer | Add `?debug=1` to the page URL, before any invitation fragment | Use the download button beside language/theme controls |
|
||||
| Hosted Server | Start with `--debug`, `SCREENER_DEBUG=server` or `SCREENER_DEBUG=route` | On Unix, `kill -USR1 <pid>`; also exported at orderly shutdown |
|
||||
| Hosted Server | Start with `--debug`, `PIIK_DEBUG=server` or `PIIK_DEBUG=route` | On Unix, `kill -USR1 <pid>`; also exported at orderly shutdown |
|
||||
|
||||
Client/Server ZIP and Browser JSON reports are separate: when investigating
|
||||
Browser/Client cooperation, include both from the same reproduction. Neither
|
||||
action stops an active share or uploads anything. Browser export also remains
|
||||
available as `await window.__SCREENER_DEBUG__.export()` in DevTools.
|
||||
available as `await window.__PIIK_DEBUG__.export()` in DevTools.
|
||||
|
||||
Client logs go to `logs` beside the executable, falling back to `Screener/logs`
|
||||
Client 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
|
||||
`SCREENER_LOG_DIR`; an explicit directory must be writable. Choosing a
|
||||
`PIIK_LOG_DIR`; an explicit directory must be writable. Choosing a
|
||||
directory alone does not enable collection. Non-interactive Clients export at
|
||||
orderly shutdown. On Client, `SCREENER_DEBUG=route` alone retains console route
|
||||
orderly shutdown. On Client, `PIIK_DEBUG=route` alone retains console route
|
||||
tracing; use `--debug` for file collection and the `D` action.
|
||||
|
||||
Hosted logs use `SCREENER_LOG_DIR`, otherwise systemd `LOGS_DIRECTORY`,
|
||||
Hosted logs use `PIIK_LOG_DIR`, otherwise systemd `LOGS_DIRECTORY`,
|
||||
otherwise `logs` under the working directory. The service unit supplies
|
||||
`/var/log/screener` with mode `0700`. Normal service notices remain in the
|
||||
`/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.
|
||||
|
||||
@@ -129,10 +129,10 @@ project references and the reasons for this collection boundary.
|
||||
| Port | Scope | Owner |
|
||||
| ---: | --- | --- |
|
||||
| TCP 80/443 | public | HTTP redirect and HTTPS/WSS reverse proxy |
|
||||
| UDP 3478 | public | in-process STUN-only Screener listener |
|
||||
| UDP 3479/3480 | public when NAT prediction is enabled | in-process auxiliary STUN-only Screener listeners |
|
||||
| UDP 7882 (or `SFU_UDP_PORT`) | public when SFU enabled | in-process Screener WebRTC media |
|
||||
| TCP 8787 | private | Screener application |
|
||||
| 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
|
||||
@@ -142,7 +142,7 @@ 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. Screener
|
||||
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
|
||||
|
||||
@@ -136,7 +136,7 @@ It has three concrete failures/limits:
|
||||
|
||||
- The secondary sender's `framesSent` stayed zero despite sending the complete
|
||||
payload. Its `qualityLimitationReason=none` is not useful proof that the
|
||||
borrowed encoding fits that connection. Existing Screener sender evidence
|
||||
borrowed encoding fits that connection. Existing Piik sender evidence
|
||||
cannot consume those counters unchanged.
|
||||
- In a VP8 late-join arm, the secondary received bytes but decoded zero frames
|
||||
and sent 34 PLI requests. Those requests did not make the primary encoder
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
OpenAI's agent-first repository treats `AGENTS.md` as a map into a structured,
|
||||
versioned knowledge base. Its reported failure mode for one large instruction
|
||||
file is the same one observed in Screener: scarce context is crowded out, every
|
||||
file is the same one observed in Piik: scarce context is crowded out, every
|
||||
rule appears equally important, stale guidance accumulates, and ownership is
|
||||
hard to verify. The recommended corrective structure is progressive disclosure,
|
||||
cross-links, and mechanical freshness/structure checks. Codex concatenates the
|
||||
@@ -34,7 +34,7 @@ below that value and using nested context for genuinely distinct subtrees. Its
|
||||
bounded-memory guidance starts consolidation at 80% rather than treating the
|
||||
hard limit as the normal operating target.
|
||||
|
||||
Screener therefore warns at the published recommendation or 80% of a loader
|
||||
Piik therefore warns at the published recommendation or 80% of a loader
|
||||
limit, then fails only at a real loading boundary or a small explicit buffer:
|
||||
32 KiB for the Codex chain, 20,000 characters for Hermes, and 250 effective
|
||||
Claude lines above the 200-line recommendation. The same envelope applies to the
|
||||
@@ -55,7 +55,7 @@ Sources:
|
||||
### Documentation Shape
|
||||
|
||||
Diataxis separates tutorial, how-to, reference, and explanation because mixing
|
||||
reader goals makes each form harder to use. Screener's internal product modules
|
||||
reader goals makes each form harder to use. Piik's internal product modules
|
||||
are compact reference; ADRs are explanation of a decision; deployment is a
|
||||
how-to/reference boundary; research is evidence and explanation. The framework
|
||||
does not require creating all four categories when there is no reader need.
|
||||
@@ -76,7 +76,7 @@ Sources:
|
||||
|
||||
## Applicability
|
||||
|
||||
Screener is small enough that a vector database, memory provider, generated code
|
||||
Piik is small enough that a vector database, memory provider, generated code
|
||||
map, parallel agent-context format, or separate RFC repository would add more
|
||||
ownership than it removes. The useful practices are bounded always-on context,
|
||||
one owner per fact, domain-shaped reference, evidence on demand, short ADRs,
|
||||
|
||||
@@ -49,7 +49,7 @@ bounded graph controller; absent LiveKit configuration still means P2P-only
|
||||
service. Room privacy and topology-optimization controls remain independent.
|
||||
The old environment variable must be removed before the next deployment.
|
||||
There is no Host-star compatibility path to port. Removing the unused
|
||||
authentication fields requires the coordinated private `screener-v21` release;
|
||||
authentication fields required the coordinated private signaling v21 release;
|
||||
rollback to the prior server must also restore its environment configuration.
|
||||
|
||||
[ADR-0009](../adr/0009-optional-nat-prediction.md) distinguishes server-owned
|
||||
|
||||
@@ -208,4 +208,4 @@ copies no source code and adds no dependency. W3C material uses the
|
||||
[W3C Document License](https://www.w3.org/copyright/document-license-2023/).
|
||||
Chromium and WebRTC source files carry BSD-style licenses. Chrome for Developers
|
||||
prose is CC BY 4.0, with samples under Apache 2.0. These sources are evidence
|
||||
only; their implementations are not incorporated into Screener.
|
||||
only; their implementations are not incorporated into Piik.
|
||||
@@ -23,7 +23,7 @@ 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. Screener follows
|
||||
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
|
||||
@@ -49,9 +49,9 @@ credentials or route policy; those stay in the Browser/server protocol.
|
||||
|
||||
## Client Composition
|
||||
|
||||
The Client and Hosted Screener run the same server core, so the local package is
|
||||
The Client 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 Client README](../../cmd/screener-client/README.md) owns
|
||||
tunnel sidecars; [the Client README](../../cmd/piik-client/README.md) owns
|
||||
that layout. In Local mode the Client 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
|
||||
@@ -67,7 +67,7 @@ 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 Screener origin completed it after Chromium received
|
||||
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.
|
||||
|
||||
@@ -97,7 +97,7 @@ 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 Client responsible for shipping those updates and adds substantial
|
||||
package size. These facts do not prove equivalent Screener media behavior.
|
||||
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
|
||||
@@ -147,7 +147,7 @@ The sidecar remains an explicit package input rather than a linked Client
|
||||
dependency.
|
||||
|
||||
The peer topology gate now treats native `getStats()` RTP identity and frame
|
||||
totals as its portable core proof. Detailed Screener quality metrics enrich a
|
||||
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.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Baseline: `3da8ecd22a3499e660f498e527ad4ffbaef08c82`.
|
||||
|
||||
## Goal
|
||||
|
||||
The owner requests source/library-level STUN and SFU inside the Screener Go
|
||||
The owner requests source/library-level STUN and SFU inside the Piik Go
|
||||
process. Bundled coturn/LiveKit executables, automatic installers, subprocess
|
||||
supervision and embedding the full LiveKit service do not meet this goal.
|
||||
The owner has also agreed to [node-local adaptive reuse](./node-local-adaptation.md):
|
||||
@@ -25,7 +25,7 @@ meet this requirement and is not an SFU replacement candidate.
|
||||
Retain H264/VP8, Opus, per-subscriber adaptation, retransmission, recovery and
|
||||
the existing three STUN destinations. Do not trade weak-Viewer experience for a
|
||||
smaller package, invent an application quality score or add a media ladder.
|
||||
The media library, not Screener, must own congestion and layer decisions.
|
||||
The media library, not Piik, must own congestion and layer decisions.
|
||||
No recording, mixing, TURN relay, public port scanning or production test.
|
||||
Selective local transcoding is now in research scope under the agreed model;
|
||||
the existing fanout-only probe does not establish that capability.
|
||||
@@ -53,7 +53,7 @@ because its example compiles. Keep test executables under the worktree's stable
|
||||
v3 and ICE v2. Do not introduce another older media stack by default.
|
||||
- inlivedev/sfu uses Pion WebRTC v4 and exposes room/client APIs. Its README
|
||||
explicitly warns that its API is early-stage; listed features are claims to
|
||||
verify, not proof of Screener's required behavior.
|
||||
verify, not proof of Piik's required behavior.
|
||||
- Galene is useful architectural reference, not yet an accepted library adapter.
|
||||
|
||||
## Current Evidence
|
||||
@@ -91,7 +91,7 @@ Do not add that second transport merely to change the service's name.
|
||||
WHIP is HTTP signaling for WebRTC ingest, not a replacement media transport.
|
||||
Its no-renegotiation constraint must be checked against live audio/source changes;
|
||||
it is not adopted merely because the request/response looks simpler. The current
|
||||
Screener signaling owner remains authoritative during this evaluation.
|
||||
Piik signaling owner remains authoritative during this evaluation.
|
||||
|
||||
## Sources
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ that changes this boundary.
|
||||
Native libp2p, Tailscale, and mobile studies are useful operational evidence,
|
||||
but their relay reservation, raw-socket control, address discovery, native
|
||||
coordination, and sampled networks differ from browser WebRTC. Their success
|
||||
rates are not Screener coverage estimates.
|
||||
rates are not Piik coverage estimates.
|
||||
|
||||
## TURN Screening And No-Go
|
||||
|
||||
@@ -171,11 +171,11 @@ measured `B_pub` and `sum(B_s)`, so the SFU advantage is not assumed.
|
||||
This no-go is an application-scope decision, not a claim that TURN is broken.
|
||||
Coturn remains a valid BSD-3-Clause STUN/TURN implementation, and LiveKit
|
||||
supports TCP and embedded/external TURN options. Framework capability alone
|
||||
does not require enabling every transport in Screener.
|
||||
does not require enabling every transport in Piik.
|
||||
|
||||
## SFU Admission Evidence
|
||||
|
||||
LiveKit controls do not directly express Screener's resource dimensions:
|
||||
LiveKit controls do not directly express Piik's resource dimensions:
|
||||
|
||||
- room `maxParticipants` limits participant count;
|
||||
- `canPublishSources` is an authorization allowlist;
|
||||
|
||||
@@ -208,7 +208,7 @@ extension forcibly disabled **Broadcast IP for Best WebRTC Performance**;
|
||||
correcting the setting/extension restored Native sharing. The confirmed cause
|
||||
is that extension's WebRTC policy, not unsupported Windows capture. VPN
|
||||
extensions may reapply the override; the
|
||||
[Chromium WebRTC FAQ](../../cmd/screener-client/README.md#chromium-webrtc-connections)
|
||||
[Chromium WebRTC FAQ](../../cmd/piik-client/README.md#chromium-webrtc-connections)
|
||||
owns the user steps. This does not authorize a Browser-specific transport fallback.
|
||||
|
||||
An isolated Chrome 152.0.7977.82 data-channel A/B verifies the policy
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
## Result
|
||||
|
||||
Screener Client can own one process-isolated Windows capture and hardware H.264
|
||||
Piik Client can own one process-isolated Windows capture and hardware H.264
|
||||
encoder, feed its Annex-B access units into one Pion source, and deliver that
|
||||
source through independent WebRTC transports to unmodified Chrome receivers.
|
||||
The Browser remains the room, route, and signaling authority.
|
||||
|
||||
@@ -129,7 +129,7 @@ Before native product consideration, one current-wire candidate must prove:
|
||||
and
|
||||
8. project, dependency, H.264 patent, and distribution license decisions.
|
||||
|
||||
No native experiment may preserve an obsolete Screener wire, create another
|
||||
No native experiment may preserve an obsolete Piik wire, create another
|
||||
room/topology model, loosen endpoint capacity, or become production merely to
|
||||
make a diagnostic gate pass.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ alongside an identical `high` encoding.
|
||||
|
||||
## Two Workstreams
|
||||
|
||||
- Self-contained Screener Server: library-level STUN/media components inside the
|
||||
- Self-contained Piik Server: library-level STUN/media components inside the
|
||||
executable, not bundled external service processes or an automatic installer.
|
||||
- Adaptive reuse: local derivation, shared lower outputs, independent child
|
||||
delivery and quality recovery, usable by Native Client and the server.
|
||||
@@ -74,7 +74,7 @@ not inferred from the words "automatic" or "simulcast":
|
||||
counting. Do not claim every unused individual lower layer is always stopped.
|
||||
- A higher quality request is not subject to downgrade-only debounce. Reduced
|
||||
maximum demand is debounced; the pinned server default is five seconds. This
|
||||
is an upstream implementation fact, not a proposed Screener timing constant.
|
||||
is an upstream implementation fact, not a proposed Piik timing constant.
|
||||
Publisher deactivation debounce is not a five-second delay before reducing
|
||||
traffic to a congested subscriber.
|
||||
- The SDK applies the selected active flags through `RTCRtpSender.setParameters`
|
||||
@@ -137,7 +137,7 @@ retire their resources immediately; warm retention cannot revive a retired sourc
|
||||
| Component | Useful capability | Boundary |
|
||||
| --- | --- | --- |
|
||||
| Existing `mediaedge.Source` and Pion RTP/WebRTC/interceptors | Encoded fanout, per-edge transport and feedback | No decoder/transcoder or shared-variant policy is supplied automatically |
|
||||
| Existing Native encoders and generation/keyframe ownership | Platform encode paths already integrated with Screener | Received-source decode/scale and shared derived outputs still need design |
|
||||
| Existing Native encoders and generation/keyframe ownership | Platform encode paths already integrated with Piik | Received-source decode/scale and shared derived outputs still need design |
|
||||
| LiveKit Dynacast, layer selector and prober sources | Reference for demand aggregation, safe switching and recovery probes | Apache-2.0 code; inspect imports/ownership before any extraction, not whole-service embedding |
|
||||
| libvpx multi-resolution VP8 API/example | Multiple spatial encodes through one coordinated API; libvpx is already used | VP8-specific; no promise that H264 hardware sessions have the same cost curve |
|
||||
| OpenH264 AVC simulcast API | Library H264 encode/decode and per-spatial-layer configuration | Software codec; inspect realtime cost and actual source/binary distribution terms before selection |
|
||||
|
||||
@@ -93,7 +93,7 @@ all layers are distinct costs.
|
||||
each transport still owns its packet headers and recovery.
|
||||
5. Reduced demand stops unused upper outputs through the framework's normal
|
||||
deactivation semantics. Any debounce belongs to that owner, not another
|
||||
Screener timer beside it. No application-selected timer values in this draft.
|
||||
Piik timer beside it. No application-selected timer values in this draft.
|
||||
6. Source replacement/failure/stop invalidates the same generation. No dormant
|
||||
warm pool survives and no old callback can resurrect an encoder.
|
||||
|
||||
@@ -127,8 +127,8 @@ an explicitly controlled input-frame boundary is required. In particular,
|
||||
|
||||
| Existing module / primary source | Reuse or learn | Integration limit |
|
||||
| --- | --- | --- |
|
||||
| Screener `mediaedge.Source`, `Edge`, Native capture generations | Encoded-source ownership, Pion connections, existing share/route identity | Static RTP broadcast alone does not solve switching sequence spaces or codec descriptors |
|
||||
| [Pion GCC](https://github.com/pion/interceptor/blob/main/pkg/gcc/send_side_bwe.go) and RTP/RTCP interceptors | Existing mature feedback and bandwidth estimate | Current Screener path only observes GCC and uses a no-queue pacer; selection/pacing is not already implemented |
|
||||
| Piik `mediaedge.Source`, `Edge`, Native capture generations | Encoded-source ownership, Pion connections, existing share/route identity | Static RTP broadcast alone does not solve switching sequence spaces or codec descriptors |
|
||||
| [Pion GCC](https://github.com/pion/interceptor/blob/main/pkg/gcc/send_side_bwe.go) and RTP/RTCP interceptors | Existing mature feedback and bandwidth estimate | Current Piik path only observes GCC and uses a no-queue pacer; selection/pacing is not already implemented |
|
||||
| [LiveKit Dynacast manager](https://github.com/livekit/livekit/blob/v1.13.6/pkg/rtc/dynacast/dynacastmanagervideo.go) | Highest-needed activation and asymmetric demand handling | Apache-2.0; reference, not import the entire service or its downstream-node aggregation |
|
||||
| [LiveKit Simulcast selector](https://github.com/livekit/livekit/blob/v1.13.6/pkg/sfu/videolayerselector/simulcast.go), [RTPMunger](https://github.com/livekit/livekit/blob/v1.13.6/pkg/sfu/rtpmunger.go), [prober](https://github.com/livekit/livekit/blob/v1.13.6/pkg/sfu/ccutils/prober.go) | Keyframe switching, packet continuity, bounded recovery probes | Valuable source, but imports protocol/buffer/logger infrastructure; not a demonstrated tiny drop-in |
|
||||
| [libwebrtc VP8 adapter](https://github.com/webrtc-mirror/webrtc/blob/main/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc) | Coordinated libvpx encoding, SetRates, active-stream keyframes, prepared scale buffers, separate codec and media timestamps | BSD-style; references many WebRTC types. Reuse the underlying libvpx API before copying a large wrapper |
|
||||
@@ -141,7 +141,7 @@ or a proved adaptation replacement. Its inspected layer sender is coupled to
|
||||
Client, track, bitrate-controller and packet-map owners; don't copy it as an
|
||||
independent universal selector. No new dependency or upstream implementation
|
||||
source was copied in this design pass. Preserve upstream licenses/notices when
|
||||
an actual module is chosen; Screener's MIT does not replace them.
|
||||
an actual module is chosen; Piik's MIT does not replace them.
|
||||
|
||||
Parallel inLive API inspection found work to validate before selecting it:
|
||||
publisher-demand change notification is not public; `AddRelayTrack` installs a
|
||||
@@ -149,7 +149,7 @@ no-op PLI callback; the layer sender has its own packet mapping rather than a
|
||||
standalone codec-neutral switch API. Its inspected timestamp expression subtracts
|
||||
the layer origin twice. Manager room removal/locking, failed-PC closing and
|
||||
logger injection also need focused reproductions. These are candidate-library
|
||||
risks, not claims about deployed Screener bugs or reasons to expand the Native
|
||||
risks, not claims about deployed Piik bugs or reasons to expand the Native
|
||||
module into an SFU fork.
|
||||
|
||||
## Required Before Production
|
||||
@@ -354,7 +354,7 @@ compare the selected complete media adapter against the same release trace.
|
||||
Run the probe explicitly from the repository root, optionally with
|
||||
`-frame-bursts`; it writes only ignored `build/embedded-media` diagnostics. It is
|
||||
not a default unit/CI task. The observed cadence sensitivity is a reason to test
|
||||
the real packet path, not to introduce a Screener congestion score.
|
||||
the real packet path, not to introduce a Piik congestion score.
|
||||
|
||||
### Embedded Service Composition
|
||||
|
||||
@@ -372,7 +372,7 @@ the existing Close/End owner retires STUN too. No service supervisor or second
|
||||
availability flag is needed. Deployment removes coturn in the final coordinated
|
||||
cutover, not while the media implementation is still under acceptance.
|
||||
|
||||
The implementation candidate uses a thin Screener SFU with LiveKit **media-core
|
||||
The implementation candidate uses a thin Piik SFU with LiveKit **media-core
|
||||
components**, without its RTC room or service. A stock-Pion compile and actual
|
||||
ReceiverBase/DownTrack projection pass; two receiving PCs also demonstrate an
|
||||
unaffected high-output sibling and high/low/high allocation under forced budgets.
|
||||
@@ -463,8 +463,8 @@ and the existing pinned libvpx build, using the same MSVC flags as the earlier
|
||||
CPU probe. Generate its JSONL under `build/embedded-media`, then run:
|
||||
|
||||
```powershell
|
||||
$env:SCREENER_ENCODED_FIXTURE = 'build/embedded-media/encoded-group.fixture.jsonl'
|
||||
$env:SCREENER_ENCODED_OUTPUT = 'build/embedded-media/encoded-group.received.json'
|
||||
$env:PIIK_ENCODED_FIXTURE = 'build/embedded-media/encoded-group.fixture.jsonl'
|
||||
$env:PIIK_ENCODED_OUTPUT = 'build/embedded-media/encoded-group.received.json'
|
||||
& .\build\embedded-media\mediaedge.test.exe '-test.run=TestEncodedGroupVP8Fixture' '-test.v' '-test.timeout=30s'
|
||||
node scripts/encoded-group-decode.mjs
|
||||
```
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# Piik rename
|
||||
|
||||
Status: accepted rename and coordinated cutover plan.
|
||||
Last reviewed: 2026-09-10.
|
||||
|
||||
## Accepted identity
|
||||
|
||||
Display `Piik`; use `piik` for executable, package, environment and service
|
||||
identifiers. GitHub is `TNTcraftHIM/Piik`; the Go module follows that exact case.
|
||||
The native macOS bundle identifier is `tv.piik.client`.
|
||||
The product keeps its TV mascot. The wordmark and morph animation remain in the
|
||||
[brand study](../design/piik-brand.html) for the future public website.
|
||||
|
||||
This is a private pre-release rename. It changes names and deployment identity,
|
||||
not media policy, routing, capture behavior or SQLite room semantics.
|
||||
|
||||
## Recovery and local metadata
|
||||
|
||||
The external `Piik-recovery/rename-20260910` directory contains a verified
|
||||
`repository.bundle` and a complete `git-metadata` copy. The latter preserves
|
||||
reflogs and all ten stash entries, which a bundle of ordinary refs alone does
|
||||
not capture. Earlier recovery bundles also remain outside the repository.
|
||||
Backups keep their original names and contents so they remain identifiable.
|
||||
|
||||
The main directory is `Piik`; preparation worktrees are `Piik-appearance` and
|
||||
`Piik-rename`, with `Piik-external-audit` retained separately. Their private Git
|
||||
registration names, backlinks and shared remote are updated. The hook path is
|
||||
relative `.githooks`. Retire integrated preparation worktrees after cutover.
|
||||
The audit worktree's branch and source revision remain untouched. Integration
|
||||
keeps one complete phase commit on main.
|
||||
|
||||
On Windows, a terminal can hold the repository directory open. Move the entries
|
||||
into an empty verified destination and run `git worktree repair` from the new
|
||||
main directory. Do not terminate the user's terminal to release a path.
|
||||
Existing firewall rules name executable paths, so moved build binaries require
|
||||
their corresponding path rules to be reviewed before network acceptance.
|
||||
|
||||
## Runtime and data boundary
|
||||
|
||||
`piik-v23` and `piik-client-v9` are new exact protocol labels. Their message
|
||||
schemas retain versions 23 and 9; the full label, not only its numeric suffix,
|
||||
is checked. Native capture remains v7. Release Web, Server, Client and capture
|
||||
artifacts together; old pages and installed Clients cannot interoperate across
|
||||
the renamed control boundary. No alternate protocol reader is introduced.
|
||||
|
||||
SQLite schema 2, its application ID, room codes, token/grant digests and password
|
||||
material remain unchanged. The four-byte database file identity is a format
|
||||
constant, not display branding. Copy the database only while the old process is
|
||||
stopped, verify integrity and retained columns, and preserve the original for
|
||||
rollback. Do not recreate rooms or repeat the earlier schema-1 cutover.
|
||||
|
||||
The implementation renames Browser storage prefixes, the site-access cookie
|
||||
and the Client configuration/cache directory. The owner accepts a clean break:
|
||||
copy directly compatible, accessible settings once during cutover; discard
|
||||
unavailable or incompatible settings. The product reads only Piik names, with
|
||||
no migration code, alternate reader or old-name alias.
|
||||
|
||||
The local Client configuration is unchanged JSON version 1 and can be copied
|
||||
byte-for-byte into the Piik directory without replacing an existing new config.
|
||||
Browser credentials and settings are origin/session-owned. Transfer them only
|
||||
through an available original Browser session; do not modify a live Browser's
|
||||
storage database or introduce a product bridge to recover them. Otherwise the
|
||||
new namespace starts empty, requiring login, room creation and preference setup.
|
||||
Old room authority remains in SQLite, but an unavailable Host credential cannot
|
||||
be reconstructed from its stored digest. Site-access cookies and remembered
|
||||
Client activation are renewed normally under the new contract.
|
||||
|
||||
## Git history
|
||||
|
||||
The owner authorized replacing the old name in Git history. Use the maintained
|
||||
`git-filter-repo` tool in a fresh, separate bare clone, never in the working
|
||||
repository. Scope this to commit/tag **messages**: historical source snapshots,
|
||||
authorship, dates and topology remain factual. Current tracked prose and code
|
||||
use the accepted identity; old snapshots remain recoverable at their mapped
|
||||
commits and in the original archive.
|
||||
|
||||
The initial inventory found two matching commit bodies and no matching commit
|
||||
subjects or tag names. A small text change still changes descendant SHAs and
|
||||
invalidates their commit signatures. Preserve `commit-map` and `ref-map`; verify
|
||||
equal commit counts, identical source trees, mapped parents, authors and dates,
|
||||
no dropped commits and a clean repository integrity check. No replacement refs,
|
||||
duplicate compatibility branches or history-rewriting tool enter the product.
|
||||
|
||||
The rehearsal verified all 546 reachable branch/tag commits: exactly two messages
|
||||
changed, all file trees and mapped parent relationships match, and authors/dates
|
||||
are preserved. Standard filtering rewrote 545 IDs and removed 374 signatures.
|
||||
Those signatures remain verifiable only in the original archive; a rewritten
|
||||
commit must not be presented as preserving its earlier GitHub verification.
|
||||
|
||||
Apply a reviewed message rewrite only with the coordinated brand integration,
|
||||
using explicit ref targets and old-SHA leases. Do not use `push --mirror` from
|
||||
the rehearsal: it could overwrite unrelated refs. Preserve the external audit
|
||||
branch and stash history in the original repository. Old audit/deployment SHAs
|
||||
remain evidence identifiers, interpreted through the archive and commit map.
|
||||
|
||||
## Operational cutover
|
||||
|
||||
The following old identifiers are retained here only as operator recovery
|
||||
inputs, not as runtime aliases:
|
||||
|
||||
| Surface | Before | After |
|
||||
| --- | --- | --- |
|
||||
| Service, user and group | `screener` | `piik` |
|
||||
| Installation root | `/opt/screener` | `/opt/piik` |
|
||||
| Environment file | `/etc/screener/screener.env` | `/etc/piik/piik.env` |
|
||||
| Branded environment prefix | `SCREENER_` | `PIIK_` |
|
||||
| Browser storage prefix | `screener:` | `piik:` |
|
||||
| Client config directory | `Screener` | `Piik` |
|
||||
|
||||
Prepare the new immutable artifacts, service/environment/proxy configuration,
|
||||
permissions and database path before stopping the old service. Record original
|
||||
configuration and ownership for recovery. Do not run two room authorities on
|
||||
the same database or two media services on the same UDP ports.
|
||||
|
||||
The routine `deploy/release-app.sh` assumes an existing **Piik** installation.
|
||||
It is not the first brand migration tool: its old-release checks and recovery
|
||||
target the Piik service/binary. Perform the first name cutover as one explicit
|
||||
infrastructure operation, then use the ordinary wrapper for future releases.
|
||||
On failure, stop the candidate and restore the old binary, service, environment,
|
||||
proxy and data together before reopening ingress.
|
||||
|
||||
GitHub is already renamed and the remote works. There are no published releases
|
||||
or Pages site to migrate. Keep repository visibility private; `piik.tv` DNS and
|
||||
Pages publication remain a separate website task. Old GitHub deployment/PR
|
||||
records describe earlier operations and are not rewritten as new releases.
|
||||
|
||||
## Validation and references
|
||||
|
||||
Acceptance covers the tracked-name inventory, Web type/build checks, relevant
|
||||
contract/storage tests, native compilation, Client/Server packaging and a
|
||||
controlled local launch. Production release additionally requires the accepted
|
||||
best-effort settings transfer, configuration/database recovery and postflight.
|
||||
|
||||
Primary references, checked 2026-09-10:
|
||||
|
||||
- [Git worktree repair](https://git-scm.com/docs/git-worktree): repair both
|
||||
directions after moving the main repository or linked worktrees.
|
||||
- [git-filter-repo](https://github.com/newren/git-filter-repo/blob/main/Documentation/git-filter-repo.txt):
|
||||
message replacement, fresh clones and old/new commit maps.
|
||||
- [GitHub repository rename](https://docs.github.com/en/repositories/creating-and-managing-repositories/renaming-a-repository):
|
||||
ordinary URL redirects do not cover repository-hosted Actions or project Pages.
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
Last reviewed: 2026-08-31
|
||||
|
||||
This document owns evidence for showing a live Screener session on an AirPlay,
|
||||
This document owns evidence for showing a live Piik session on an AirPlay,
|
||||
Cast, or Presentation API display. It does not add a product output surface.
|
||||
|
||||
## Current Decision
|
||||
|
||||
Do not add an application Cast or AirPlay button yet. Browser or operating-system
|
||||
tab/screen mirroring is already usable without Screener integration. The Web
|
||||
tab/screen mirroring is already usable without Piik integration. The Web
|
||||
platform does not give the current `video.srcObject = MediaStream` a portable
|
||||
remote-playback contract.
|
||||
|
||||
The only application design worth a physical prototype is a custom Cast
|
||||
receiver acting as another authenticated Screener Viewer. It would receive its
|
||||
receiver acting as another authenticated Piik Viewer. It would receive its
|
||||
own WebRTC route and count toward room and endpoint capacity; it would not reuse
|
||||
or fling the controlling Browser's decoded video element.
|
||||
|
||||
@@ -24,7 +24,7 @@ or fling the controlling Browser's decoded video element.
|
||||
Browser and operating-system UI can mirror a tab, window, screen, or media
|
||||
element. The W3C Remote Playback model explicitly permits this implementation
|
||||
shape but does not standardize its transport, latency, quality, lifecycle, or
|
||||
device coverage. Screener needs no adapter for it and cannot claim its result.
|
||||
device coverage. Piik needs no adapter for it and cannot claim its result.
|
||||
|
||||
### Media Remoting Or Flinging
|
||||
|
||||
@@ -55,12 +55,12 @@ application with custom messaging.
|
||||
|
||||
That makes a narrow architecture possible: launch a receiver page, deliver a
|
||||
short-lived room-scoped Viewer grant over the established control channel, and
|
||||
let that page join through the normal Screener Viewer and routing contracts. The
|
||||
let that page join through the normal Piik Viewer and routing contracts. The
|
||||
grant must not appear in the presentation URL, logs, storage, or device metadata.
|
||||
|
||||
This is not accepted product behavior. Google's documented media matrix does
|
||||
not promise WebRTC in a Custom Web Receiver, the Presentation API is not a
|
||||
cross-Browser surface, and no target receiver has proved Screener's codec,
|
||||
cross-Browser surface, and no target receiver has proved Piik's codec,
|
||||
autoplay, audio, network, or lifecycle requirements.
|
||||
|
||||
## Physical Acceptance Gate
|
||||
|
||||
@@ -230,7 +230,7 @@ default screen-share publication can expose original and lower representations,
|
||||
and server BWE can forward a lower representation to a constrained subscriber
|
||||
while another receives the highest available representation.
|
||||
|
||||
Calling the pinned client's own encoding calculator with Screener's exact
|
||||
Calling the pinned client's own encoding calculator with Piik's exact
|
||||
publish options produces two VP8 encodings for every accepted profile:
|
||||
|
||||
| Profile | Lower representation | Original representation |
|
||||
@@ -239,7 +239,7 @@ publish options produces two VP8 encodings for every accepted profile:
|
||||
| 1080p30 | 1/2 scale, 1.25 Mbps, 30 fps | 5 Mbps, 30 fps |
|
||||
| 1080p60 | 1/2 scale, 2 Mbps, 60 fps | 8 Mbps, 60 fps |
|
||||
|
||||
Both encodings start without an explicit RTP `priority` because Screener's
|
||||
Both encodings start without an explicit RTP `priority` because Piik's
|
||||
custom `screenShareEncoding` replaces LiveKit's priority-bearing preset while
|
||||
retaining its default `simulcast: true`. The audio encoding is `high` priority.
|
||||
Priority can only redistribute bandwidth within that PeerConnection and request
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
## Current Ownership
|
||||
|
||||
`cmd/screener-server` (Hosted) and `cmd/screener-client` (Client) compose the
|
||||
`cmd/piik-server` (Hosted) and `cmd/piik-client` (Client) compose the
|
||||
same application from `internal/server` and own only their defaults,
|
||||
reachability, and lifecycle policy. Within that scope `protocol` owns wire types,
|
||||
strict decoding, and shared scalars; `config` owns environment validation plus
|
||||
@@ -46,8 +46,8 @@ share one route authority and LiveKit remains an optional fallback of that graph
|
||||
|
||||
```text
|
||||
one Go module
|
||||
cmd/screener-server -> shared server application
|
||||
cmd/screener-client -> shared server application + launcher + native media
|
||||
cmd/piik-server -> shared server application
|
||||
cmd/piik-client -> shared server application + launcher + native media
|
||||
internal/server -> rooms, routing, HTTP/signaling, persistence, SFU adapters
|
||||
internal/client -> current native and platform boundaries
|
||||
one React/Vite static artifact -> embedded in both binaries
|
||||
@@ -106,7 +106,7 @@ origin, site-access password, one STUN URL, loopback listen host), polled
|
||||
`/healthz` every 10 ms until `{"status":"ok"}`, waited 5 s idle, sampled
|
||||
resident memory through PowerShell `WorkingSet64`, then killed the process.
|
||||
Five runs per side; the median is reported. Before is the Node baseline at tag
|
||||
`baseline-b20fd88`; after is `screener-server` under the same script.
|
||||
`baseline-b20fd88`; after is `piik-server` under the same script.
|
||||
|
||||
| metric | before | after |
|
||||
| --- | ---: | ---: |
|
||||
@@ -117,9 +117,9 @@ Five runs per side; the median is reported. Before is the Node baseline at tag
|
||||
The before total is the Node runtime (91,694,408 B), the production
|
||||
`node_modules` tree (12,640,469 B in 1,513 files), `dist/client` (1,492,721 B)
|
||||
and `dist/server` (856,898 B). The after total is the linux/amd64
|
||||
`screener-server` built with `-s -w` and embedded assets (13,983,906 B) plus its
|
||||
`piik-server` built with `-s -w` and embedded assets (13,983,906 B) plus its
|
||||
notices and `REVISION`. For reference, the windows/amd64 binaries are
|
||||
14,276,608 B (`screener-server`) and 22,703,104 B (`screener-client`, which also
|
||||
14,276,608 B (`piik-server`) and 22,703,104 B (`piik-client`, which also
|
||||
carries Pion and the terminal UI); the Client package additionally drops the
|
||||
Node runtime and dependency tree it used to ship beside its Go executable.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ The installed Chrome is 152.0.7977.82. Its [DEPS][chromium-deps] pins libwebrtc
|
||||
to `6f37672d358475cd17544121a12494da454d85fb`; WebRTC references below use that
|
||||
revision, not a floating upstream branch. Source shows available mechanisms,
|
||||
not which field trials or hardware encoder a particular runtime selected.
|
||||
The Screener comparison uses the `3c192ddd` candidate, not production.
|
||||
The Piik comparison uses the `3c192ddd` candidate, not production.
|
||||
|
||||
## Actual Control Ownership
|
||||
|
||||
@@ -45,7 +45,7 @@ These are connected but different owners:
|
||||
|
||||
For example, the adapter can request at most 3/5 of the current pixel count or
|
||||
reduce FPS to 2/3 under the corresponding preference. These are upstream rules,
|
||||
not proposed Screener constants. The default [encoder minimum][encoder-api] is
|
||||
not proposed Piik constants. The default [encoder minimum][encoder-api] is
|
||||
320x180 pixels and can be overridden; no universal 108p floor is established.
|
||||
VP8's [libvpx adapter][vp8] disables libvpx internal resizing because WebRTC owns
|
||||
that work outside the codec. Turning on libvpx resizing alone does not restore
|
||||
@@ -53,7 +53,7 @@ the omitted control chain.
|
||||
|
||||
### Motion And Simulcast Are Not Synonyms
|
||||
|
||||
Screener's `motion` hint becomes `kFluid` in the [Chromium sink][chromium-hint].
|
||||
Piik's `motion` hint becomes `kFluid` in the [Chromium sink][chromium-hint].
|
||||
[VideoRtpSender][sender-hint] then sets `is_screencast=false`; this follows the
|
||||
realtime-video path even for display capture. Explicit degradation preference
|
||||
still has precedence over the hint's default. Do not assume all display capture
|
||||
@@ -584,7 +584,7 @@ software encoder. VSE invokes `OnEncodeStarted` on its encoder queue just
|
||||
before the codec call; raw arrival and `OnDiscardedFrame` do not supply CPU
|
||||
samples. Replaying dropped inputs as encoded work would misrepresent feedback.
|
||||
|
||||
Screener's synchronous drain and latest-input mailbox reduce arrivals into VSE
|
||||
Piik's synchronous drain and latest-input mailbox reduce arrivals into VSE
|
||||
under this load, but the [same pinned VSE][vse] also skips queued frames before
|
||||
calling the CPU observer. Therefore moving admission or reporting source drops
|
||||
alone is not an established fix for multi-second encode gaps. Chromium's pinned
|
||||
|
||||
+12
-9
@@ -23,21 +23,24 @@ and Git/PRs own completed history.
|
||||
|
||||
## Deployment
|
||||
|
||||
The owner authorized integration, coordinated cutover and cleanup before the
|
||||
Piik appearance phase. Authorization is not deployment evidence: the immutable
|
||||
release descriptor, runtime `REVISION` and operator deployment record own the
|
||||
actual deployed identity and postflight result. The
|
||||
[schema cutover procedure](./deployment.md#permanent-room-schema-cutover) preserves
|
||||
existing room authority and Browser credential keys with a database/application
|
||||
rollback boundary.
|
||||
Source, package identity, GitHub repository and local worktree paths use Piik.
|
||||
The strict wire labels and stored keys move together at the coordinated
|
||||
[brand cutover](./research/piik-rename-plan.md). Directly compatible, accessible
|
||||
settings are transferred once; unavailable settings start fresh. Runtime code
|
||||
keeps only the Piik contract.
|
||||
The immutable release descriptor, runtime `REVISION` and operator deployment
|
||||
record own exact identity and postflight results. The
|
||||
[schema cutover](./deployment.md#permanent-room-schema-cutover) preserved existing
|
||||
room authority and Browser credential keys. Old active pages reload at the
|
||||
signaling v23 boundary.
|
||||
|
||||
The existing deployment uses one Go process for Web, room authority/signaling,
|
||||
Binding-only STUN on UDP 3478/3479/3480 and optional SFU on UDP 7882. nginx owns
|
||||
HTTPS; external LiveKit/coturn services remain disabled. Participants, routes and
|
||||
media remain process-only. This private service is not a public demonstration.
|
||||
|
||||
[TODO](./todo.md) owns closeout and subsequent appearance, renaming, distribution
|
||||
and ablation work. No public site or bulk rename belongs to this release.
|
||||
[TODO](./todo.md) owns rename acceptance, distribution and ablation work.
|
||||
The public website is a later phase.
|
||||
|
||||
## Media Evidence And Limits
|
||||
|
||||
|
||||
+9
-33
@@ -7,43 +7,19 @@ and Git/PRs own completed history. A parked idea is not implementation authority
|
||||
|
||||
## Now
|
||||
|
||||
Finish the owner-authorized PR386 squash, matched Web/Client/Server cutover and
|
||||
cleanup, then resume Piik appearance. Entry/Client lifecycle repairs, confirmed
|
||||
reconnect ownership fixes and the permanent-room/Hosted SQLite-default revision
|
||||
are implemented and verified. Product modules and
|
||||
[ADR-0002](./adr/0002-memory-resident-protected-rooms.md) own that accepted behavior.
|
||||
|
||||
Use the [coordinated cutover](./deployment.md#permanent-room-schema-cutover) to
|
||||
preserve existing SQLite authority and unchanged Browser credential keys; old
|
||||
active pages reload at the signaling v23 boundary. Runtime release metadata and
|
||||
the operator record own deployment completion. Do not recreate databases or
|
||||
add a replacement garbage collector. Later manual feedback is nonblocking.
|
||||
No further product implementation is queued for the accepted Piik rename.
|
||||
Its coordinated Web/Client/Server and Git-history cutover follows the
|
||||
[rename plan](./research/piik-rename-plan.md); the immutable release descriptor
|
||||
and deployment record own rollout identity. Preserve the original repository
|
||||
backup and external-audit worktree. Website work starts on owner direction.
|
||||
|
||||
## Next — Awaiting Owner Direction
|
||||
|
||||
1. Resume the [Piik brand study](./design/piik-brand.html) after the experience
|
||||
repairs. Keep round i dots; the tiny-e experiment was rejected. Try using the
|
||||
two outer stems as small headphones/earcups on the TV, retaining its familiar
|
||||
silhouette and the k diagonals as antennae. Display `Piik` and technical
|
||||
`piik` remain proposals. Settle identity before coordinated renaming or the
|
||||
public-site implementation.
|
||||
2. After the brand discussion, rename display copy, Go/npm source identity,
|
||||
Client/Server packages and OS icons, strict protocol/service identifiers,
|
||||
diagnostic redaction, configuration and deployment tooling in one coordinated
|
||||
phase. Inventory is complete. Browser storage contains room authority/grants
|
||||
and Client configuration contains a saved Site; decide preservation/reset
|
||||
explicitly before renaming their keys or directories. Preserve SQLite room
|
||||
authority when changing deployment paths. Use matching Web/Client/Server
|
||||
artifacts and one current reader/writer, without compatibility aliases.
|
||||
Keep third-party names/notices and historical evidence attribution accurate.
|
||||
|
||||
The owner owns **piik.tv**.
|
||||
Agree on casing, TV mascot/wordmark treatment, repository and runtime identifiers,
|
||||
release names and the GitHub Pages website before implementing the rename.
|
||||
Keep one current internal contract and remove replaced names in the coordinated
|
||||
change; no private compatibility aliases. Existing sketches are input, not an
|
||||
accepted identity. Do not configure DNS/Pages or publish the brand before that
|
||||
design discussion. The private production service is not a public demo.
|
||||
Design the GitHub Pages website around the accepted brand study. Keep one
|
||||
current internal contract; third-party names/notices remain accurate. DNS/Pages
|
||||
and public publication are separate from the repository rename. The private
|
||||
production service is not a public demo.
|
||||
|
||||
Include the owner-requested frontend/backend ablation review in that phase.
|
||||
Review duplicated behavior/state, module boundaries, interface clarity, lifecycle
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module github.com/TNTcraftHIM/Screener
|
||||
module github.com/TNTcraftHIM/Piik
|
||||
|
||||
go 1.26
|
||||
|
||||
|
||||
+2
-2
@@ -6,10 +6,10 @@
|
||||
<meta name="theme-color" content="#141e29" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#e9f2ee" media="(prefers-color-scheme: light)" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>Screener</title>
|
||||
<title>Piik</title>
|
||||
<script>
|
||||
try {
|
||||
var theme = localStorage.getItem("screener:ui-theme") ||
|
||||
var theme = localStorage.getItem("piik:ui-theme") ||
|
||||
(matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
||||
document.documentElement.dataset.theme = theme;
|
||||
} catch (e) {}
|
||||
|
||||
@@ -16,18 +16,18 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/browser"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/clientconfig"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/lan"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/launcher"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecontrol"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/publictunnel"
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
serverapp "github.com/TNTcraftHIM/Screener/internal/server/app"
|
||||
serverconfig "github.com/TNTcraftHIM/Screener/internal/server/config"
|
||||
"github.com/TNTcraftHIM/Screener/internal/server/webassets"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/browser"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/clientconfig"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/lan"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/launcher"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecontrol"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/publictunnel"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
serverapp "github.com/TNTcraftHIM/Piik/internal/server/app"
|
||||
serverconfig "github.com/TNTcraftHIM/Piik/internal/server/config"
|
||||
"github.com/TNTcraftHIM/Piik/internal/server/webassets"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -63,14 +63,14 @@ type Options struct {
|
||||
|
||||
func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
options.Debug = options.Debug || clientDebugEnabled(os.Getenv("SCREENER_DEBUG"))
|
||||
options.Debug = options.Debug || clientDebugEnabled(os.Getenv("PIIK_DEBUG"))
|
||||
options.console = newClientConsole(cancel, options.DisableBrowser)
|
||||
var recorder *diagnostics.Recorder
|
||||
var restoreLogger func()
|
||||
defer func() {
|
||||
cancel()
|
||||
if recorder != nil {
|
||||
slog.Debug("screener-client", "event", "stopped", "failed", returnedErr != nil, diagnostics.Error(returnedErr))
|
||||
slog.Debug("piik-client", "event", "stopped", "failed", returnedErr != nil, diagnostics.Error(returnedErr))
|
||||
if options.console.program == nil {
|
||||
path, err := recorder.Export()
|
||||
options.console.send(consoleExportResult{path: path, err: err})
|
||||
@@ -85,7 +85,7 @@ func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
var err error
|
||||
recorder, err = openClientDiagnostics(options.LogDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Screener Client diagnostics are unavailable: %w", err)
|
||||
return fmt.Errorf("Piik Client diagnostics are unavailable: %w", err)
|
||||
}
|
||||
previous, previousWriter, previousFlags := slog.Default(), log.Writer(), log.Flags()
|
||||
var dependencyLog *diagnostics.LineWriter
|
||||
@@ -102,7 +102,7 @@ func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
log.SetFlags(previousFlags)
|
||||
options.console.send(consoleDebug{logPath: recorder.LogPath(), export: recorder.Export})
|
||||
}
|
||||
slog.Debug("screener-client", "event", "start", "revision", BuildRevision)
|
||||
slog.Debug("piik-client", "event", "start", "revision", BuildRevision)
|
||||
options.console.show(consoleView{state: "starting"})
|
||||
if err := validateMode(options); err != nil {
|
||||
return err
|
||||
@@ -115,21 +115,21 @@ func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
var err error
|
||||
configPath, err = clientconfig.DefaultPath()
|
||||
if err != nil {
|
||||
return errors.New("Screener Client configuration is unavailable")
|
||||
return errors.New("Piik Client configuration is unavailable")
|
||||
}
|
||||
}
|
||||
config, err := clientconfig.LoadOrCreate(configPath)
|
||||
if err != nil {
|
||||
return errors.New("Screener Client configuration is unavailable")
|
||||
return errors.New("Piik Client configuration is unavailable")
|
||||
}
|
||||
config, err = applyMode(config, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slog.Debug("screener-client", "event", "configuration", "siteConfigured", config.Site != "", "localAccessProtected", config.LocalAccessPassword != "")
|
||||
slog.Debug("piik-client", "event", "configuration", "siteConfigured", config.Site != "", "localAccessProtected", config.LocalAccessPassword != "")
|
||||
if options.SiteSet || options.Local {
|
||||
if err = clientconfig.Save(configPath, config); err != nil {
|
||||
return errors.New("Screener Client configuration is unavailable")
|
||||
return errors.New("Piik Client configuration is unavailable")
|
||||
}
|
||||
}
|
||||
nativeMedia := discoverNativeMedia(ctx, options.CaptureProcess)
|
||||
@@ -139,7 +139,7 @@ func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
recorder.Context("capture", nativeMedia.capture)
|
||||
recorder.Binary("captureExecutable", nativeMedia.captureProcess)
|
||||
}
|
||||
slog.Debug("screener-client", "event", "native-capabilities",
|
||||
slog.Debug("piik-client", "event", "native-capabilities",
|
||||
"video", nativeMedia.capabilities.Video, "processAudio", nativeMedia.capabilities.ProcessAudio,
|
||||
"systemAudio", nativeMedia.capabilities.SystemAudio, "hardwareH264", nativeMedia.capabilities.HardwareH264,
|
||||
"softwareVP8", nativeMedia.capabilities.SoftwareVP8)
|
||||
@@ -150,10 +150,10 @@ func Run(ctx context.Context, options Options) (returnedErr error) {
|
||||
Presentation: options.console.setLanguage,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.New("Screener Client could not start")
|
||||
return errors.New("Piik Client could not start")
|
||||
}
|
||||
defer client.Close()
|
||||
slog.Debug("screener-client", "event", "control-ready")
|
||||
slog.Debug("piik-client", "event", "control-ready")
|
||||
if options.console.machine {
|
||||
if err = printEndpoint(client.Endpoint()); err != nil {
|
||||
return err
|
||||
@@ -209,7 +209,7 @@ func runLauncher(
|
||||
))
|
||||
options.console.show(consoleView{state: "setup", entry: launch.URL()})
|
||||
if err = browser.Open(launch.URL()); err != nil {
|
||||
return errors.New("Screener Client could not open its launcher")
|
||||
return errors.New("Piik Client could not open its launcher")
|
||||
}
|
||||
|
||||
var selection launcher.Selection
|
||||
@@ -219,7 +219,7 @@ func runLauncher(
|
||||
return nil
|
||||
case err = <-launch.Done():
|
||||
if err != nil {
|
||||
return errors.New("Screener Client launcher stopped unexpectedly")
|
||||
return errors.New("Piik Client launcher stopped unexpectedly")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -232,7 +232,7 @@ func runLauncher(
|
||||
if err = clientconfig.Save(configPath, config); err != nil {
|
||||
launch.SetResult("", err)
|
||||
<-launch.Handled()
|
||||
return errors.New("Screener Client configuration is unavailable")
|
||||
return errors.New("Piik Client configuration is unavailable")
|
||||
}
|
||||
client.SetAllowedOrigins(clientOrigins(config.Site, options.Port))
|
||||
options.SiteSet = false
|
||||
@@ -289,7 +289,7 @@ func applyMode(config clientconfig.Config, options Options) (clientconfig.Config
|
||||
var err error
|
||||
config.Site, err = clientconfig.NormalizeSite(options.Site)
|
||||
if err != nil || config.Site == "" {
|
||||
return clientconfig.Config{}, errors.New("Screener Site must be an HTTP or HTTPS origin")
|
||||
return clientconfig.Config{}, errors.New("Piik Site must be an HTTP or HTTPS origin")
|
||||
}
|
||||
} else if options.Local {
|
||||
config.Site = ""
|
||||
@@ -315,7 +315,7 @@ func clientDebugEnabled(value string) bool {
|
||||
|
||||
func openClientDiagnostics(directory string) (*diagnostics.Recorder, error) {
|
||||
if directory = strings.TrimSpace(directory); directory == "" {
|
||||
directory = strings.TrimSpace(os.Getenv("SCREENER_LOG_DIR"))
|
||||
directory = strings.TrimSpace(os.Getenv("PIIK_LOG_DIR"))
|
||||
}
|
||||
if directory != "" {
|
||||
return diagnostics.Open(directory, "client", BuildRevision)
|
||||
@@ -332,33 +332,33 @@ func openClientDiagnostics(directory string) (*diagnostics.Recorder, error) {
|
||||
if cacheErr != nil {
|
||||
return nil, errors.Join(err, cacheErr)
|
||||
}
|
||||
return diagnostics.Open(filepath.Join(cache, "Screener", "logs"), "client", BuildRevision)
|
||||
return diagnostics.Open(filepath.Join(cache, "Piik", "logs"), "client", BuildRevision)
|
||||
}
|
||||
|
||||
// runSite opens the configured Screener Site in the Browser and waits for the
|
||||
// runSite opens the configured Piik Site in the Browser and waits for the
|
||||
// loopback server, which is the only thing this mode owns. It takes no context:
|
||||
// cancellation reaches it through client.Done().
|
||||
func runSite(site string, options Options, client *loopback.Server) error {
|
||||
var err error
|
||||
slog.Debug("screener-client", "event", "mode", "mode", "site")
|
||||
slog.Debug("piik-client", "event", "mode", "mode", "site")
|
||||
launchURL := clientLaunchURL(site)
|
||||
view := consoleView{mode: "site", state: "starting", entry: launchURL}
|
||||
options.console.show(view)
|
||||
if options.console.machine {
|
||||
fmt.Printf("Screener Site: %s\n", site)
|
||||
fmt.Printf("Piik Site: %s\n", site)
|
||||
}
|
||||
if !options.DisableBrowser {
|
||||
if err = browser.Open(launchURL); err != nil {
|
||||
return errors.New("Screener Client could not open the Site")
|
||||
return errors.New("Piik Client could not open the Site")
|
||||
}
|
||||
} else if options.Ready != nil {
|
||||
options.Ready(launchURL)
|
||||
}
|
||||
view.state = "ready"
|
||||
slog.Debug("screener-client", "event", "site-ready")
|
||||
slog.Debug("piik-client", "event", "site-ready")
|
||||
options.console.show(view)
|
||||
if err = <-client.Done(); err != nil {
|
||||
return errors.New("Screener Client stopped unexpectedly")
|
||||
return errors.New("Piik Client stopped unexpectedly")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -370,7 +370,7 @@ func runLocal(ctx context.Context, options Options, config clientconfig.Config,
|
||||
if options.Link {
|
||||
view.mode = "link"
|
||||
}
|
||||
slog.Debug("screener-client", "event", "mode", "mode", view.mode)
|
||||
slog.Debug("piik-client", "event", "mode", "mode", view.mode)
|
||||
options.console.show(view)
|
||||
listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IPv4zero, Port: options.Port})
|
||||
if err != nil {
|
||||
@@ -402,7 +402,7 @@ func runLocal(ctx context.Context, options Options, config clientconfig.Config,
|
||||
}
|
||||
defer tunnel.Close()
|
||||
publicOrigin = tunnel.Origin()
|
||||
slog.Debug("screener-client", "event", "public-link-ready")
|
||||
slog.Debug("piik-client", "event", "public-link-ready")
|
||||
}
|
||||
|
||||
stunURLs, natPredictionStunURLs := localSTUNURLs(options.Link)
|
||||
@@ -436,7 +436,7 @@ func runLocal(ctx context.Context, options Options, config clientconfig.Config,
|
||||
if _, err = localServer.Listen(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
slog.Debug("screener-client", "event", "local-server-ready", "port", options.Port, "publicLink", publicOrigin != "")
|
||||
slog.Debug("piik-client", "event", "local-server-ready", "port", options.Port, "publicLink", publicOrigin != "")
|
||||
|
||||
// The readiness lines follow the listener, which the packaged smoke and the
|
||||
// public-link gate both read from stdout before they probe the port.
|
||||
@@ -458,7 +458,7 @@ func runLocal(ctx context.Context, options Options, config clientconfig.Config,
|
||||
)
|
||||
if !options.DisableBrowser {
|
||||
if err = browser.Open(launchURL); err != nil {
|
||||
return errors.New("Screener Client could not open the Local page")
|
||||
return errors.New("Piik Client could not open the Local page")
|
||||
}
|
||||
} else if options.Ready != nil {
|
||||
options.Ready(launchURL)
|
||||
@@ -478,7 +478,7 @@ func runLocal(ctx context.Context, options Options, config clientconfig.Config,
|
||||
return endLocalServer(localServer)
|
||||
case err = <-client.Done():
|
||||
if err != nil {
|
||||
return errors.New("Screener Client runtime stopped unexpectedly")
|
||||
return errors.New("Piik Client runtime stopped unexpectedly")
|
||||
}
|
||||
return nil
|
||||
case <-tunnelDone:
|
||||
@@ -495,7 +495,7 @@ func clientLaunchURL(raw string) string {
|
||||
if err != nil {
|
||||
return raw
|
||||
}
|
||||
fragment.Set("screener-client", "1")
|
||||
fragment.Set("piik-client", "1")
|
||||
parsed.Fragment = fragment.Encode()
|
||||
return parsed.String()
|
||||
}
|
||||
@@ -513,7 +513,7 @@ func clientLaunchURLWithLocalAccess(raw, password string) string {
|
||||
if password != "" {
|
||||
fragment.Set("client-access", password)
|
||||
}
|
||||
fragment.Set("screener-client", "1")
|
||||
fragment.Set("piik-client", "1")
|
||||
parsed.Fragment = fragment.Encode()
|
||||
return parsed.String()
|
||||
}
|
||||
@@ -604,7 +604,7 @@ func tunnelExecutable(configured string) string {
|
||||
func printEndpoint(endpoint loopback.Endpoint) error {
|
||||
payload, err := json.Marshal(endpoint)
|
||||
if err != nil {
|
||||
return errors.New("Screener Client endpoint is unavailable")
|
||||
return errors.New("Piik Client endpoint is unavailable")
|
||||
}
|
||||
fmt.Println(string(payload))
|
||||
return nil
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/clientconfig"
|
||||
serverconfig "github.com/TNTcraftHIM/Screener/internal/server/config"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/clientconfig"
|
||||
serverconfig "github.com/TNTcraftHIM/Piik/internal/server/config"
|
||||
)
|
||||
|
||||
func TestOccupiedPortRejectsLinkBeforeStartingATunnel(t *testing.T) {
|
||||
@@ -41,7 +41,7 @@ func TestClientLaunchURLMarksThePageWithoutChangingOrigin(t *testing.T) {
|
||||
t.Fatalf("launch URL = %q, %v", value, err)
|
||||
}
|
||||
fragment, err := url.ParseQuery(parsed.Fragment)
|
||||
if err != nil || fragment.Get("screener-client") != "1" {
|
||||
if err != nil || fragment.Get("piik-client") != "1" {
|
||||
t.Fatalf("Client launch fragment = %q, %v", parsed.Fragment, err)
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func TestClientDiagnosticsUseFilesOnlyWhenEnabled(t *testing.T) {
|
||||
log.SetOutput(previousOutput)
|
||||
slog.SetLogLoggerLevel(previousLevel)
|
||||
})
|
||||
t.Setenv("SCREENER_DEBUG", "")
|
||||
t.Setenv("PIIK_DEBUG", "")
|
||||
for _, enabled := range []bool{false, true} {
|
||||
output.Reset()
|
||||
directory := t.TempDir()
|
||||
@@ -72,7 +72,7 @@ func TestClientDiagnosticsUseFilesOnlyWhenEnabled(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("invalid mode must stop before starting capture or services")
|
||||
}
|
||||
if strings.Contains(output.String(), "screener-client") {
|
||||
if strings.Contains(output.String(), "piik-client") {
|
||||
t.Fatalf("Client diagnostics reached stderr: %s", output.String())
|
||||
}
|
||||
content, readErr := os.ReadFile(filepath.Join(directory, "client.log"))
|
||||
@@ -92,7 +92,7 @@ func TestClientDiagnosticsUseFilesOnlyWhenEnabled(t *testing.T) {
|
||||
|
||||
func TestClientDiagnosticDirectoryHonorsExplicitSelection(t *testing.T) {
|
||||
environmentDirectory := t.TempDir()
|
||||
t.Setenv("SCREENER_LOG_DIR", environmentDirectory)
|
||||
t.Setenv("PIIK_LOG_DIR", environmentDirectory)
|
||||
for _, directory := range []string{"", t.TempDir()} {
|
||||
recorder, err := openClientDiagnostics(directory)
|
||||
if err != nil {
|
||||
@@ -139,7 +139,7 @@ func TestLaunchURLPreservesLocalAccessInsideThePrivateFragment(t *testing.T) {
|
||||
}
|
||||
fragment, err := url.ParseQuery(parsed.Fragment)
|
||||
if err != nil || fragment.Get("client-access") != "secret" ||
|
||||
fragment.Get("screener-client") != "1" {
|
||||
fragment.Get("piik-client") != "1" {
|
||||
t.Fatalf("local native launch fragment = %q, %v", parsed.Fragment, err)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ func TestLaunchURLEncodesAndClearsOptionalLocalAccess(t *testing.T) {
|
||||
}
|
||||
fragment, err := url.ParseQuery(parsed.Fragment)
|
||||
if err != nil || fragment.Get("client-access") != "a+b&c?d=e" ||
|
||||
fragment.Get("screener-client") != "1" || fragment.Get("retained") != "yes" {
|
||||
fragment.Get("piik-client") != "1" || fragment.Get("retained") != "yes" {
|
||||
t.Fatalf("encoded local launch fragment = %q, %v", parsed.Fragment, err)
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestLaunchURLEncodesAndClearsOptionalLocalAccess(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fragment, err = url.ParseQuery(parsed.Fragment)
|
||||
if err != nil || fragment.Get("client-access") != "" || fragment.Get("screener-client") != "1" {
|
||||
if err != nil || fragment.Get("client-access") != "" || fragment.Get("piik-client") != "1" {
|
||||
t.Fatalf("open local launch fragment = %q, %v", parsed.Fragment, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"charm.land/lipgloss/v2"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/browser"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/browser"
|
||||
"github.com/charmbracelet/colorprofile"
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
"github.com/charmbracelet/x/term"
|
||||
@@ -72,7 +72,7 @@ var consoleCopy = map[string][3]string{
|
||||
"mode": {"Mode", "模式", ""},
|
||||
"local": {"Local network", "局域网", "□"},
|
||||
"link": {"Public link", "公网链接", "↗"},
|
||||
"site": {"Screener Site", "Screener 站点", "@"},
|
||||
"site": {"Piik Site", "Piik 站点", "@"},
|
||||
"setup": {"Choose a mode in the browser", "在浏览器中选择模式", "?"},
|
||||
"starting": {"Starting", "正在启动", "…"},
|
||||
"ready": {"Ready", "已就绪", "✓"},
|
||||
@@ -141,10 +141,10 @@ func (console *clientConsole) finish(err error) error {
|
||||
if console.program != nil {
|
||||
terminalErr := <-console.done
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Screener Client:", err)
|
||||
fmt.Fprintln(os.Stderr, "Piik Client:", err)
|
||||
}
|
||||
if terminalErr != nil {
|
||||
fmt.Fprintln(os.Stderr, "Screener Client:", terminalErr)
|
||||
fmt.Fprintln(os.Stderr, "Piik Client:", terminalErr)
|
||||
}
|
||||
return terminalErr
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func (model consoleModel) text(key string) string {
|
||||
|
||||
func (model consoleModel) View() tea.View {
|
||||
view := tea.NewView(model.content(true))
|
||||
view.WindowTitle = "Screener Client"
|
||||
view.WindowTitle = "Piik Client"
|
||||
view.AltScreen = true
|
||||
return view
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func (model consoleModel) content(styled bool) string {
|
||||
revision = revision[:7]
|
||||
}
|
||||
var out strings.Builder
|
||||
heading := "Screener\nClient\n" + muted.Render(revision)
|
||||
heading := "Piik\nClient\n" + muted.Render(revision)
|
||||
animated := styled && model.animating()
|
||||
mascot := accent.Render(consoleTV(model.frame, animated, compact || width < 34))
|
||||
if styled && model.colors && width >= 36 && !compactDebug {
|
||||
|
||||
@@ -166,11 +166,11 @@ func TestConsoleDiagnosticsFitCompactTerminal(t *testing.T) {
|
||||
model := consoleModel{
|
||||
view: consoleView{mode: "local", state: "ready", entry: "http://localhost:8787/"},
|
||||
width: 30, height: 18, colors: true,
|
||||
debug: consoleDebug{logPath: "C:/Screener/logs/client.log", export: func() (string, error) { return "", nil }},
|
||||
debug: consoleDebug{logPath: "C:/Piik/logs/client.log", export: func() (string, error) { return "", nil }},
|
||||
}
|
||||
for _, language := range []string{"en", "zh", "vis"} {
|
||||
model.language = language
|
||||
for _, path := range []string{"", "C:/Screener/logs/client-20260908T120000Z.zip", "C:/Users/Example/Documents/Workspaces/Screener-embedded-media/build/client-check/logs/client-diagnostics-20260908T120000Z-123456789.zip"} {
|
||||
for _, path := range []string{"", "C:/Piik/logs/client-20260908T120000Z.zip", "C:/Users/Example/Documents/Workspaces/Piik-embedded-media/build/client-check/logs/client-diagnostics-20260908T120000Z-123456789.zip"} {
|
||||
model.exportPath = path
|
||||
content := model.content(true)
|
||||
if lipgloss.Width(content) > model.width || lipgloss.Height(content) > model.height {
|
||||
|
||||
@@ -32,7 +32,7 @@ func DefaultPath() (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("find user configuration directory: %w", err)
|
||||
}
|
||||
return filepath.Join(directory, "Screener", "client.json"), nil
|
||||
return filepath.Join(directory, "Piik", "client.json"), nil
|
||||
}
|
||||
|
||||
func LoadOrCreate(path string) (Config, error) {
|
||||
@@ -99,7 +99,7 @@ func NormalizeSite(value string) (string, error) {
|
||||
parsed.Host == "" || parsed.User != nil ||
|
||||
(parsed.Path != "" && parsed.Path != "/") ||
|
||||
parsed.RawQuery != "" || parsed.Fragment != "" {
|
||||
return "", errors.New("Screener Site must be an HTTP or HTTPS origin")
|
||||
return "", errors.New("Piik Site must be an HTTP or HTTPS origin")
|
||||
}
|
||||
return parsed.Scheme + "://" + parsed.Host, nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/clientconfig"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/clientconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -255,7 +255,7 @@ func (server *Server) handleLaunch(response http.ResponseWriter, request *http.R
|
||||
server.mu.Unlock()
|
||||
if !resultSet || resultErr != nil {
|
||||
writeJSON(response, http.StatusServiceUnavailable, map[string]string{
|
||||
"error": "Screener Client could not start",
|
||||
"error": "Piik Client could not start",
|
||||
})
|
||||
server.markHandled()
|
||||
return
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestLauncherServesStateAndCompletesOneSelection(t *testing.T) {
|
||||
if selection != (Selection{Mode: ModeLink, Language: "vis"}) {
|
||||
t.Fatalf("selection = %+v", selection)
|
||||
}
|
||||
server.SetResult("http://localhost:8787/#screener-client=1", nil)
|
||||
server.SetResult("http://localhost:8787/#piik-client=1", nil)
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("launcher did not emit a selection")
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func TestLauncherServesStateAndCompletesOneSelection(t *testing.T) {
|
||||
Target string `json:"target"`
|
||||
}
|
||||
if response.StatusCode != http.StatusOK || json.NewDecoder(response.Body).Decode(&launch) != nil ||
|
||||
launch.Target != "http://localhost:8787/#screener-client=1" {
|
||||
launch.Target != "http://localhost:8787/#piik-client=1" {
|
||||
t.Fatalf("launcher result = %d, %+v", response.StatusCode, launch)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
@@ -135,7 +135,7 @@ func TestLauncherCarriesAndNormalizesAnOptionalLocalPassword(t *testing.T) {
|
||||
if selection.Mode != ModeLocal || selection.Language != "zh" || selection.LocalAccessPassword != "new-local-pass" {
|
||||
t.Fatalf("selection = %+v", selection)
|
||||
}
|
||||
server.SetResult("http://localhost:8787/#screener-client=1", nil)
|
||||
server.SetResult("http://localhost:8787/#piik-client=1", nil)
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("launcher did not emit a selection")
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
const (
|
||||
ProtocolVersion = 9
|
||||
ServiceName = "screener-client"
|
||||
ControlSubprotocol = "screener-client-v9"
|
||||
ServiceName = "piik-client"
|
||||
ControlSubprotocol = "piik-client-v9"
|
||||
MaxControlMessageBytes = 256 << 10
|
||||
DefaultPortStart = 39721
|
||||
DefaultPortEnd = 39730
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativeaudio"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativeaudio"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media"
|
||||
@@ -59,7 +59,7 @@ func (engine *Engine) NewAudioSource(capacity, bitrate int) (*AudioSource, error
|
||||
track, err := webrtc.NewTrackLocalStaticSample(
|
||||
opusCapability,
|
||||
"audio",
|
||||
"screener-native",
|
||||
"piik-native",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -82,7 +82,7 @@ func (engine *Engine) NewRelayedAudioSource(capacity int) (*AudioSource, error)
|
||||
track, err := webrtc.NewTrackLocalStaticRTP(
|
||||
opusCapability,
|
||||
"audio",
|
||||
"screener-native",
|
||||
"piik-native",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
@@ -138,22 +138,22 @@ func (engine *Engine) NewEdge(source *Source, options EdgeOptions) (*Edge, error
|
||||
edge.localCandidates.addPion(candidate)
|
||||
})
|
||||
connection.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
|
||||
log.Debug("screener-client", "event", "media-ice-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
log.Debug("piik-client", "event", "media-ice-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
})
|
||||
if dtls := edge.sender.Transport(); dtls != nil {
|
||||
dtls.OnStateChange(func(state webrtc.DTLSTransportState) {
|
||||
log.Debug("screener-client", "event", "media-dtls-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
log.Debug("piik-client", "event", "media-dtls-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
})
|
||||
}
|
||||
connection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
|
||||
debug := slog.Default().Enabled(engine.ctx, slog.LevelDebug)
|
||||
if debug {
|
||||
log.Debug("screener-client", "event", "media-connection-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
log.Debug("piik-client", "event", "media-connection-state", "direction", "outbound", "local", options.Local, "state", state.String())
|
||||
}
|
||||
if state == webrtc.PeerConnectionStateConnected {
|
||||
if err := edge.transport.SetConnected(); err != nil {
|
||||
if debug {
|
||||
log.Debug("screener-client", "event", "media-activation-failed", diagnostics.Error(err))
|
||||
log.Debug("piik-client", "event", "media-activation-failed", diagnostics.Error(err))
|
||||
}
|
||||
_ = connection.Close()
|
||||
return
|
||||
@@ -165,7 +165,7 @@ func (engine *Engine) NewEdge(source *Source, options EdgeOptions) (*Edge, error
|
||||
if pair, pairErr := edge.SelectedPair(); pairErr == nil {
|
||||
selected = &pair
|
||||
if debug {
|
||||
log.Debug("screener-client", "event", "media-selected-path", "direction", "outbound", "local", options.Local,
|
||||
log.Debug("piik-client", "event", "media-selected-path", "direction", "outbound", "local", options.Local,
|
||||
"localType", pair.Local.String(), "remoteType", pair.Remote.String(), "natTraversalPath", pair.NatTraversalPath)
|
||||
}
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func logLocalMediaCandidateCounts(report webrtc.StatsReport) {
|
||||
tcp++
|
||||
}
|
||||
}
|
||||
slog.Debug("screener-client", "event", "media-candidate-counts", "local", true,
|
||||
slog.Debug("piik-client", "event", "media-candidate-counts", "local", true,
|
||||
"direction", string(direction), "type", kind.String(), "udp", udp, "tcp", tcp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativeaudio"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativeaudio"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/livekit/livekit-server/pkg/sfu/streamtracker"
|
||||
"github.com/pion/interceptor"
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/portmapping"
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/portmapping"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/rtcp"
|
||||
@@ -90,7 +90,7 @@ func NewEngine(options EngineOptions) (*Engine, error) {
|
||||
loggerFactory := diagnostics.PionLoggerFactory()
|
||||
ready := make(chan struct{})
|
||||
mux := ice.NewUniversalUDPMuxDefault(ice.UniversalUDPMuxParams{
|
||||
Logger: loggerFactory.NewLogger("screener-ice"),
|
||||
Logger: loggerFactory.NewLogger("piik-ice"),
|
||||
UDPConn: &initializingUDPConn{UDPConn: connection, ready: ready},
|
||||
})
|
||||
close(ready)
|
||||
@@ -288,7 +288,7 @@ func (engine *Engine) NewSource(codec string, capacity, layers int, requestKeyFr
|
||||
publications: make(map[*Publication]struct{}),
|
||||
}
|
||||
media, err := forwarding.NewEncodedSource(forwarding.SourceOptions{
|
||||
ID: "screen", StreamID: "screener-native", Codec: videoCodecs[codec],
|
||||
ID: "screen", StreamID: "piik-native", Codec: videoCodecs[codec],
|
||||
Formats: make([]forwarding.LayerFormat, layers), MaxPackets: encoded.MaxPacketWindow,
|
||||
OnRTCP: func(layer int, packets []rtcp.Packet) {
|
||||
for _, packet := range packets {
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
)
|
||||
|
||||
// Explicit codec gate input; ordinary unit checks do not build/run a native codec.
|
||||
func TestEncodedGroupVP8Fixture(t *testing.T) {
|
||||
inputPath := os.Getenv("SCREENER_ENCODED_FIXTURE")
|
||||
inputPath := os.Getenv("PIIK_ENCODED_FIXTURE")
|
||||
if inputPath == "" {
|
||||
t.Skip("set SCREENER_ENCODED_FIXTURE to the bounded VP8 fixture JSONL")
|
||||
t.Skip("set PIIK_ENCODED_FIXTURE to the bounded VP8 fixture JSONL")
|
||||
}
|
||||
input, err := os.Open(inputPath)
|
||||
if err != nil {
|
||||
@@ -228,7 +228,7 @@ func TestEncodedGroupVP8Fixture(t *testing.T) {
|
||||
t.Fatal("sender evidence counted unused-layer bytes")
|
||||
}
|
||||
}
|
||||
if outputPath := os.Getenv("SCREENER_ENCODED_OUTPUT"); outputPath != "" {
|
||||
if outputPath := os.Getenv("PIIK_ENCODED_OUTPUT"); outputPath != "" {
|
||||
data, err := json.Marshal(delivered)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/pion/rtcp"
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/webrtc/v4"
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
)
|
||||
|
||||
|
||||
@@ -99,14 +99,14 @@ func (engine *Engine) NewReceiver(options ReceiverOptions) (*Receiver, webrtc.Se
|
||||
connection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
|
||||
debug := slog.Default().Enabled(engine.ctx, slog.LevelDebug)
|
||||
if debug {
|
||||
slog.Debug("screener-client", "event", "media-connection-state", "direction", "inbound", "state", state.String())
|
||||
slog.Debug("piik-client", "event", "media-connection-state", "direction", "inbound", "state", state.String())
|
||||
}
|
||||
var selected *SelectedPair
|
||||
if state == webrtc.PeerConnectionStateConnected && (receiver.events.ConnectionState != nil || debug) {
|
||||
if pair, pairErr := receiver.SelectedPair(); pairErr == nil {
|
||||
selected = &pair
|
||||
if debug {
|
||||
slog.Debug("screener-client", "event", "media-selected-path", "direction", "inbound",
|
||||
slog.Debug("piik-client", "event", "media-selected-path", "direction", "inbound",
|
||||
"localType", pair.Local.String(), "remoteType", pair.Remote.String(), "natTraversalPath", pair.NatTraversalPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,17 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
// Replays actual SDK encoder output through independent Pion connections. The
|
||||
// relays retain derivation capability, but healthy children need only raw reuse.
|
||||
func TestRelayChainEncodedFixture(t *testing.T) {
|
||||
fixture := os.Getenv("SCREENER_POOL_CHAIN_FIXTURE")
|
||||
fixture := os.Getenv("PIIK_POOL_CHAIN_FIXTURE")
|
||||
if fixture == "" {
|
||||
t.Skip("set SCREENER_POOL_CHAIN_FIXTURE and SCREENER_NATIVE_CAPTURE")
|
||||
t.Skip("set PIIK_POOL_CHAIN_FIXTURE and PIIK_NATIVE_CAPTURE")
|
||||
}
|
||||
check := func(err error) {
|
||||
t.Helper()
|
||||
@@ -29,11 +29,11 @@ func TestRelayChainEncodedFixture(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
executable := os.Getenv("SCREENER_NATIVE_CAPTURE")
|
||||
executable := os.Getenv("PIIK_NATIVE_CAPTURE")
|
||||
info, err := os.Stat(executable)
|
||||
check(err)
|
||||
if info.IsDir() {
|
||||
t.Fatal("SCREENER_NATIVE_CAPTURE must name the existing capture executable")
|
||||
t.Fatal("PIIK_NATIVE_CAPTURE must name the existing capture executable")
|
||||
}
|
||||
input, err := os.Open(fixture)
|
||||
check(err)
|
||||
@@ -293,7 +293,7 @@ func TestRelayChainEncodedFixture(t *testing.T) {
|
||||
}{len(frames), 2, actual, false, true})
|
||||
check(err)
|
||||
t.Log(string(summary))
|
||||
if output := os.Getenv("SCREENER_POOL_CHAIN_OUTPUT"); output != "" {
|
||||
if output := os.Getenv("PIIK_POOL_CHAIN_OUTPUT"); output != "" {
|
||||
check(os.WriteFile(output, append(summary, '\n'), 0o600))
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
"github.com/livekit/mediatransportutil/pkg/utils"
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/livekit/mediatransportutil"
|
||||
mediacodec "github.com/livekit/mediatransportutil/pkg/codec"
|
||||
"github.com/pion/rtcp"
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
// Explicit small native-codec acceptance, never launched by the ordinary suite.
|
||||
// Forced layer demand tests derivation ownership, not network adaptation.
|
||||
func TestRelayDerivationFixture(t *testing.T) {
|
||||
executable, fixture := os.Getenv("SCREENER_NATIVE_CAPTURE"), os.Getenv("SCREENER_ENCODED_FIXTURE")
|
||||
executable, fixture := os.Getenv("PIIK_NATIVE_CAPTURE"), os.Getenv("PIIK_ENCODED_FIXTURE")
|
||||
if executable == "" || fixture == "" {
|
||||
t.Skip("set SCREENER_NATIVE_CAPTURE and SCREENER_ENCODED_FIXTURE for native relay acceptance")
|
||||
t.Skip("set PIIK_NATIVE_CAPTURE and PIIK_ENCODED_FIXTURE for native relay acceptance")
|
||||
}
|
||||
input, err := os.Open(fixture)
|
||||
if err != nil {
|
||||
@@ -291,9 +291,9 @@ func TestRelayDerivationFixture(t *testing.T) {
|
||||
// Forced direct-child budgets exercise real per-group WebRTC spatial adaptation;
|
||||
// they do not simulate transport loss or prove bandwidth-estimator behavior.
|
||||
func TestRelayIndependentSpatialFixture(t *testing.T) {
|
||||
executable, fixture := os.Getenv("SCREENER_NATIVE_CAPTURE"), os.Getenv("SCREENER_GROUP_MOTION_INPUT")
|
||||
executable, fixture := os.Getenv("PIIK_NATIVE_CAPTURE"), os.Getenv("PIIK_GROUP_MOTION_INPUT")
|
||||
if executable == "" || fixture == "" {
|
||||
t.Skip("set SCREENER_NATIVE_CAPTURE and SCREENER_GROUP_MOTION_INPUT")
|
||||
t.Skip("set PIIK_NATIVE_CAPTURE and PIIK_GROUP_MOTION_INPUT")
|
||||
}
|
||||
check := func(err error) {
|
||||
t.Helper()
|
||||
@@ -457,7 +457,7 @@ func TestRelayIndependentSpatialFixture(t *testing.T) {
|
||||
default:
|
||||
}
|
||||
}
|
||||
if path := os.Getenv("SCREENER_GROUP_OUTPUT"); path != "" {
|
||||
if path := os.Getenv("PIIK_GROUP_OUTPUT"); path != "" {
|
||||
file, err := os.Create(path)
|
||||
check(err)
|
||||
check(json.NewEncoder(file).Encode(output))
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
mediacodec "github.com/livekit/mediatransportutil/pkg/codec"
|
||||
"github.com/livekit/server-sdk-go/v2/pkg/samplebuilder"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/livekit/mediatransportutil"
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/pion/interceptor"
|
||||
@@ -26,8 +26,8 @@ import (
|
||||
// One real VP8 derived process, no desktop capture. The link changes capacity;
|
||||
// production BWE, output admission and codec controls supply every adaptation.
|
||||
func TestRelayNetworkVP8Fixture(t *testing.T) {
|
||||
if os.Getenv("SCREENER_RELAY_NETWORK") == "" {
|
||||
t.Skip("set SCREENER_RELAY_NETWORK=1, SCREENER_NATIVE_CAPTURE and SCREENER_ENCODED_FIXTURE")
|
||||
if os.Getenv("PIIK_RELAY_NETWORK") == "" {
|
||||
t.Skip("set PIIK_RELAY_NETWORK=1, PIIK_NATIVE_CAPTURE and PIIK_ENCODED_FIXTURE")
|
||||
}
|
||||
check := func(err error) {
|
||||
t.Helper()
|
||||
@@ -35,7 +35,7 @@ func TestRelayNetworkVP8Fixture(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
input, err := os.Open(os.Getenv("SCREENER_ENCODED_FIXTURE"))
|
||||
input, err := os.Open(os.Getenv("PIIK_ENCODED_FIXTURE"))
|
||||
check(err)
|
||||
defer input.Close()
|
||||
var motion [][]byte
|
||||
@@ -70,7 +70,7 @@ func TestRelayNetworkVP8Fixture(t *testing.T) {
|
||||
check(err)
|
||||
defer source.Close()
|
||||
source.relay = &relayDerivation{source: source, options: RelayOptions{
|
||||
CaptureProcess: os.Getenv("SCREENER_NATIVE_CAPTURE"),
|
||||
CaptureProcess: os.Getenv("PIIK_NATIVE_CAPTURE"),
|
||||
Capabilities: nativecapture.Capabilities{SoftwareVP8: true, Adapters: []nativecapture.Adapter{{Index: 0}}},
|
||||
}}
|
||||
check(source.SetRelayProfile(nativecapture.VideoProfile{Width: 1280, Height: 720,
|
||||
@@ -332,9 +332,9 @@ func TestRelayNetworkVP8Fixture(t *testing.T) {
|
||||
recovered = true
|
||||
}
|
||||
}
|
||||
outputPath := os.Getenv("SCREENER_ENCODED_OUTPUT")
|
||||
outputPath := os.Getenv("PIIK_ENCODED_OUTPUT")
|
||||
if outputPath == "" {
|
||||
t.Fatal("SCREENER_ENCODED_OUTPUT must name the ignored received-frame artifact")
|
||||
t.Fatal("PIIK_ENCODED_OUTPUT must name the ignored received-frame artifact")
|
||||
}
|
||||
data, err := json.Marshal(delivered)
|
||||
check(err)
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/forwarding"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/forwarding"
|
||||
mediacodec "github.com/livekit/mediatransportutil/pkg/codec"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/livekit/livekit-server/pkg/sfu/streamtracker"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
@@ -13,11 +13,11 @@ import (
|
||||
|
||||
// Opt-in real capture-process check; normal tests never start a codec or GPU.
|
||||
func TestAdaptiveOutputFixture(t *testing.T) {
|
||||
executable, fixture := os.Getenv("SCREENER_NATIVE_CAPTURE"), os.Getenv("SCREENER_ADAPTIVE_INPUT")
|
||||
executable, fixture := os.Getenv("PIIK_NATIVE_CAPTURE"), os.Getenv("PIIK_ADAPTIVE_INPUT")
|
||||
if executable == "" || fixture == "" {
|
||||
t.Skip("set SCREENER_NATIVE_CAPTURE and SCREENER_ADAPTIVE_INPUT")
|
||||
t.Skip("set PIIK_NATIVE_CAPTURE and PIIK_ADAPTIVE_INPUT")
|
||||
}
|
||||
codec := os.Getenv("SCREENER_ADAPTIVE_CODEC")
|
||||
codec := os.Getenv("PIIK_ADAPTIVE_CODEC")
|
||||
if codec == "" {
|
||||
codec = "vp8"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -103,7 +103,7 @@ func Discover(parent context.Context, executable string) (Capabilities, error) {
|
||||
command.Stderr = stderr
|
||||
hideWindow(command)
|
||||
if err := command.Run(); err != nil {
|
||||
slog.DebugContext(ctx, "screener-client", "event", "capture-probe-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
slog.DebugContext(ctx, "piik-client", "event", "capture-probe-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return Capabilities{}, errors.New("native capture probe timed out")
|
||||
}
|
||||
@@ -127,11 +127,11 @@ func PackagedExecutable() string {
|
||||
name := ""
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
name = "screener-client-capture.exe"
|
||||
name = "piik-client-capture.exe"
|
||||
case "darwin":
|
||||
name = "screener-client-capture"
|
||||
name = "piik-client-capture"
|
||||
case "linux":
|
||||
name = "screener-client-capture"
|
||||
name = "piik-client-capture"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/media/encoded"
|
||||
"github.com/TNTcraftHIM/Piik/internal/media/encoded"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -143,7 +143,7 @@ func ListSources(parent context.Context, executable string) ([]CaptureTarget, er
|
||||
command.Stderr = stderr
|
||||
hideWindow(command)
|
||||
if err := command.Run(); err != nil {
|
||||
slog.DebugContext(ctx, "screener-client", "event", "capture-source-list-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
slog.DebugContext(ctx, "piik-client", "event", "capture-source-list-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
return nil, errors.New("native capture source list is unavailable")
|
||||
}
|
||||
var targets []CaptureTarget
|
||||
@@ -178,7 +178,7 @@ func PreviewSource(parent context.Context, executable string, target CaptureTarg
|
||||
command.Stderr = stderr
|
||||
hideWindow(command)
|
||||
if err := command.Run(); err != nil {
|
||||
slog.DebugContext(ctx, "screener-client", "event", "capture-source-preview-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
slog.DebugContext(ctx, "piik-client", "event", "capture-source-preview-failed", diagnostics.Error(err), "canceled", ctx.Err() != nil)
|
||||
return nil, errors.New("native capture preview is unavailable")
|
||||
}
|
||||
preview := stdout.Bytes()
|
||||
@@ -198,7 +198,7 @@ func StartVideo(parent context.Context, executable string, options VideoOptions)
|
||||
}
|
||||
environment := []string(nil)
|
||||
if options.RestoreToken != "" {
|
||||
environment = []string{"SCREENER_XDP_RESTORE_TOKEN=" + options.RestoreToken}
|
||||
environment = []string{"PIIK_XDP_RESTORE_TOKEN=" + options.RestoreToken}
|
||||
}
|
||||
arguments := []string{
|
||||
"--capture-video",
|
||||
@@ -398,7 +398,7 @@ func startStreamWithEnvironment(
|
||||
logger := slog.Default().With("capture", captureID)
|
||||
command := exec.CommandContext(ctx, executable, arguments...)
|
||||
if logger.Enabled(ctx, slog.LevelDebug) {
|
||||
environment = append(environment, "SCREENER_CAPTURE_DEBUG=1")
|
||||
environment = append(environment, "PIIK_CAPTURE_DEBUG=1")
|
||||
}
|
||||
if len(environment) > 0 {
|
||||
command.Env = append(os.Environ(), environment...)
|
||||
@@ -420,7 +420,7 @@ func startStreamWithEnvironment(
|
||||
if err = command.Start(); err != nil {
|
||||
_ = trace.Close()
|
||||
cancel()
|
||||
logger.DebugContext(ctx, "screener-client", "event", "capture-process-start-failed", diagnostics.Error(err))
|
||||
logger.DebugContext(ctx, "piik-client", "event", "capture-process-start-failed", diagnostics.Error(err))
|
||||
return nil, fmt.Errorf("start native capture process: %w", err)
|
||||
}
|
||||
logger = logger.With("pid", command.Process.Pid)
|
||||
@@ -431,7 +431,7 @@ func startStreamWithEnvironment(
|
||||
mode = strings.TrimPrefix(arguments[0], "--")
|
||||
}
|
||||
}
|
||||
logger.DebugContext(ctx, "screener-client", "event", "capture-process-started", "mode", mode)
|
||||
logger.DebugContext(ctx, "piik-client", "event", "capture-process-started", "mode", mode)
|
||||
stream := &Stream{
|
||||
cancel: cancel,
|
||||
input: stdout,
|
||||
@@ -444,7 +444,7 @@ func startStreamWithEnvironment(
|
||||
waitErr := command.Wait()
|
||||
_ = trace.Close()
|
||||
logCaptureFailure(ctx, waitErr, command.ProcessState.ExitCode(), stderr.Bytes())
|
||||
logger.DebugContext(ctx, "screener-client", "event", "capture-process-ended", "mode", mode,
|
||||
logger.DebugContext(ctx, "piik-client", "event", "capture-process-ended", "mode", mode,
|
||||
"durationMs", time.Since(started).Milliseconds(), "exitCode", command.ProcessState.ExitCode(),
|
||||
"canceled", ctx.Err() != nil, "cancelReason", diagnostics.SafeText(fmt.Sprint(context.Cause(ctx))), diagnostics.Error(waitErr))
|
||||
stream.done <- waitErr
|
||||
@@ -473,7 +473,7 @@ func logCaptureFailure(ctx context.Context, err error, exitCode int, stderr []by
|
||||
if canceled && stage == "" && hresult == "" {
|
||||
return
|
||||
}
|
||||
slog.DebugContext(ctx, "screener-client", "event", "capture-process-failed",
|
||||
slog.DebugContext(ctx, "piik-client", "event", "capture-process-failed",
|
||||
"exitCode", exitCode, "stage", stage, "hresult", hresult, "canceled", canceled)
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ func (stream *Stream) Read() (Frame, error) {
|
||||
frame, err := readFrame(stream.input)
|
||||
if err != nil && stream.logger != nil {
|
||||
stream.readEnd.Do(func() {
|
||||
stream.logger.DebugContext(stream.ctx, "screener-client", "event", "capture-stream-ended",
|
||||
stream.logger.DebugContext(stream.ctx, "piik-client", "event", "capture-stream-ended",
|
||||
"eof", errors.Is(err, io.EOF), "canceled", stream.ctx.Err() != nil, diagnostics.Error(err))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestCaptureFailureDebugUsesOnlyFixedFields(t *testing.T) {
|
||||
if err := json.Unmarshal(output.Bytes(), &record); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(record) != 8 || record["event"] != "capture-process-failed" || record["msg"] != "screener-client" ||
|
||||
if len(record) != 8 || record["event"] != "capture-process-failed" || record["msg"] != "piik-client" ||
|
||||
record["level"] != "DEBUG" || record["exitCode"] != float64(2) || record["stage"] != check.stage ||
|
||||
record["hresult"] != check.hresult || record["canceled"] != check.canceled || strings.Contains(output.String(), "private") {
|
||||
t.Fatalf("diagnostic leaked or changed fields: %s", output.String())
|
||||
|
||||
@@ -16,12 +16,12 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/mediaedge"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativehost"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativeviewer"
|
||||
"github.com/TNTcraftHIM/Screener/internal/diagnostics"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/mediaedge"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativehost"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativeviewer"
|
||||
"github.com/TNTcraftHIM/Piik/internal/diagnostics"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
@@ -153,7 +153,7 @@ func (session *Session) Handle(ctx context.Context, payload []byte) (result any,
|
||||
!validQualitySettings(request.Profile) {
|
||||
return nil, errors.New("native start-share request is invalid")
|
||||
}
|
||||
slog.Debug("screener-client", "event", "native-profile-requested", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-profile-requested", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "profile", nativeQualityProfile(request.Profile), "codec", request.Codec, "audio", request.Audio,
|
||||
"sourceKind", request.Source.Kind, "adapterIndex", request.AdapterIndex, "encoderIndex", request.EncoderIndex)
|
||||
return session.startShare(ctx, envelope, request)
|
||||
@@ -166,7 +166,7 @@ func (session *Session) Handle(ctx context.Context, payload []byte) (result any,
|
||||
return nil, errors.New("native update-share request is invalid")
|
||||
}
|
||||
profile := nativeQualityProfile(request.Profile)
|
||||
slog.Debug("screener-client", "event", "native-profile-requested", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-profile-requested", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "profile", profile)
|
||||
var err error
|
||||
if host := session.current(request.ShareID); host != nil {
|
||||
@@ -199,7 +199,7 @@ func (session *Session) Handle(ctx context.Context, payload []byte) (result any,
|
||||
audio := request.Audio && session.capabilities.Summary().AudioFor(
|
||||
request.Source.Kind,
|
||||
)
|
||||
slog.Debug("screener-client", "event", "native-source-requested", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-source-requested", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "sourceKind", request.Source.Kind, "audio", audio,
|
||||
"adapterIndex", request.AdapterIndex, "encoderIndex", request.EncoderIndex)
|
||||
err := host.ReplaceSource(ctx, nativecapture.VideoOptions{
|
||||
@@ -210,7 +210,7 @@ func (session *Session) Handle(ctx context.Context, payload []byte) (result any,
|
||||
if err != nil {
|
||||
return operationFailure(envelope, err), nil
|
||||
}
|
||||
slog.Debug("screener-client", "event", "native-source-applied", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-source-applied", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "sourceKind", request.Source.Kind, "audio", audio)
|
||||
return shareSourceReplacedResponse{
|
||||
responseEnvelope: response(envelope, "share-source-replaced"),
|
||||
@@ -347,7 +347,7 @@ func (session *Session) Handle(ctx context.Context, payload []byte) (result any,
|
||||
return nil, errors.New("native share does not exist")
|
||||
}
|
||||
host.SetPaused(request.Paused)
|
||||
slog.Debug("screener-client", "event", "native-share-paused", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-share-paused", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "paused", request.Paused)
|
||||
return response(envelope, "share-paused"), nil
|
||||
default:
|
||||
@@ -429,7 +429,7 @@ func (session *Session) shareUpdateResult(request requestEnvelope, shareID strin
|
||||
if err != nil {
|
||||
return operationFailure(request, err)
|
||||
}
|
||||
slog.Debug("screener-client", "event", "native-profile-applied", "requestId", request.ID,
|
||||
slog.Debug("piik-client", "event", "native-profile-applied", "requestId", request.ID,
|
||||
"share", diagnostics.ID(shareID), "profile", profile)
|
||||
return shareUpdatedResponse{responseEnvelope: response(request, "share-updated"), ShareID: shareID}
|
||||
}
|
||||
@@ -480,7 +480,7 @@ func (session *Session) startShare(
|
||||
session.host = host
|
||||
session.mu.Unlock()
|
||||
codec := host.Codec()
|
||||
slog.Debug("screener-client", "event", "native-profile-applied", "requestId", envelope.ID,
|
||||
slog.Debug("piik-client", "event", "native-profile-applied", "requestId", envelope.ID,
|
||||
"share", diagnostics.ID(request.ShareID), "profile", profile, "codec", codec, "audio", host.HasAudio())
|
||||
go session.watchHost(host)
|
||||
return shareStartedResponse{
|
||||
@@ -940,7 +940,7 @@ func response(request requestEnvelope, responseType string) responseEnvelope {
|
||||
|
||||
func operationFailure(request requestEnvelope, causes ...error) requestFailedResponse {
|
||||
if len(causes) > 0 {
|
||||
slog.Debug("screener-client", "event", "native-operation-failed", "requestId", request.ID,
|
||||
slog.Debug("piik-client", "event", "native-operation-failed", "requestId", request.ID,
|
||||
"requestType", diagnostics.SafeText(request.Type), diagnostics.Error(causes[0]))
|
||||
}
|
||||
return requestFailedResponse{
|
||||
@@ -965,10 +965,10 @@ func (session *Session) traceRequest(request requestEnvelope, payload []byte) fu
|
||||
"share", diagnostics.ID(identity.ShareID), "connection", diagnostics.ID(identity.ConnectionID),
|
||||
"sourceConnection", diagnostics.ID(identity.SourceConnectionID), "publication", diagnostics.ID(identity.PublicationGeneration))
|
||||
started := time.Now()
|
||||
logger.Debug("screener-client", "event", "native-request-started")
|
||||
logger.Debug("piik-client", "event", "native-request-started")
|
||||
return func(result any, err error) {
|
||||
failure, rejected := result.(requestFailedResponse)
|
||||
logger.Debug("screener-client", "event", "native-request-ended", "durationMs", time.Since(started).Milliseconds(),
|
||||
logger.Debug("piik-client", "event", "native-request-ended", "durationMs", time.Since(started).Milliseconds(),
|
||||
"failed", err != nil || rejected, "code", failure.Code, diagnostics.Error(err))
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,13 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativehost"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/loopback"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativehost"
|
||||
)
|
||||
|
||||
func TestMain(tests *testing.M) {
|
||||
if directory := os.Getenv("SCREENER_QUIET_CAPTURE_FIXTURE"); directory != "" {
|
||||
if directory := os.Getenv("PIIK_QUIET_CAPTURE_FIXTURE"); directory != "" {
|
||||
runQuietCaptureFixture(directory)
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func TestQuietHostUpdatePreservesControlAndCancelsCleanly(t *testing.T) {
|
||||
slog.SetDefault(slog.New(slog.NewJSONHandler(&trace, &slog.HandlerOptions{Level: slog.LevelDebug})))
|
||||
}
|
||||
directory := t.TempDir()
|
||||
t.Setenv("SCREENER_QUIET_CAPTURE_FIXTURE", directory)
|
||||
t.Setenv("PIIK_QUIET_CAPTURE_FIXTURE", directory)
|
||||
executable, err := os.Executable()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package nativecontrol
|
||||
|
||||
import (
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/mediaedge"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/mediaedge"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativeaudio"
|
||||
"github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativeaudio"
|
||||
"github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
@@ -76,7 +76,7 @@ func runAudioRecoveryCapture() {
|
||||
}
|
||||
|
||||
func TestAudioEOFWaitsForExplicitSourceReplacement(t *testing.T) {
|
||||
t.Setenv("SCREENER_NATIVEHOST_PIPE_FIXTURE", "audio-recovery")
|
||||
t.Setenv("PIIK_NATIVEHOST_PIPE_FIXTURE", "audio-recovery")
|
||||
check := func(err error) {
|
||||
t.Helper()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package nativehost
|
||||
|
||||
import "github.com/TNTcraftHIM/Screener/internal/client/nativecapture"
|
||||
import "github.com/TNTcraftHIM/Piik/internal/client/nativecapture"
|
||||
|
||||
type QualityProfile struct {
|
||||
Video nativecapture.VideoProfile
|
||||
|
||||
Loaded 100 of 254 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user