A Claude Code skill that records browser-based gameplay and web sessions as MP4 video using Playwright for browser automation. Point it at any URL, describe what inputs to simulate, and get a clean MP4 back — no manual screen recording setup required.
Works on Windows, Mac, WSL, and headless Linux VPS. Platform detection and virtual display management are fully automatic.
Drop the skill file into your Claude Code skills directory:
cp screen-recorder.skill ~/.claude/skills/Then install dependencies for your platform:
Mac
brew install ffmpeg
pip install playwright
playwright install chromiumLinux / WSL / VPS
sudo apt-get install -y ffmpeg xvfb
pip install playwright
playwright install chromium
playwright install-deps chromiumWindows
winget install ffmpeg
pip install playwright
playwright install chromiumVerify everything is ready:
python3 scripts/detect_platform.py --verifyThe skill uses Playwright to launch a real Chromium browser, navigate to your site, simulate inputs, and record the viewport directly as video. ffmpeg converts the output to MP4.
Platform Detection
|
v
Display Setup (Xvfb on headless Linux/VPS, native on Windows/Mac)
|
v
Playwright Browser Launch (headed or headless)
|
v
Navigate --> Setup --> Record --> Simulate Inputs
|
v
MP4 Output (Playwright video or ffmpeg capture)
No manual display setup required. The skill detects your environment automatically:
- Windows / Mac — launches a headed browser with native GPU support
- WSL with WSLg — uses the WSLg X server for headed recording
- Linux VPS / headless WSL — auto-starts an Xvfb virtual display and runs headed inside it
detect_platform.py runs first on every invocation and returns a JSON object describing the OS, display method, available tools, and any missing dependencies.
Trigger the skill with natural language in Claude Code. All of the following work:
record my game at https://yourgamesite.com for 30 seconds
Detects platform, launches browser, navigates to URL, records 30 seconds, saves MP4.
record gameplay on https://yourgamesite.com, press Space to start,
then hold ArrowRight for 2 seconds, jump with Space every 3 seconds, record for 1 minute
Claude generates a scenario JSON from your description and runs it during the recording.
go to https://yourgamesite.com, click "Play as Guest", wait for the game to load,
then record 30 seconds of gameplay using arrow keys
Pre-actions (click, type, wait_for) run before recording starts — useful for login flows, cookie banners, or waiting for assets to load.
record 3 separate clips from https://yourgamesite.com:
1. Easy mode gameplay for 20 seconds
2. Hard mode gameplay for 20 seconds
3. The boss fight sequence for 30 seconds
Produces three separate named MP4 files plus a manifest.json.
record my game site for 30 seconds then analyze the recording
Pipes straight into the video-analyzer skill after capture completes.
Scenarios are JSON files that describe what the browser does during the recording. Claude can generate them from a plain English description, or you can write them directly.
{
"name": "basic_gameplay",
"description": "Start game and play for 30 seconds",
"steps": [
{ "action": "wait", "ms": 2000 },
{ "action": "click", "selector": "#start-button" },
{ "action": "wait", "ms": 1000 },
{ "action": "key", "key": "ArrowRight" },
{ "action": "hold_key", "key": "ArrowRight", "duration_ms": 1500 },
{ "action": "key_combo", "keys": ["Shift", "Space"] },
{ "action": "loop_start", "count": 5 },
{ "action": "key", "key": "Space" },
{ "action": "wait", "ms": 300 },
{ "action": "loop_end" },
{ "action": "screenshot", "label": "score_screen" }
]
}| Action | Parameters | Description |
|---|---|---|
wait |
ms |
Pause for N milliseconds |
click |
selector, button? |
Click a CSS selector or x/y coordinates |
dbl_click |
selector |
Double-click an element |
key |
key |
Press and release a single key |
key_combo |
keys[] |
Hold all keys simultaneously |
hold_key |
key, duration_ms |
Hold a key for a duration |
type |
text, delay_ms? |
Type text character by character |
mouse_move |
x, y |
Move cursor to absolute coordinates |
mouse_move_rel |
dx, dy |
Move cursor relative to current position |
mouse_down |
button? |
Press a mouse button |
mouse_up |
button? |
Release a mouse button |
drag |
from_x, from_y, to_x, to_y |
Click and drag |
scroll |
x, y |
Scroll by pixels (negative = up) |
screenshot |
label |
Save a still image mid-recording |
wait_for |
selector, timeout_ms? |
Wait until an element appears |
js |
script |
Execute JavaScript in the page |
navigate |
url |
Navigate to a different URL mid-session |
reload |
— | Reload the current page |
loop_start |
count |
Begin a repeated block |
loop_end |
— | End a repeated block |
ArrowUp ArrowDown ArrowLeft ArrowRight
Space Enter Escape Tab Backspace
Shift Control Alt Meta
w a s d q e r f (any letter)
0-9 F1-F12
Two pre-built scenarios are included:
scenarios/basic_play.json— wait for page load, click a start button, record gameplayscenarios/keyboard_gameplay.json— WASD/arrow key gameplay with jumps, loops, and a mid-session screenshot
| Platform | Display | Capture Method | Headless? |
|---|---|---|---|
| Windows | Native | Playwright (or gdigrab) | No — headed |
| Mac | Native | Playwright (or avfoundation) | No — headed |
| WSL with WSLg | WSLg X server | Playwright | No — headed via WSLg |
| WSL without WSLg | None / headless | Playwright headless | Yes |
| Linux VPS | Xvfb (auto-started) | Playwright | Headed inside Xvfb |
WebGL / Canvas game support by platform:
| Platform | WebGL Support | Notes |
|---|---|---|
| Windows | Full | Native GPU, best performance |
| Mac | Full | Native GPU |
| WSL + WSLg | Usually works | Shared Windows GPU |
| WSL headless | Limited | Software rendering only |
| Linux VPS | Limited | No GPU on most VPS instances |
For VPS/headless environments with WebGL games, the skill automatically adds software rendering flags (--use-gl=swiftshader).
See references/platform_notes.md for per-platform setup details and common issue fixes.
All recordings are saved as MP4 with this structure:
outputs/recordings/
├── gameplay_01.mp4 <- main recording
├── gameplay_02_hard_mode.mp4
├── manifest.json <- metadata for all recordings in the run
└── stills/ <- mid-scenario screenshots if captured
├── mid_game_01.png
└── ...
Quality control — default CRF 18 = high quality. To reduce file size:
| CRF Value | Quality | File Size |
|---|---|---|
| 18 | High (default) | Largest |
| 23 | Good | ~40% smaller |
| 28 | Acceptable | Smallest |
Pass --quality 23 to convert_output.py to re-encode at a different quality level.
The screen-recorder and video-analyzer skills are designed to work together. After recording:
record my game for 30 seconds then analyze the recording for quality and content
Or use convert_output.py directly with the --pipe-to-analyzer flag, which writes an analyzer_queue.json that the video-analyzer skill picks up automatically.
| Script | Purpose |
|---|---|
scripts/detect_platform.py |
Detect OS, display, ffmpeg, Playwright — outputs JSON |
scripts/setup_deps.py |
Install all missing dependencies for the detected platform |
scripts/record_session.py |
Main recorder — browser launch, navigation, input sim, video capture |
scripts/convert_output.py |
Convert WebM to MP4, package outputs, optional analyzer handoff |
scripts/multi_record.py |
Run multiple scenarios sequentially or in parallel |
Browser opens but game does not load
Add a longer wait in pre-actions: { "action": "wait", "ms": 5000 } or use wait_for to wait for a specific element like canvas.
WebGL game shows black screen on VPS/headless The skill adds software rendering flags automatically. Some games require actual GPU hardware — try on Windows or Mac, or a VPS with GPU passthrough.
Recording is choppy
Lower the viewport resolution (1280x720 to 854x480) or reduce FPS from 60 to 30.
Playwright cannot find Chromium
playwright install chromium
playwright install-deps chromium # Linux onlyWSL: no display error
Enable WSLg (update Windows + WSL) or the skill will fall back to headless automatically.
For VcXsrv: export DISPLAY=$(grep nameserver /etc/resolv.conf | awk '{print $2}'):0
Mac: screen recording permission denied System Settings → Privacy & Security → Screen Recording → enable Terminal (or iTerm).
MIT — see LICENSE