---
name: screen-recording
description: >
  Record the user's screen to a video clip via Adom Desktop. THE right tool is
  WGC single-window capture (background, no picker, no banner, occlusion-safe), not
  whole-desktop capture. Covers the full recording verb surface, on-screen captions,
  and the gotchas that make or break it. Trigger words: record the screen, screen
  recording, desktop_record, record a window, WGC, record a demo, capture the screen,
  on-screen captions, desktop_caption, record the browser flow, record in the background.
---

# Screen recording

> **Search the verb surface before you assume.** This skill exists because an agent
> assumed whole-desktop capture was the only option and that nbrowser had no recording,
> both wrong. Run `adom-desktop help record` (the `desktop_recording` namespace, 10
> verbs) and `adom-desktop help <verb>` FIRST. The right tool was hiding in plain sight.

## Use WGC single-window capture (the right tool, almost always)

`desktop_record_window_start` records ONE window via **Windows Graphics Capture (WGC) +
Media Foundation**. This is what you want for recording a browser flow or an app:

- **No picker, no capture banner** (border suppressed on Win11).
- **Background-capturable**: the target window can be **occluded or off-screen** and it
  still records. So you do NOT need to foreground anything, the foreground-theft problem
  (another window stealing focus) simply does not apply.
- Resolve the window by `hwnd` (from `desktop_list_windows` / `desktop_find_window`) or
  `titleContains`, same as `desktop_screenshot_window`.

```bash
# start (recordingId is nested under output.data; path is top-level)
adom-desktop desktop_record_window_start '{"hwnd":17830478,"fps":30,"codec":"h264"}'
# ... drive the page via nbrowser_eval / browser_eval (also background) ...
adom-desktop desktop_record_window_stop '{"recordingId":"rec-<hex>"}'   # -> .mp4 path
# the .mp4 lands under %TEMP%\adom-desktop-recordings\ ; pull_file it (lands in /tmp here)
```

Parse: `recordingId = output.data.recordingId`, `path = top-level .path`.

### The one rule: WGC captures the window's ACTIVE tab

WGC records the window's pixels, i.e. its currently-visible tab. So **the tab you drive
via CDP must be the active tab in the recorded window.** nbrowser has no "activate tab"
verb, so: open a fresh tab with `nbrowser_open_tab` (it becomes active), confirm with
`desktop_find_window` that the window's title is your target, and drive THAT tab. Then
WGC + background CDP eval = a clean recording with zero foregrounding. Output is full-res
window-only (no desktop, no taskbar to crop).

## Whole-desktop capture (only when you truly need the whole screen)

`desktop_record_start` records EVERY pixel via Chrome getDisplayMedia. Avoid it for
single-window jobs, it has three problems WGC doesn't:

- **Foreground theft.** It captures whatever is topmost. If you drive via background CDP,
  the recording shows the WRONG window unless you `desktop_bring_to_front` the target
  before EVERY visible step (the "foreground re-bump"). A window that updates on its own
  (e.g. the Hydrogen panel showing your conversation) keeps stealing the foreground and
  ruins the take.
- **Picker + banner + wake-lock.**
- **Privacy.** It records the user's other tabs/apps.
- Gotchas if you must use it: `recordingId` is **top-level** in the response (not under
  `output`); reset stale state with `desktop_recorder_close` + `sleep 2` first (it
  silently returns no id / a ~439-byte empty file otherwise); run it via the background
  tool, NOT detached with `&` (detached runs produced empty files).

## nbrowser_record (getDisplayMedia, has a picker, inferior to WGC)

`nbrowser_record_start` exists but uses **getDisplayMedia**, so it parks in
`state:"awaiting_pick"` with a **share picker up on the user's screen**. You cannot stop
an `awaiting_pick` record via the API (`nbrowser_record_stop` errors "not recording"),
and the picker is browser chrome (not page DOM, not UIA-reachable). To clear a stuck
picker: click its **Cancel** button via a foregrounded `desktop_click` at the mapped
coordinate, or navigate the tab (cancels the pending request). **Just use WGC instead.**

## On-screen captions

```bash
adom-desktop desktop_caption '{"text":"Every part matched","size":"large","position":"bottom","id":"d","persist":true}'
adom-desktop desktop_caption '{"action":"force-clear"}'   # nuke ALL captions
```

- A large always-on-top click-through overlay, captured by the recording. BUT WGC records
  a single WINDOW; a desktop caption overlay is a SEPARATE window, so WGC of the target
  window will NOT include it. For WGC clips, **caption in post** (see
  [video-post-production](../video-post-production/SKILL.md)). Use `desktop_caption` for
  whole-desktop recordings.
- `force-clear` before any recording: `persist:true` captions survive across clips and
  leak a stale caption into the next one.
- Live captions drift on autonomous flows (the page advances faster than your sleeps).
  Record CLEAN, caption in post, where you control the exact timing.

## Always verify

The recorder can be flaky. After stop, pull the file and **extract a frame to CONFIRM the
right window/tab was captured** before you build on it. Don't assume.
