Files
punktfunk/docs-site/content/docs/moonlight.md
T
enricobuehler 09a5957c6d feat(clients): unified stats vocabulary across every client + Moonlight comparison docs
One stat model everywhere (design/stats-unification.md): four measurement
points (capture/received/decoded/displayed), three stages that tile the
interval exactly, and a HUD that shows the addition explicitly —

  end-to-end 14.2 ms p50 · 19.8 p95 · capture→on-glass
  = host+network 9.8 + decode 2.1 + display 2.3

replacing each client's ad-hoc mix of overlapping absolutes (the Apple HUD's
three arrow lines that looked sequential but weren't), mean-vs-median decode
times (Windows/Linux), missing same-host-clock flags (Windows/Linux), and
three different names for the same capture→received measurement (probe's
"reassembled", Apple/Android's "client", Windows/Linux's post-decode "lat").

Per client: Apple threads receivedNs through the VT decode via the frame
refcon bit pattern so the decode stage exists at all (stage-1 fallback
honestly degrades to a capture→received headline); Windows carries
FrameTimes through the existing frame channel to the render thread and adds
e2e p50/p95 post-Present; Linux stamps received at AU pop and rides
decoded_ns on DecodedFrame to the paintable-set site; Android pairs receipt
stamps with MediaCodec output buffers via the codec's pts round-trip (JNI
stats array 14→16 doubles, indexes 0-13 unchanged). fps now uniformly counts
received AUs; lost/(received+lost) per window, hidden at zero.

docs-site gains "Understanding the Stats Overlay": what each line means, why
the equation only approximately sums (percentiles), and a line-by-line
Moonlight/Sunshine matrix — including that Moonlight has no end-to-end
number and its "network latency" is an ENet control RTT, so punktfunk's
headline must not be compared against any single Moonlight line.

Verified here: linux client + probe + core check/clippy/fmt green, android
native cargo-ndk arm64 check green. Pending: Windows CI + on-glass, swift
test on the mac, on-device Android.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 21:01:29 +00:00

58 lines
2.9 KiB
Markdown

---
title: Connect with Moonlight
description: Stream from a punktfunk host using any Moonlight client.
---
punktfunk speaks the **GameStream** protocol, so [Moonlight](https://moonlight-stream.org/) connects
to it like it would to any GameStream host — no punktfunk-specific app needed. It's a great option for
a browser, a smart TV, or any device without a native client.
> Many platforms also have a **native punktfunk client** with lower latency and built-in
> discovery/pairing — including **Windows** and **Android** (phone and Android TV). See
> [Clients](/docs/clients) before reaching for Moonlight.
## 1. Make sure the host is running with GameStream enabled
Moonlight needs the GameStream planes, which are **opt-in**. Run the host with `--gamestream`:
```sh
punktfunk-host serve --gamestream
```
(Bare `serve` is the secure native-only default and stock Moonlight clients can't connect to it; the
native plane is always on, and `--gamestream` adds the Moonlight-compat surface.) GameStream pairs over
plain HTTP and its legacy control encryption is weaker than the native plane's, so only enable it on a
**trusted LAN**. If you run the host as a [service](/docs/running-as-a-service), make sure its
`ExecStart` includes `--gamestream`. The host advertises itself on the network, so Moonlight usually
finds it on its own.
## 2. Add the host in Moonlight
Open Moonlight. Your host should appear automatically on the same network. If it doesn't, use **Add
Host manually** and enter the host machine's IP address.
## 3. Pair
Select the host and choose **Pair**. Moonlight shows a 4-digit PIN. On the host, you confirm pairing
(from the web console, or it accepts the ceremony when armed) — see [Pairing & Trust](/docs/pairing).
Once paired, Moonlight remembers the host.
## 4. Stream
Pick an app/desktop and start streaming. The host creates a virtual display at the resolution and
frame rate Moonlight requests (set these in Moonlight's settings), encodes it on the GPU, and streams
it. Mouse, keyboard, and controllers flow back to the host.
## Tips
- **Set your resolution and frame rate in Moonlight's settings** before connecting — the host matches
whatever Moonlight asks for, creating the virtual display at that exact mode.
- **Codec:** HEVC (H.265) is a good default; AV1 is available if your client supports it.
- **Bitrate:** start moderate and raise it. For very high bitrates, the [native
clients](/docs/clients) have a built-in speed test; with Moonlight, set the bitrate manually.
- Moonlight uses the GameStream protocol, not punktfunk's native FEC/encryption extensions. On a
solid LAN this is fine; on a lossy link a [native client](/docs/clients) holds up better.
- Comparing Moonlight's performance overlay with a punktfunk client's stats HUD? The numbers
measure different slices of the pipeline — see [Understanding the Stats Overlay](/docs/stats)
for a line-by-line comparison matrix before drawing conclusions.