# 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](https://docs.punktfunk.unom.io)** — start with
[How It Works](https://docs.punktfunk.unom.io/docs/how-it-works) or the
[Quick Start](https://docs.punktfunk.unom.io/docs/quickstart).

punktfunk pairs a **virtual-display streaming host** with native clients on every platform. It speaks
the existing **GameStream** protocol, so any [Moonlight](https://moonlight-stream.org/) 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 |
|-----------|-------|
| **Core** — `punktfunk-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 protocol** — `punktfunk/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](https://docs.punktfunk.unom.io/docs/status)** ·
roadmap: **[/docs/roadmap](https://docs.punktfunk.unom.io/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](https://docs.punktfunk.unom.io/docs/ubuntu-gnome) · [KDE](https://docs.punktfunk.unom.io/docs/ubuntu-kde) |
| **Fedora / Bazzite** (rpm-ostree) | `rpm-ostree install punktfunk punktfunk-web` *(or the bootc image)* | [Fedora — KDE](https://docs.punktfunk.unom.io/docs/fedora-kde) · [Bazzite](https://docs.punktfunk.unom.io/docs/bazzite) |
| **Arch / Steam Deck** (PKGBUILD / sysext) | `makepkg -si` *(Arch)* · sysext `.raw` *(SteamOS)* | [packaging/arch](packaging/arch/README.md) |
| **Windows** (NVIDIA, x64) | signed `setup.exe` from the package registry | [Windows Host](https://docs.punktfunk.unom.io/docs/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](https://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](https://docs.punktfunk.unom.io/docs/pairing). Per-device install steps:
**[/docs/install-client](https://docs.punktfunk.unom.io/docs/install-client)**.

## Build & test (from source)

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

```sh
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](https://docs.punktfunk.unom.io).

## 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.
