docs: full env/config reference + fix outdated Bazzite gamescope-only framing
apple / swift (push) Successful in 1m6s
android / android (push) Successful in 4m34s
ci / rust (push) Successful in 4m47s
ci / web (push) Successful in 48s
ci / docs-site (push) Successful in 1m15s
apple / screenshots (push) Successful in 5m14s
deb / build-publish (push) Successful in 2m46s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / bench (push) Successful in 4m41s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 46s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m47s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m47s
docker / deploy-docs (push) Successful in 20s

Rebuild configuration.md into a complete PUNKTFUNK_* reference (verified
against config.rs, the host.env templates, and the env read sites): core,
gamescope/session-following, compositor, video quality, gamepads, audio,
Windows host, auth/paths, perf tuning, diagnostics, and client-side knobs.

Rework bazzite.md: it now documents both Steam Gaming Mode (gamescope) and
the KDE Plasma desktop with auto-detect/session-following, attach vs managed,
and the Desktop screencast + kde-desktop-setup.sh input grant — previously it
only described the managed gamescope model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 20:06:28 +00:00
parent d6596ff81b
commit dd4da9e04d
2 changed files with 198 additions and 53 deletions
+64 -19
View File
@@ -1,15 +1,23 @@
--- ---
title: Bazzite — gamescope title: Bazzite
description: Set up a punktfunk host on Bazzite, streaming a Steam/gamescope session at your client's mode. description: Set up a punktfunk host on Bazzite — it follows the box between Steam Gaming Mode (gamescope) and the KDE Plasma desktop automatically.
--- ---
[Bazzite](https://bazzite.gg/) already ships everything a punktfunk host needs — the NVIDIA driver, [Bazzite](https://bazzite.gg/) already ships everything a punktfunk host needs — the NVIDIA driver,
NVENC, PipeWire, and **gamescope**. So a Bazzite host is the most "appliance-like" setup: the host NVENC, PipeWire, **gamescope**, and the **KDE Plasma desktop**. So a Bazzite host is the most
launches its own gamescope session at the **client's** resolution and refresh, so your games run at "appliance-like" setup, and it streams **both** of Bazzite's faces:
the mode of the device you're streaming to, not the TV the box is plugged into.
> This is ideal for a dedicated game-streaming box. For a general desktop, prefer - **Steam Gaming Mode** (gamescope) — the couch/handheld game UI.
> [Ubuntu/Fedora KDE](/docs/ubuntu-kde) or [GNOME](/docs/ubuntu-gnome). - **The KDE Plasma desktop** — the full desktop you get from "Switch to Desktop".
The host **auto-detects which one is live and follows the box across the switch** — including
mid-stream. You flip between Gaming Mode and Desktop with Bazzite's normal Steam UI /
"Switch to Desktop"; the host just re-targets whatever's running and keeps streaming. Nothing in
`host.env` forces a mode.
> Ideal for a dedicated game-streaming box that you also occasionally want as a remote desktop. For a
> pure desktop machine, [Ubuntu/Fedora KDE](/docs/ubuntu-kde) or [GNOME](/docs/ubuntu-gnome) are
> simpler.
## Install ## Install
@@ -58,31 +66,65 @@ permission, not a client problem.)
## Configure ## Configure
The RPM ships a gamescope-ready config you can copy as your starting point: The RPM ships a Bazzite-tuned config you can copy as your starting point:
```sh ```sh
mkdir -p ~/.config/punktfunk mkdir -p ~/.config/punktfunk
cp /usr/share/punktfunk/host.env.bazzite ~/.config/punktfunk/host.env cp /usr/share/punktfunk/host.env.bazzite ~/.config/punktfunk/host.env
``` ```
The key settings in `~/.config/punktfunk/host.env` point the host at the gamescope backend: The template is deliberately minimal — it does **not** force a compositor, because the host
auto-detects Gaming Mode (gamescope) vs Desktop (KWin) on every connect and follows the switch
mid-stream. The only settings that matter are the session anchors plus zero-copy:
```sh ```sh
PUNKTFUNK_COMPOSITOR=gamescope XDG_RUNTIME_DIR=/run/user/1000
PUNKTFUNK_GAMESCOPE_SESSION=steam # the host owns a Steam session at the client's mode DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
PUNKTFUNK_INPUT_BACKEND=gamescope PUNKTFUNK_VIDEO_SOURCE=virtual
PUNKTFUNK_ZEROCOPY=1 PUNKTFUNK_ZEROCOPY=1 # GPU zero-copy (dmabuf → CUDA → NVENC); auto-falls back to CPU
PUNKTFUNK_GAMESCOPE_ATTACH=1 # Gaming Mode = attach to the box's own session (see below)
``` ```
With this, when a client connects the host starts a `gamescope-session-plus` (Steam) session at the ### Gaming Mode: attach vs managed
client's exact resolution and refresh, and relaunches it if the client changes mode. There should be
**no physical gaming session already running** on the box. For Gaming Mode there are two models (pick one; the shipped default is **attach**):
- **Attach** (`PUNKTFUNK_GAMESCOPE_ATTACH=1`, the default) — the **box** owns its gamescope session
and decides Gaming vs Desktop via the normal Steam UI. The host just attaches to whatever's live
and never tears it down, so switching Desktop ↔ Game is rock-solid and disconnecting leaves the box
where it was. The streamed game-mode resolution is the box's gamescope mode
(`SCREEN_WIDTH/HEIGHT` in `/etc/gamescope-session-plus/sessions.d/steam`), not the client's.
- **Managed** (`PUNKTFUNK_GAMESCOPE_MANAGED=1`, and remove the attach line) — the host tears the
box's gamescope down on connect and launches its **own** at the *client's* exact resolution and
refresh, restoring on idle. Client-mode-following, but it can't coexist with a box-owned game-mode
session, and there must be **no physical gaming session already running**.
Mid-stream Gaming ↔ Desktop following (`PUNKTFUNK_SESSION_WATCH`) is **on by default** on
Bazzite/SteamOS. See [Configuration](/docs/configuration) for the full list of knobs.
### Streaming the KDE Plasma desktop
The **virtual output** (video) for the Desktop session needs no config — the host package ships an
`io.unom.Punktfunk.Host.desktop` file whose `X-KDE-Wayland-Interfaces` grants the host KWin's
restricted screencast protocol on a normal interactive Plasma session (least-privilege, the same
mechanism krfb/krdp use). After a **fresh host install, log out and back into the Desktop session
once** so KWin re-reads that grant.
The one thing a normal KDE login lacks is the RemoteDesktop grant for headless **input** injection.
Seed it once (as the streaming user, no root) so the host auto-approves instead of popping an
un-answerable dialog:
```sh
bash /usr/share/punktfunk/bazzite/kde-desktop-setup.sh
```
Gaming Mode needs none of this — it auto-attaches.
## Run as an always-on host ## Run as an always-on host
Bazzite hosts are typically headless. Enable the host service and linger so it starts at boot — see Bazzite hosts are typically headless. Enable the host service and linger so it starts at boot — see
[Running as a Service](/docs/running-as-a-service). Because the host launches its own gamescope [Running as a Service](/docs/running-as-a-service). One host service covers both Gaming Mode and the
session per client, you don't need a separate desktop-session unit. Desktop; it follows whichever the box is in.
```sh ```sh
systemctl --user enable --now punktfunk-host systemctl --user enable --now punktfunk-host
@@ -109,9 +151,12 @@ the console login screen — see [Forgot your Password?](/docs/forgot-password).
## Good to know ## Good to know
These apply to the **Gaming Mode (gamescope)** path; the KDE Desktop path is unaffected:
- **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's - **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's
current gamescope is fine; this only bites if you've pinned an old one. current gamescope is fine; this only bites if you've pinned an old one.
- **The mouse cursor isn't included in the captured image** — a gamescope limitation for now. - **The mouse cursor isn't included in the captured image** — a gamescope limitation for now. (The
KDE Desktop path renders the cursor normally.)
- **HDR isn't supported yet** on the gamescope path — gamescope's capture output is 8-bit. SDR streams - **HDR isn't supported yet** on the gamescope path — gamescope's capture output is 8-bit. SDR streams
normally. normally.
+134 -34
View File
@@ -1,63 +1,163 @@
--- ---
title: Configuration title: Configuration
description: The host.env settings — compositor, resolution, bitrate, input — and how to tune them. description: Every host.env setting and PUNKTFUNK_* environment variable — compositor, video, input, gamepads, tuning — and how to use them.
--- ---
The host reads its settings from **`~/.config/punktfunk/host.env`** (a simple `KEY=value` file). Your The host reads its settings from **`~/.config/punktfunk/host.env`** (a simple `KEY=value` file, `#`
starts a comment). On Windows the service reads **`%ProgramData%\punktfunk\host.env`** instead. Your
[setup guide](/docs/requirements) gives you a starting `host.env` for your desktop; this page is the [setup guide](/docs/requirements) gives you a starting `host.env` for your desktop; this page is the
reference. full reference for every setting.
## Session settings > **You rarely need most of these.** The host **auto-detects** the compositor, input backend, and
> encoder from your live session — a box that flips between Steam Gaming Mode and a KDE/GNOME desktop
> is followed automatically. The `PUNKTFUNK_*` knobs below are mostly **optional overrides** for
> forcing a specific backend, tuning performance, or debugging. The starter `host.env` for your
> platform sets only the few you actually need.
These tell the host which desktop session to attach to. Your setup guide sets them for you. ## Session anchors
These tell the host which desktop session to attach to. Your setup guide sets them for you; they're
required when the host runs outside your interactive session (e.g. as a service).
| Setting | What it does | | Setting | What it does |
|---|---| |---|---|
| `WAYLAND_DISPLAY` | The Wayland socket of your session (`wayland-0` for a normal desktop). | | `XDG_RUNTIME_DIR` | Your session's runtime dir (e.g. `/run/user/1000`). Always needed for a service. |
| `DBUS_SESSION_BUS_ADDRESS` | Your session bus (e.g. `unix:path=/run/user/1000/bus`). Always needed for a service. |
| `WAYLAND_DISPLAY` | The Wayland socket of your session (`wayland-0` for a normal desktop, `wayland-kde` for the headless-KDE unit). |
| `XDG_CURRENT_DESKTOP` | Your desktop (`GNOME`, `KDE`). | | `XDG_CURRENT_DESKTOP` | Your desktop (`GNOME`, `KDE`). |
| `XDG_RUNTIME_DIR`, `DBUS_SESSION_BUS_ADDRESS` | Needed when the host runs outside your interactive session (e.g. as a service). |
## Core settings On Linux the host **rewrites `WAYLAND_DISPLAY` / `XDG_CURRENT_DESKTOP` / `XDG_RUNTIME_DIR` /
`DBUS_SESSION_BUS_ADDRESS` on every connect** to follow the active session (Gaming ↔ Desktop). Only
`XDG_RUNTIME_DIR` and `DBUS_SESSION_BUS_ADDRESS` need to be pinned as trustworthy anchors.
## Core
| Setting | Values | Meaning | | Setting | Values | Meaning |
|---|---|---| |---|---|---|
| `PUNKTFUNK_COMPOSITOR` | `mutter` · `kwin` · `gamescope` · `wlroots` | Which backend creates the virtual display. Match your desktop. | | `PUNKTFUNK_COMPOSITOR` | `kwin` · `mutter` · `gamescope` · `wlroots` (aliases: `kde`/`plasma`, `gnome`, `sway`/`hyprland`) | Which backend creates the virtual display. **Leave unset to auto-detect;** set only to force one. |
| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at its exact mode (the normal choice). `portal` captures an existing monitor instead. | | `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at the client's exact mode (the normal choice). `portal` captures an existing monitor instead. |
| `PUNKTFUNK_ZEROCOPY` | `1` · `0` | GPU zero-copy capture→encode. Leave on; it falls back to a CPU path automatically. | | `PUNKTFUNK_ZEROCOPY` | `1` · `0` | GPU zero-copy capture→encode (dmabuf → CUDA → NVENC, or D3D11 on Windows). Leave on; it falls back to a CPU path automatically. |
| `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite. | | `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite/gamescope, `wlr` for Sway/wlroots. Auto-detected with the compositor. |
| `PUNKTFUNK_ENCODER` | `auto` · `nvenc` · `vaapi` (Linux) · `amf` · `qsv` · `sw` (Windows) | Encoder backend. `auto` (default) detects the GPU vendor: NVIDIA→NVENC, AMD→VAAPI/AMF, Intel→VAAPI/QSV, else software. |
| `PUNKTFUNK_RENDER_NODE` | path | Linux DRM render node for zero-copy (default `/dev/dri/renderD128`). Set on multi-GPU boxes to pick the right GPU. |
## Resolution and refresh rate Resolution and refresh are **not** set here — **the client chooses them.** When a device connects,
the host creates a virtual display at that device's resolution and refresh rate. A 1080p60 laptop and
a 1440p120 desktop each get their own. (With Moonlight, set the mode in Moonlight; the native clients
let you pick a mode or default to the device's display.)
You don't set these on the host — **the client chooses them**. When a device connects, the host ## gamescope / session following (Linux, Bazzite/SteamOS)
creates a virtual display at that device's resolution and refresh rate. A 1080p60 laptop and a
1440p120 desktop each get their own. (With Moonlight, set the mode in Moonlight's settings; the Two mutually-exclusive models for a Steam/gamescope box. See [Bazzite](/docs/bazzite) for the full
native clients let you pick a mode or default to the device's display.) picture.
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_GAMESCOPE_ATTACH` | `1` | **Attach** model: the box owns its gamescope session (you switch Gaming ↔ Desktop with the Steam UI); the host just captures whatever's live and never tears it down. Rock-solid; streamed resolution is the box's gamescope mode. |
| `PUNKTFUNK_GAMESCOPE_MANAGED` | `1` | **Managed** model: the host tears the box's gamescope down on connect and launches its **own** at the *client's* exact resolution, restoring on idle. Client-mode-following, but doesn't coexist with a box-owned game-mode session. |
| `PUNKTFUNK_GAMESCOPE_SESSION` | `steam` | The host owns a `gamescope-session-plus` (Steam) session at the client's mode (headless appliance; no physical session running). |
| `PUNKTFUNK_GAMESCOPE_NODE` | `auto` · node id | Discover + capture a **running** gamescope's PipeWire node at a fixed mode. Do **not** combine with `SESSION`. |
| `PUNKTFUNK_GAMESCOPE_APP` | command | For an ad-hoc bare-gamescope session, the nested command to run (e.g. `vkcube`). |
| `PUNKTFUNK_SESSION_WATCH` | `1` · `0` | Follow a Gaming ↔ Desktop switch **mid-stream** (rebuild the backend in place, no reconnect). **On by default** on Bazzite/SteamOS; set `0` to disable. |
## Compositor-specific (Linux)
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_KWIN_VIRTUAL_PRIMARY` | `1` | Make the streamed per-session output the sole desktop so plasmashell + windows render on it (not on the headless bootstrap output). Set by the KDE appliance `host.env`. |
| `PUNKTFUNK_MUTTER_VIRTUAL_PRIMARY` | `1` | GNOME/Mutter equivalent of the above. |
| `PUNKTFUNK_MUTTER_VIRTUAL_REFRESH` | `1` | Pin the client's exact WxH**@Hz** via `RecordVirtual`'s custom modes (needed for >60 Hz on Mutter). |
## Video quality
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_FEC_PCT` | `N` (percent) | Forward-error-correction redundancy for lossy links (the default is sensible for a normal LAN). Higher = more loss-resilient, more bandwidth. |
| `PUNKTFUNK_10BIT` | `1` | HEVC Main10 / HDR. Honored only when the client also advertises 10-bit. **Windows host only** (the Linux host stays 8-bit). |
| `PUNKTFUNK_444` | `1` | Full-chroma HEVC 4:4:4 (Range Extensions) — sharper text/desktop, no chroma loss. **punktfunk/1 native only** (Moonlight stays 4:2:0), HEVC-only, honored only when the client advertises 4:4:4 **and** the GPU supports it (probed; NVENC is the validated path — VAAPI/AMF/QSV decline). Independent of 10-bit. |
| `PUNKTFUNK_DSCP` | `1` | Opt-in DSCP / `SO_PRIORITY` QoS tagging on the media sockets. No-op on the wire on Windows without a qWAVE policy. |
## Gamepads
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_GAMEPAD` | `xbox360` · `xboxone` · `dualsense` · `dualshock4` · `steamdeck` · `steamcontroller` (aliases: `ps5`, `ps4`, `deck`, …) | The virtual pad the host creates. Usually **auto-resolved from the client's physical controller** — set this only to force a type. `xbox360` (XInput) is the universal fallback. DualSense/DualShock 4/Steam Deck need Linux UHID; unsupported choices fold to Xbox 360. |
| `PUNKTFUNK_STEAM_GADGET` | `1` · `0` | Force the raw USB-gadget virtual Steam Deck on/off. **On by default on SteamOS**, off elsewhere. Lets Steam promote the virtual Deck to full Steam Input. |
## Audio / microphone
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_AUDIO_GAIN` | float (default `1.0`) | Linear gain applied to capture — bump it for a quiet source. |
| `PUNKTFUNK_MIC_DEVICE` | name substring | **(Windows)** Target mic-uplink device by friendly-name substring (first match wins). |
| `PUNKTFUNK_NO_MIC_INSTALL` | set | **(Windows)** Skip installing the virtual-mic driver (e.g. when the host runs as SYSTEM). |
## Windows host
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_VDISPLAY` | `pf` | Virtual-display backend. The bundled pf-vdisplay IddCx driver is the only backend now — informational; leave as `pf`. |
| `PUNKTFUNK_IDD_PUSH` | `1` · `0` | Capture straight from the pf-vdisplay driver's shared ring (the validated zero-copy path, incl. the secure desktop). Set `0` to force WGC/DDA capture. |
| `PUNKTFUNK_SECURE_DDA` | `1` | Capture the secure desktop (UAC / lock / login) so the stream survives those transitions. |
| `PUNKTFUNK_MONITOR_LINGER_MS` | ms (default `10000`) | Keep a per-client virtual display alive briefly after disconnect so a quick reconnect reuses it (no display connect/disconnect chime). |
| `PUNKTFUNK_RENDER_ADAPTER` | description substring | Multi-GPU boxes only: force the NVENC/capture GPU by adapter Description substring (e.g. `4090`). Leave unset on single-GPU machines. |
| `PUNKTFUNK_HOST_CMD` | e.g. `serve --gamestream` | The host subcommand the service launches. Default `serve --gamestream`; use `serve` for a secure native-only host. |
## Auth, API & paths
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_MGMT_TOKEN` | token | Bearer token for the management API. If unset it's auto-generated and persisted to `~/.config/punktfunk/mgmt-token` (the bundled web console sources it). Set only to pin a specific token. |
| `PUNKTFUNK_UI_PASSWORD` | password | Web-console login password. Normally generated on first start and stored in `~/.config/punktfunk/web-password` — see [Forgot your Password?](/docs/forgot-password). |
| `PUNKTFUNK_CONFIG_DIR` | path | Override the config directory (default `~/.config/punktfunk`) — pairing state, certs, apps.json, captures. |
## Advanced performance tuning
Leave these at their defaults unless you're chasing latency; see the [troubleshooting](/docs/troubleshooting)
notes for context.
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_GSO` | `1` · `0` | UDP Generic Segmentation Offload on the send path (coalesce a frame's packets into kernel super-buffers) — the dominant lever above ~1 Gbps. On by default; auto-falls back to `sendmmsg`. Set `0` if a NIC/middlebox mishandles GSO. |
| `PUNKTFUNK_SPLIT_ENCODE` | `0`/`disable` · `1`/`auto` · `2` · `3` | NVENC N-way split-encode for very high pixel rates (5K@240). `auto` picks automatically above ~1 Gpix/s. |
| `PUNKTFUNK_GPU_PRIORITY_CLASS` | `off` · `normal` · `high` · `realtime` | **(Windows)** GPU scheduling priority for capture/encode under a GPU-saturating game. Default `high`; `realtime` is the strongest lever but can freeze NVENC on some setups. |
| `PUNKTFUNK_IDD_DEPTH` | `N` (default `2`) | **(Windows)** IDD-push pipeline depth. `1` cuts latency once GPU priority is raised; higher smooths a contended GPU. |
## Diagnostics
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_PERF` | `1` | Log per-stage timing (capture, encode, send) — handy when tuning latency. |
| `RUST_LOG` | `info` · `debug` · `trace` | Log verbosity. On Windows, logs land in `%ProgramData%\punktfunk\logs\`. |
| `PUNKTFUNK_FFMPEG_DEBUG` | set | Verbose libavcodec/FFmpeg logging from the encoder. |
| `PUNKTFUNK_VIDEO_DROP` | `N` (percent) | Deliberately drop N% of video packets to exercise FEC recovery. **Testing only.** |
## Client-side (native clients)
A few knobs are read by the native **clients**, not the host:
| Setting | Values | Meaning |
|---|---|---|
| `PUNKTFUNK_DECODER` | `software` · `vaapi` (Linux) | Force the decode path. Default auto-selects hardware (VAAPI on Intel/AMD, D3D11VA on Windows) with a software fallback. |
## Bitrate ## Bitrate
The client requests a bitrate; the host encodes to it. To find a good value for your link: The client requests a bitrate; the host encodes to it. There's no host-side bitrate knob. To find a
good value:
- **Native clients (Apple, Linux, and more):** use the built-in **speed test** (from a host's menu). - **Native clients (Apple, Linux, Windows, Android):** use the built-in **speed test** (from a
It measures your link, suggests a bitrate, and applies it. host's menu). It measures your link, suggests a bitrate, and applies it.
- **Moonlight:** set the bitrate in Moonlight's settings. Start moderate and raise it. - **Moonlight:** set the bitrate in Moonlight's settings. Start moderate and raise it.
## Multiple devices at once ## Multiple devices at once
Today the native `punktfunk/1` host (`serve`) streams **one session at a time** — additional Today the native `punktfunk/1` host (`serve`) streams **one session at a time** — additional clients
clients wait in the accept queue until the active session ends. Each session gets its own virtual wait in the accept queue until the active session ends. Each session gets its own virtual display at
display at the client's exact resolution; concurrent native sessions are on the roadmap. the client's exact resolution; concurrent native sessions are on the roadmap. (`punktfunk1-host`, the
standalone test host, has a `--max-concurrent N` knob — see the [Host CLI](/docs/host-cli) reference —
(`punktfunk1-host`, the standalone test host, has a `--max-concurrent N` knob, default 4, bounded by your but `serve` does not take that flag.)
GPU's encoder — see the [Host CLI](/docs/host-cli) reference — but `serve` does **not** take
that flag.)
## Codec and FEC ## Codec and FEC
- The host encodes **HEVC (H.265)** by default; **AV1** is available for clients that support it. - The host encodes **HEVC (H.265)** by default; **AV1** is available for clients that support it.
- The native protocol adds forward error correction for lossy links. `PUNKTFUNK_FEC_PCT=N` sets the - The native protocol adds forward error correction for lossy links — see `PUNKTFUNK_FEC_PCT` above.
redundancy percentage (the default is sensible for a normal LAN).
## Diagnostics
- `PUNKTFUNK_PERF=1` logs per-stage timing (capture, encode, send) — handy when tuning latency.
- `RUST_LOG=info` (or `debug`) controls log verbosity.