Skill: athola/nm-scry-browser-recording (version 1.0.2)

--- name: browser-recording description: Record browser sessions using Playwright for web UI tutorials, converts version: 1.9.5 triggers: - playwright - browser - recording - video - web - tutorial metadata: {"openclaw": {"homepage": "https://github.com/athola/claude-night-market/tree/master/plugins/scry", "emoji": "\ud83e\udd9e", "requires": {"config": ["night-market.scry:gif-generation"]}}} source: claude-night-market source_plugin: scry --- > **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin. ## Table of Contents - [Overview](#overview) - [Required TodoWrite Items](#required-todowrite-items) - [Process](#process) - [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation) - [Step 2: Check Spec File](#step-2:-check-spec-file) - [Step 3: Execute Recording](#step-3:-execute-recording) - [Step 4: Convert to GIF](#step-4:-convert-to-gif) - [Example Playwright Spec](#example-playwright-spec) - [Playwright Configuration](#playwright-configuration) - [Exit Criteria](#exit-criteria) - [Error Handling](#error-handling) - [Output Locations](#output-locations) - [See Also](#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 skill ``` **Verification:** Run the command with `--help` flag to verify availability. ## Process ### Step 1: Validate Playwright Installation Check that Playwright is available: ```bash npx playwright --version ``` **Verification:** Run the command with `--help` flag to verify availability. If not installed, the user should run: ```bash npm install -D @playwright/test npx playwright install chromium ``` **Verification:** 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/` or `tests/` directory - Have `.spec.ts` or `.spec.js` extension - Include video configuration (see spec-execution module) ### Step 3: Execute Recording Run the spec with video enabled: ```bash npx playwright test <spec-file> --config=playwright.config.ts ``` **Verification:** 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 ```typescript 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`: ```typescript 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.md` for detailed Playwright execution options - See `modules/video-capture.md` for video format and quality settings ## See Also - scry:gif-generation: Convert video to optimized GIF ## Troubleshooting ### Common Issues **Command not found** Ensure all dependencies are installed and in PATH **Permission errors** Check file permissions and run with appropriate privileges **Unexpected behavior** Enable verbose logging with `--verbose` flag

path: modules/spec-execution.md
content: # Spec Execution Module

Execute Playwright specs with video recording enabled.

## Playwright Configuration for Video

### Minimal Config

Create `playwright.config.ts`:

```typescript
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    video: 'on',
  },
  outputDir: './test-results',
});
```

### Full Recording Config

```typescript
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

```bash
npx playwright test specs/demo.spec.ts
```

### With Custom Config

```bash
npx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts
```

### Common Options

```bash
# 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 --debug
```

## Video Output Paths

Playwright creates videos at:
```
<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm
```

Example:
```
test-results/demo-spec-ts-chromium/demo-workflow/video.webm
```

### Programmatic Video Path

Access video path in test:

```typescript
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:**
```bash
npx playwright install chromium
```

**Timeout errors:**
```typescript
// 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

```bash
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
fi
```

## Best Practices for Recording Specs

1. **Use explicit waits** - Avoid flaky recordings
   ```typescript
   await page.waitForSelector('.element');
   await page.waitForLoadState('networkidle');
   ```

2. **Add pauses for visibility** - Give viewers time to see actions
   ```typescript
   await page.waitForTimeout(500);
   ```

3. **Use slowMo** - Slow down all actions
   ```typescript
   launchOptions: { slowMo: 100 }
   ```

4. **Consistent viewport** - Match video size to viewport
   ```typescript
   viewport: { width: 1280, height: 720 },
   video: { size: { width: 1280, height: 720 } }
   ```

5. **Disable retries** - One clean recording
   ```typescript
   retries: 0
   ```


path: modules/video-capture.md
content: # Video 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

```typescript
// 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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```bash
ffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4
```

### Extract Specific Time Range

```bash
# Extract from 0:05 to 0:15
ffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm
```

### Change Resolution

```bash
# Scale to 800px width, maintain aspect ratio
ffmpeg -i video.webm -vf "scale=800:-1" scaled.webm
```

### Speed Up Video

```bash
# 2x speed
ffmpeg -i video.webm -filter:v "setpts=0.5*PTS" faster.webm
```

### Add Padding/Borders

```bash
# Add 10px black border
ffmpeg -i video.webm -vf "pad=width+20:height+20:10:10:black" padded.webm
```

### Combine Multiple Videos

```bash
# 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.webm
```

## Converting 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):

```bash
# 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.gif
```

## Troubleshooting

### 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


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)