diff --git a/.gitignore b/.gitignore index 74abca3d..fe2cf8f4 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,9 @@ screenshots/ # Local screenshot scratch folder (capture-steam-interval.ts output) screenshot-review/ +# Raw screencast frames + intermediate encodes (capture-videos.ts scratch). +videos/ + # background-agent git worktrees — never track .worktrees/ diff --git a/README.md b/README.md index fc0051c1..87c21861 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,22 @@ N64 classic — without leaving your game. It runs as an **in-game overlay** in Steam's Gaming Mode and as a **standalone app** on the desktop, detecting which mode you're in and adapting automatically. -[**Install →**](#install) · [Featured plugins](#featured-plugins) · [All plugins](#all-plugins) · [Supported devices](#supported-devices--testing) · [Docs](#documentation) +[**Install →**](#install) · [See it in action](#see-it-in-action) · [Featured plugins](#featured-plugins) · [All plugins](#all-plugins) · [Supported devices](#supported-devices--testing) · [Docs](#documentation) > 🚧 **Pre-launch.** Daily-driven on OneXPlayer devices and tested on Valve's > Steam Deck. I'm [looking for testers](#supported-devices--testing) on other > handhelds. +## See it in action + +Set your power limit without leaving your game — TDP presets and a live slider, +right in the overlay: + +![Loadout — TDP control in the overlay](plugins/tdp-control/assets/demo.webp) + +Clips are captured straight from the running overlay — see +[docs/media-capture.md](docs/media-capture.md). + ## Install One command. It downloads the prebuilt binary and overlay, verifies SHA-256, @@ -271,6 +281,7 @@ before trusting a change). Full dev/build/test loop: | [Gamepad Navigation](docs/gamepad-navigation-guide.md) | Spatial navigation, focus management | | [OS Compatibility](docs/os-compatibility.md) | SteamOS, Bazzite, CachyOS specifics | | [Releasing](docs/releasing.md) | Versioning policy + how releases are cut | +| [Media Capture](docs/media-capture.md) | Capturing overlay screenshots + video clips | See [CHANGELOG.md](CHANGELOG.md) for the release history. diff --git a/docs/media-capture.md b/docs/media-capture.md new file mode 100644 index 00000000..b6f12224 --- /dev/null +++ b/docs/media-capture.md @@ -0,0 +1,177 @@ +# Media capture — screenshots & video clips + +Loadout's README and per-plugin pages are illustrated with media captured +straight from the **running overlay** over its CEF DevTools endpoint +(`http://localhost:9222` in dev). Two scripts drive the same overlay the same +way — they share the CDP + navigation + recipe machinery in +[`scripts/lib/overlay-cdp.ts`](../scripts/lib/overlay-cdp.ts): + +| Script | Output | Written to | +| -------------------------------- | --------------------------------- | ----------------------------------------------------- | +| `scripts/capture-screenshots.ts` | PNG stills (tracked) | `plugins//assets/screenshot*.png`, `docs/assets/` | +| `scripts/capture-videos.ts` | animated **WebP** clips (tracked) | `plugins//assets/demo.webp`, `docs/assets/*.webp` | + +## Prerequisites + +- The overlay running in dev with DevTools exposed: `bun run dev:overlay` + (DevTools is baked in via `electrobun.config.ts` → `build.linux.chromiumFlags`). +- `ffmpeg` on `PATH` — used to encode the captured frames. It's the only extra + dependency; the WebP/GIF/H.264 encoders it ships with are all we need. + +## Capturing video clips + +There are two capture modes, both encoding to WebP with ffmpeg: + +- **Per-plugin tours** (`--tours`, the default) — captioned tours defined by + each plugin's `tour.json`. See [Per-plugin tours](#per-plugin-tours---tours). +- **Steam Big Picture** (`--target=steam`) — theme-loader / Store Bridge as + they appear in Steam's own UI. See + [Steam Big Picture clips](#steam-big-picture-clips---targetsteam). + +```sh +bun run capture:videos --list # list every tour + steam clip +bun run capture:videos --format=all # also emit GIF + MP4 alongside the WebP +bun run capture:videos --width=1024 # lighter than the 1280 default +bun run capture:videos --keep-frames # leave the raw JPEG frames in videos/ +``` + +### How it records + +`Page.startScreencast` streams JPEG frames as the page changes; each frame is +timestamped on arrival. Frames only arrive on a **visual change**, so a +deliberate `wait` hold emits no frames — its duration is preserved as the gap +to the next frame. ffmpeg then re-encodes the frames (with their real +per-frame durations) to a constant-rate animated WebP. Raw frames land in the +gitignored `videos//` scratch dir and are deleted unless `--keep-frames`. + +## Steam Big Picture clips (`--target=steam`) + +Some of the best features — theme-loader's CSS theming and Store Bridge's Epic +collection — render in **Steam's own Big Picture UI**, not the overlay. That's a +different CEF surface (port `8080`, discovered via +[`@loadout/steam-cdp`](../packages/steam-cdp)), but the same screencast → ffmpeg +pipeline applies. + +**Run it from Gaming Mode with Big Picture in the foreground.** CEF only rasters +its offscreen surface while Steam is actively painting it, so a backgrounded Big +Picture screencasts blank — the script skips a clip that captures too few +frames and tells you why. + +Two clips ship (`--target=steam --list` to see them): + +- **`steam-theme`** — flips theme-loader's injected `