
Browser Recording
- 104 installs
- 325 repo stars
- Updated August 2, 2026
- athola/claude-night-market
Record Playwright test runs as video so you can debug flaky UI flows and share repros without re-running locally.
About
browser-recording is an agent skill for solo builders who want Playwright specs executed with session video turned on. It documents how to define a minimal defineConfig with video: 'on' and outputDir under ./test-results, then scale to a full recording profile with explicit video size, viewport, headless defaults, slowMo for visible steps, contextOptions.recordVideo, retries disabled, and a single worker so captures stay deterministic. You use it when UI or E2E tests need visual proof for CI failures, stakeholder review, or agent-driven regression checks—not when you only need trace logs or screenshots. For Prism’s ship journey, it sits beside other QA skills as a concrete integration pattern: configure once, run specs/demo.spec.ts or filtered tests, and collect artifacts under test-results and optional videos subfolders. Intermediate complexity assumes you already have Playwright installed and spec files; the skill does not replace test authoring, only reliable recorded execution.
- Minimal and full playwright.config.ts examples with video on and 1280×720 size
- Video modes: on, off, retain-on-failure, on-first-retry via mode and recordVideo context options
- Headless runs with optional slowMo (100ms) and workers: 1 for consistent recordings
- CLI patterns: npx playwright test, custom config path, and -g test name filtering
Browser Recording by the numbers
- 104 all-time installs (skills.sh)
- Ranked #985 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/athola/claude-night-market --skill browser-recordingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 104 |
|---|---|
| repo stars | ★ 325 |
| Last updated | August 2, 2026 |
| Repository | athola/claude-night-market ↗ |
What it does
Record Playwright test runs as video so you can debug flaky UI flows and share repros without re-running locally.
Files
Table of Contents
- Overview
- Required TodoWrite Items
- Process
- Step 1: Validate Playwright Installation
- Step 2: Check Spec File
- Step 3: Execute Recording
- Step 4: Convert to GIF
- Example Playwright Spec
- Playwright Configuration
- Exit Criteria
- Error Handling
- Output Locations
- See Also
Browser Recording Skill
Record browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.
When To Use
- Recording browser sessions with Playwright
- Creating web application demo recordings
When NOT To Use
- Terminal-only workflows - use scry:vhs-recording instead
- Static screenshots - use standard screenshot tools
Overview
This skill uses Playwright's built-in video recording to capture browser interactions. The workflow:
1. Validate Playwright installation 2. Execute a Playwright spec with video recording enabled 3. Retrieve the recorded video (WebM format) 4. Convert to GIF using the gif-generation skill
💡 Note: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for automated recording workflows, CI/CD, and cross-browser support. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.
Required TodoWrite Items
When invoking this skill, create todos for:
- [ ] Validate Playwright is installed and configured
- [ ] Check spec file exists at specified path
- [ ] Execute Playwright spec with video recording
- [ ] Locate and verify video output
- [ ] Convert video to GIF using gif-generation skillVerification: Run the command with --help flag to verify availability.
Process
Step 1: Validate Playwright Installation
Check that Playwright is available:
npx playwright --versionVerification: Run the command with --help flag to verify availability.
If not installed, the user should run:
npm install -D @playwright/test
npx playwright install chromiumVerification: Run pytest -v to verify tests pass.
Step 2: Check Spec File
Verify the Playwright spec file exists. Spec files should:
- Be located in a
specs/ortests/directory - Have
.spec.tsor.spec.jsextension - Include video configuration (see spec-execution module)
Step 3: Execute Recording
Run the spec with video enabled:
npx playwright test <spec-file> --config=playwright.config.tsVerification: Run pytest -v to verify tests pass.
The config must enable video recording. See the spec-execution module for configuration details.
Step 4: Convert to GIF
After recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:
**Verification:** Run the command with `--help` flag to verify availability.
Invoke scry:gif-generation with:
- input: <path-to-webm>
- output: <desired-gif-path>
- fps: 10 (recommended for tutorials)
- width: 800 (adjust based on content)Verification: Run the command with --help flag to verify availability.
Example Playwright Spec
import { test, expect } from '@playwright/test';
test('demo workflow', async ({ page }) => {
// Navigate to the application
await page.goto('http://localhost:3000');
// Wait for page to be ready
await page.waitForLoadState('networkidle');
// Perform demo actions
await page.click('button[data-testid="start"]');
await page.waitForTimeout(500); // Allow animation to complete
await page.fill('input[name="query"]', 'example search');
await page.waitForTimeout(300);
await page.click('button[type="submit"]');
await page.waitForSelector('.results');
// Final pause to show results
await page.waitForTimeout(1000);
});Verification: Run pytest -v to verify tests pass.
Playwright Configuration
Create or update playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: {
mode: 'on',
size: { width: 1280, height: 720 }
},
viewport: { width: 1280, height: 720 },
launchOptions: {
slowMo: 100 // Slow down actions for visibility
}
},
outputDir: './test-results',
});Verification: Run pytest -v to verify tests pass.
Exit Criteria
- Playwright spec executed successfully (exit code 0)
- Video file exists in output directory
- Video has non-zero file size
- GIF conversion completed (if requested)
Error Handling
| Error | Resolution |
|---|---|
| Playwright not installed | Run npm install -D @playwright/test |
| Browser not installed | Run npx playwright install chromium |
| Spec file not found | Verify path and file extension |
| Video not created | Check Playwright config has video enabled |
| Empty video file | validate spec actions complete before test ends |
Output Locations
Default output paths:
- Videos:
./test-results/<test-name>/video.webm - Screenshots:
./test-results/<test-name>/screenshot.png
Module Reference
- See
modules/spec-execution.mdfor detailed Playwright execution options - See
modules/video-capture.mdfor video format and quality settings
See Also
- scry:gif-generation: Convert video to optimized GIF
Spec Execution Module
Execute Playwright specs with video recording enabled.
Playwright Configuration for Video
Minimal Config
Create playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: 'on',
},
outputDir: './test-results',
});Full Recording Config
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './specs',
outputDir: './test-results',
use: {
// Video settings
video: {
mode: 'on', // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'
size: {
width: 1280,
height: 720
}
},
// Browser settings
viewport: { width: 1280, height: 720 },
headless: true,
// Slow down for visibility in recordings
launchOptions: {
slowMo: 100
},
// Browser context
contextOptions: {
recordVideo: {
dir: './test-results/videos',
size: { width: 1280, height: 720 }
}
}
},
// Disable retries for recording
retries: 0,
// Single worker for consistent recording
workers: 1,
});Running Specs
Basic Execution
npx playwright test specs/demo.spec.tsWith Custom Config
npx playwright test specs/demo.spec.ts --config=playwright.recording.config.tsCommon Options
# Run specific test by name
npx playwright test -g "demo workflow"
# Run in headed mode (visible browser)
npx playwright test --headed
# Use specific browser
npx playwright test --project=chromium
# Set timeout
npx playwright test --timeout=60000
# Output verbose logs
npx playwright test --debugVideo Output Paths
Playwright creates videos at:
<outputDir>/<test-file-name>-<browser>/<test-name>/video.webmExample:
test-results/demo-spec-ts-chromium/demo-workflow/video.webmProgrammatic Video Path
Access video path in test:
import { test, expect } from '@playwright/test';
test('demo', async ({ page }, testInfo) => {
// ... test actions ...
// After test, attach video path
const video = page.video();
if (video) {
const path = await video.path();
console.log('Video saved to:', path);
}
});Error Handling
Common Issues
Browser not installed:
npx playwright install chromiumTimeout errors:
// Increase action timeout
await page.click('button', { timeout: 10000 });
// Or set global timeout in config
use: {
actionTimeout: 10000,
}Video not created:
- validate
video: 'on'in config - Check test actually runs (not skipped)
- Verify outputDir is writable
Empty or corrupted video:
- Add
await page.waitForTimeout(500)before test ends - validate page has loaded:
await page.waitForLoadState('networkidle')
Exit Code Handling
npx playwright test specs/demo.spec.ts
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "Recording completed successfully"
# Find video file
VIDEO=$(find test-results -name "video.webm" -type f | head -1)
echo "Video: $VIDEO"
else
echo "Recording failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fiBest Practices for Recording Specs
1. Use explicit waits - Avoid flaky recordings
await page.waitForSelector('.element');
await page.waitForLoadState('networkidle');2. Add pauses for visibility - Give viewers time to see actions
await page.waitForTimeout(500);3. Use slowMo - Slow down all actions
launchOptions: { slowMo: 100 }4. Consistent viewport - Match video size to viewport
viewport: { width: 1280, height: 720 },
video: { size: { width: 1280, height: 720 } }5. Disable retries - One clean recording
retries: 0Video Capture Module
Video format options, quality settings, and post-processing for Playwright recordings.
Video Format
Playwright records video in WebM format with VP8 codec. This format:
- Has good compression
- Supports transparency (if needed)
- Works well with ffmpeg for conversion
- Is natively supported by most browsers
Resolution Settings
Common Resolutions
| Resolution | Use Case | Aspect Ratio |
|---|---|---|
| 1920x1080 | Full HD, detailed demos | 16:9 |
| 1280x720 | Standard tutorials | 16:9 |
| 1024x768 | Compact demos | 4:3 |
| 800x600 | Small GIF output | 4:3 |
Playwright Video Size Configuration
// In playwright.config.ts
use: {
video: {
mode: 'on',
size: { width: 1280, height: 720 }
},
viewport: { width: 1280, height: 720 }
}Important: Match video.size to viewport for best quality.
Per-Test Video Settings
import { test } from '@playwright/test';
test.use({
video: {
mode: 'on',
size: { width: 1920, height: 1080 }
},
viewport: { width: 1920, height: 1080 }
});
test('high-res demo', async ({ page }) => {
// Test runs at 1080p
});Quality Considerations
Frame Rate
Playwright records at approximately 25 fps. This is sufficient for UI demos.
Bitrate
WebM videos from Playwright use variable bitrate. Typical sizes:
- 720p, 30 seconds: 2-5 MB
- 1080p, 30 seconds: 5-10 MB
Minimizing File Size
1. Smaller viewport - Reduce dimensions 2. Shorter duration - Trim unnecessary pauses 3. Simple animations - Fewer visual changes = smaller file
Playwright Video Configuration in Tests
Enable Video for Specific Tests
import { test } from '@playwright/test';
// Enable video for this test file
test.describe.configure({ mode: 'serial' });
test.use({
video: 'on',
viewport: { width: 1280, height: 720 }
});
test('recorded demo', async ({ page }) => {
await page.goto('https://example.com');
await page.waitForTimeout(1000);
});Conditional Recording
import { test } from '@playwright/test';
const RECORD = process.env.RECORD === 'true';
test.use({
video: RECORD ? 'on' : 'off'
});
test('conditionally recorded', async ({ page }) => {
// Only records when RECORD=true
});Custom Video Directory
import { test } from '@playwright/test';
test.use({
contextOptions: {
recordVideo: {
dir: './custom-video-output',
size: { width: 1280, height: 720 }
}
}
});Post-Processing with ffmpeg
Convert WebM to MP4
ffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4Extract Specific Time Range
# Extract from 0:05 to 0:15
ffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webmChange Resolution
# Scale to 800px width, maintain aspect ratio
ffmpeg -i video.webm -vf "scale=800:-1" scaled.webmSpeed Up Video
# 2x speed
ffmpeg -i video.webm -filter:v "setpts=0.5*PTS" faster.webmAdd Padding/Borders
# Add 10px black border
ffmpeg -i video.webm -vf "pad=width+20:height+20:10:10:black" padded.webmCombine Multiple Videos
# Create file list
echo "file 'video1.webm'" > list.txt
echo "file 'video2.webm'" >> list.txt
# Concatenate
ffmpeg -f concat -safe 0 -i list.txt -c copy combined.webmConverting to GIF
For GIF conversion, use the scry:gif-generation skill which handles:
- Palette generation for optimal colors
- Frame rate reduction (10-15 fps typical)
- Width scaling
- Dithering for quality
Quick ffmpeg conversion (basic):
# Simple conversion (larger file, lower quality)
ffmpeg -i video.webm -vf "fps=10,scale=800:-1" output.gif
# Better quality with palette
ffmpeg -i video.webm -vf "fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gifTroubleshooting
Video is black or frozen
- validate page has visible content before recording starts
- Add
await page.waitForLoadState('domcontentloaded') - Check for CSS that hides content initially
Video cuts off early
- Test might be finishing before video flushes
- Add
await page.waitForTimeout(500)at end of test - validate
await page.close()is not called (Playwright handles cleanup)
Video too large
- Reduce resolution
- Shorten test duration
- Use post-processing to compress
Choppy playback
- Normal at high resolutions
- Consider reducing to 720p
- Final GIF will be smoother at lower fps