enricobuehler e5057f6cc1 feat(windows-host): finish HostConfig migration — resolve operator/dispatch knobs once (Goal-1 stage 2)
Migrate 31 genuinely-constant operator/dispatch env::var sites onto HostConfig, so the
capture/topology/encoder decision reads ONE owner instead of being recomputed at each call
site (the latent bug where capture and encode could disagree on the resolved backend, plan §2.4):
idd_push x7, no_wgc, capture_backend, render_adapter, encoder_pref (Linux open_video +
linux_zero_copy_is_vaapi), the Windows vdisplay-backend select, plus the plan-named
secure_dda/idd_depth/zerocopy/ten_bit and the multi-site perf x4 / compositor x5 /
video_source x3 / gamepad. Each HostConfig field's parser is byte-identical to the read it
replaced, so old==new by construction (the plan's "a flipped bool is a silent regression" guard).

Scope correction — the plan's "~64 sites / Linux XDG+compositor included / grep env::var -> 0"
was unsafe as written. Two classes are deliberately KEPT as live reads and documented in config.rs:

  * Runtime-mutated session vars. vdisplay::apply_session_env REWRITES the process env on every
    connect (the Bazzite Gaming<->Desktop follow): WAYLAND_DISPLAY, XDG_CURRENT_DESKTOP,
    XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS, and the derived PUNKTFUNK_INPUT_BACKEND,
    GAMESCOPE_SESSION/NODE, KWIN/MUTTER_VIRTUAL_PRIMARY, FORCE_SHM. Parsing these once would
    freeze them at startup and silently break session-following — they are NOT constant.
  * Single-use local tuning with no resolve-once benefit (and FEC_PCT even has two different
    semantics): FEC_PCT, VIDEO_DROP, VBV_FRAMES, SPLIT_ENCODE, PACE_BURST_KB, the dxgi timing
    knobs, the *_LIVE/test gates, plus path/dynamic reads (config-dir, PATH search,
    env-forward-to-child). PUNKTFUNK_ZEROCOPY is split on purpose: Windows presence-semantics
    moved to the field; Linux keeps its own truthy (1|true|yes|on) parser.

Verified: Linux cargo check + clippy (-D warnings) + fmt clean on the touched files. The
Windows-only edits are 1:1 substitutions; they get a real Windows compile on the box with Stage 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:24:00 +00:00
2026-06-19 15:49:48 +02:00

punktfunk

Low-latency desktop and game streaming, Linux-first. Run the host on a Linux machine — or a Windows PC — with an NVIDIA GPU, connect from a Mac, PC, phone, tablet, or TV, and stream your desktop or games — each device at its own native resolution and refresh rate, over your local network.

📖 Documentation: docs.punktfunk.unom.io — start with How It Works or the Quick Start.

punktfunk pairs a virtual-display streaming host with native clients on every platform. It speaks the existing GameStream protocol, so any Moonlight client works day one — and adds its own faster punktfunk/1 protocol that breaks the ~1 Gbps FEC wall with a GF(2¹⁶) Leopard-RS transport. A single shared Rust core (punktfunk-core) holds the protocol, FEC, and crypto, linked into the host and every client over a stable C ABI.

What makes it different

  • Your device's exact mode. For each client that connects, the host spins up a virtual display sized to that device — 1080p60 to a laptop, 1440p120 to a desktop, 4K to a TV, all at once. No letterboxing, no scaling, no rearranging your real monitors.
  • Low latency, GPU end to end. Frames go straight from the compositor to the NVENC encoder with zero CPU copies (dmabuf → CUDA/Vulkan → NVENC), over a transport tuned for responsiveness rather than throughput. Stable 240 fps at 5120×1440; sub-millisecond capture-to-reassembly on a LAN.
  • Works with what you already have. Any Moonlight/Artemis client connects over GameStream — and native apps for macOS, Linux, Windows, and Android use the lower-latency punktfunk/1 protocol.
  • Secure by default. Hosts require a one-time SPAKE2 PIN pairing; after that, devices reconnect on a pinned identity. No accounts, no cloud. Hosts auto-advertise over mDNS, so clients find them on the network without typing an IP.

Status

Component State
Corepunktfunk-core + C ABI (protocol · FEC · crypto · QUIC) Complete & hardened
GameStream host → stock Moonlight Live end-to-end: pairing, RTSP, audio, per-client virtual output at native resolution, GPU zero-copy NVENC, gamepads
Native protocolpunktfunk/1 Validated live: QUIC control + GF(2¹⁶) FEC/AES-GCM data plane, PIN pairing, mDNS discovery, mid-stream mode renegotiation
Windows host (NVIDIA, x64) 🟡 Implemented & shipping as a signed installer (DXGI capture · SudoVDA virtual display · NVENC · WASAPI · ViGEm); NVIDIA-only, newer than the Linux host
macOS / iOS / tvOS client (clients/apple) Streaming live: VideoToolbox decode, controllers incl. DualSense, discovery, pairing, speed test
Linux client (clients/linux, GTK4) Streaming live: FFmpeg + VAAPI zero-copy decode, PipeWire audio, SDL3 controllers; ships as Flatpak/apt/rpm/Arch
Android client (clients/android, phone + TV) Streaming live: AMediaCodec decode + HDR10, Oboe audio, controllers, discovery, pairing
Windows client (clients/windows, WinUI 3) 🟡 Stage 1 complete, ships as signed MSIX (x64 + ARM64); D3D11VA decode + HDR present pending on-glass validation
Web console + management API (web/) TanStack console over the OpenAPI mgmt API: host status, paired devices, on-demand PIN pairing

The GameStream host works with a stock Moonlight client — validated live on NVIDIA hardware (RTX 5070 Ti, RTX 4090): PIN pairing that persists across restarts, an app catalog, RTSP/ENet/audio, and video at the client's exact resolution and refresh via a per-session virtual output (KWin, gamescope, Mutter, and Sway/wlroots backends), encoded with GPU zero-copy (dmabuf → CUDA/Vulkan → NVENC) up to 5120×1440@240. The native punktfunk/1 protocol adds a QUIC control plane and a GF(2¹⁶) Leopard-FEC + AES-GCM data plane (p50 ~0.8 ms capture→reassembled at 720p120), with mid-stream mode renegotiation and a wall-clock skew handshake so latency stays valid across machines. Both run from one process: bare punktfunk-host serve is the secure native-only default (punktfunk/1 + the management API/web console), and serve --gamestream additionally enables the GameStream/Moonlight-compat planes (opt-in, trusted-LAN only — GameStream has inherent on-path weaknesses). The host is managed through a REST API and web console. Builds against FFmpeg 7 or 8.

Full milestone status: docs.punktfunk.unom.io/docs/status · roadmap: /docs/roadmap.

Install the host

Pick your platform and install from its package registry — the per-platform guide covers adding the repo, first run, and the web console. The Linux host is the primary, most battle-tested path; a Windows host (NVIDIA-only) also ships as a signed installer.

Platform Install Guide
Ubuntu / Debian (apt) sudo apt install punktfunk-host (after adding the repo) Ubuntu — GNOME · KDE
Fedora / Bazzite (rpm-ostree) rpm-ostree install punktfunk punktfunk-web (or the bootc image) Fedora — KDE · Bazzite
Arch / Steam Deck (PKGBUILD / sysext) makepkg -si (Arch) · sysext .raw (SteamOS) packaging/arch
Windows (NVIDIA, x64) signed setup.exe from the package registry Windows Host

punktfunk-host is the streaming host; punktfunk-web is the browser console (pairing + status). After install, run punktfunk-host serve inside your desktop session (the secure native default; add --gamestream on a trusted LAN if you also want stock Moonlight clients), then pair from the web console. Full instructions: docs.punktfunk.unom.io/docs/install.

Connect a client

Streaming to… Use
Mac, iPhone, iPad, Apple TV The Apple app (clients/apple) — also on TestFlight
Linux desktop / laptop, Steam Deck punktfunk-client (Flatpak / apt / rpm / Arch)
Android phone or TV The Android app (clients/android)
Windows Native punktfunk-client (signed MSIX) or Moonlight
Anything else (browser, old phone, smart TV) Moonlight over GameStream

Each client discovers hosts on the network automatically and does a one-time PIN pairing. Per-device install steps: /docs/install-client.

Build & test (from source)

For development, or as an install fallback where no package is available:

cargo build --workspace          # the Rust core, host, Linux client, and probe (Linux & macOS)
cargo test  --workspace          # unit + loopback + proptest + C ABI harness
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check

cargo run -p loss-harness        # FEC loss-resilience sweep (no network needed)
bash crates/punktfunk-core/tests/c/run.sh   # standalone C-ABI link + round-trip proof

The C header regenerates from crates/punktfunk-core/src/abi.rs on every build (cbindgen via build.rs) into include/punktfunk_core.h. The Apple, Android, and Windows clients have their own toolchains (Xcode/swift build, Gradle, and cargo on the MSVC target) — see each client's README and the docs site.

Layout

crates/
  punktfunk-core/   protocol · FEC · pacing · crypto · QUIC control plane — the C ABI (lib + cdylib + staticlib)
  punktfunk-host/   Linux host: virtual displays · capture · encode · input · GameStream · punktfunk/1 · mgmt
clients/
  apple/    macOS / iOS / tvOS app (Swift · VideoToolbox · Metal · GameController)
  linux/    Linux desktop app (Rust · GTK4/libadwaita · FFmpeg/VAAPI · PipeWire · SDL3)
  windows/  Windows desktop app (Rust · WinUI 3 · D3D11 · WASAPI · SDL3)
  android/  Android phone + TV app (Kotlin · Rust JNI core · AMediaCodec · Oboe)
  probe/    headless reference / measurement client for punktfunk/1
  decky/    Steam Deck Decky plugin
web/                         web console (TanStack) over the management API — status · devices · pairing
packaging/                   apt · rpm / COPR · Arch · Flatpak · Bazzite bootc image
docs-site/                   public documentation site (Fumadocs) — https://docs.punktfunk.unom.io
docs/                        design notes & deep-dive plans
include/punktfunk_core.h     cbindgen-generated C header (checked in)
tools/                       latency-probe · loss-harness (measurement)

Design invariants

  • One core, linked everywhere. Protocol, FEC, and crypto live in punktfunk-core exactly once, exposed over a stable, versioned C ABI (punktfunk_abi_version(), PunktfunkConfig carries its own struct_size). Every native client links the same core.
  • No async on the hot path. The per-frame pipeline uses native threads only; tokio/quinn are gated behind the off-by-default quic feature (control plane only).
  • Native client resolution, no scaling. Each session gets a virtual output at exactly the client's WxH@Hz; each compositor keeps its own backend behind a shared VirtualDisplay trait.
  • FEC is the wall-breaker. GF(2⁸) (≤255 shards/block) for Moonlight compatibility; GF(2¹⁶) (≤65535 shards/block, SIMD, O(n log n)) for punktfunk/1 to push past ~1 Gbps.

License

MIT OR Apache-2.0.

S
Description
next gen game streaming - built using rust, back compatible with game stream clients, and supporting virtual displays for kde/kwin, gnome and gamescope.
Readme 16 MiB
v0.2.1 Latest
2026-06-28 12:51:55 +00:00
Languages
Rust 72%
Swift 12.3%
TypeScript 4.1%
Kotlin 3.2%
Shell 3.2%
Other 5.1%