Files
punktfunk/clients/probe/README.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

56 lines
3.0 KiB
Markdown

# punktfunk — probe (reference client)
`punktfunk-probe` is the **headless reference client** for the `punktfunk/1` protocol — a
command-line tool for testing, latency measurement, and validating host behavior. It's not a
streaming app you'd watch on; it connects, exercises a plane, and reports numbers. If you want to
actually stream, use the [Linux](../linux/README.md), [Windows](../windows/README.md),
[Apple](../apple/README.md), or [Android](../android/README.md) clients.
Because it links the same **`punktfunk-core`** as every other client, it's also the canonical
example of driving the protocol end to end: QUIC control plane, UDP data plane, and the side planes
(input, audio, rumble) over QUIC datagrams.
## What it does
- **Receives a real stream**, writes a playable elementary stream (`.h265`/`.h264`/`.av1` — the
extension tracks the **negotiated codec**; the probe advertises all three and the host picks), and
reports per-frame **capture→received latency** percentiles (the host stamps each frame with
its capture clock).
- **Verification mode** against a synthetic host — byte-checks deterministic test frames.
- **Exercises every plane** with scripted test traffic:
`--input-test` (mouse/keyboard), `--mic-test` (a 440 Hz Opus tone up to the host mic),
`--touch-test` (a synthetic finger), `--rich-input-test` (DualSense touchpad + motion, logging the
HID-output feedback that comes back).
- **Trust** — `--pin <64-hex>` pins the host fingerprint; `--pair <PIN>` runs the SPAKE2 pairing
ceremony and prints the verified fingerprint to pin from then on. Without a pin it trusts on first
use.
- **Discovery** — `--discover [secs]` browses the LAN for `_punktfunk._udp` hosts and prints each
(name, addr:port, pairing requirement, cert fingerprint), then exits.
- **Negotiation knobs** — `--mode WxHxFPS`, `--remode` (mid-stream mode change), `--bitrate`,
`--codec auto|h264|hevc|av1` (preference; the host resolves), `--audio-channels`
(stereo / 5.1 / 7.1), `--compositor`, `--gamepad`, `--launch`, `--speed-test`.
Env: `PUNKTFUNK_CLIENT_10BIT=1` / `PUNKTFUNK_CLIENT_444=1` advertise the 10-bit / 4:4:4 client
caps (for testing a host's `PUNKTFUNK_10BIT`/`PUNKTFUNK_444`).
## Usage
```sh
# stream 720p120 from a host, save the video, and print latency percentiles:
cargo run -p punktfunk-probe -- --mode 1280x720x120 --connect HOST:PORT --out /tmp/a.h265
# list hosts on the LAN:
cargo run -p punktfunk-probe -- --discover
# pair with a host that requires it (read the PIN off the host), then stream:
cargo run -p punktfunk-probe -- --connect HOST:PORT --pair 1234
cargo run -p punktfunk-probe -- --connect HOST:PORT --pin <64-hex> --input-test
```
Full flag reference is in the module doc-comment at the top of [`src/main.rs`](src/main.rs).
## Related
- **[Project README](../../README.md)** — the host, the streaming clients, and the protocol
- **`punktfunk-host punktfunk1-host`** — the persistent native-protocol listener to probe against
(see the "Running on this box" section of the repo README / `CLAUDE.md`)