# Playwright Record Mp4

> Use when running Playwright browser automation and needing to produce an MP4 video for tickets, bug reports, or evidence. Covers video recording config, ffmpeg detection, npx fallback install, and .webm to MP4 conversion.

- **Type:** Skill
- **Install:** `agentstack add skill-tixuz-playwright-record-mp4-playwright-record-mp4`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [tixuz](https://agentstack.voostack.com/s/tixuz)
- **Installs:** 0
- **Category:** [Web & Browser](https://agentstack.voostack.com/c/web-and-browser)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [tixuz](https://github.com/tixuz)
- **Source:** https://github.com/tixuz/playwright-record-mp4

## Install

```sh
agentstack add skill-tixuz-playwright-record-mp4-playwright-record-mp4
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Playwright Record to MP4

## Overview
Configure Playwright to record `.webm` video, run the test/script, then detect ffmpeg (install via npx if missing) and convert to MP4 with good compression.

## Output Directory — Always Confirm Before Writing

**Before generating any script, ask the user:**

> "Should the video output directory be relative to your **current working directory**, or do you want an absolute path?"

- Default suggestion: `./videos//` (relative to CWD where the skill is invoked)
- Never silently use `/tmp` or any absolute path — the user may not find the file
- If the user specifies a path like `/tmp/foo`, confirm: "I'll write to `/tmp/foo` — is that correct?"

## Output File Naming — Auto-increment if Exists

When writing the MP4, never overwrite an existing file. Use this pattern:

```js
import { existsSync } from 'fs';
import { resolve } from 'path';

let mp4 = resolve(OUTPUT_DIR, `${NAME}.mp4`);
if (existsSync(mp4)) {
    let i = 1;
    do { mp4 = resolve(OUTPUT_DIR, `${NAME}_${String(i).padStart(2, '0')}.mp4`); i++; }
    while (existsSync(mp4));
}
// result: name.mp4 → name_01.mp4 → name_02.mp4 ...
```

## Quick Reference

| Step | What |
|------|------|
| 1 | **Confirm output dir** with user (relative to CWD by default) |
| 2 | Add `recordVideo` to Playwright context |
| 3 | Run test — `.webm` lands in output dir |
| 4 | Check ffmpeg in PATH; use `ffmpeg-static` if missing |
| 5 | Convert `.webm` → `.mp4` (H.264, CRF 23), auto-increment name if exists |

## Step 1 — Playwright Video Config

**Script (one-off recording):**
```ts
import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
    recordVideo: { dir: 'videos/', size: { width: 1280, height: 720 } },
    ignoreHTTPSErrors: true,
});
const page = await context.newPage();

// --- your steps here ---

await context.close(); // must close context to flush video to disk
await browser.close();
```

**Test runner (`playwright.config.ts`):**
```ts
export default {
    use: {
        video: 'on',             // or 'retain-on-failure'
        ignoreHTTPSErrors: true,
    },
    outputDir: 'test-results/',
};
```

## Step 2 — Check ffmpeg & Convert (Shell)

Use this script after the test completes. It auto-installs via npm if ffmpeg is not on PATH.

```bash
#!/usr/bin/env bash
# Usage: ./convert.sh videos/myrecording.webm

INPUT="$1"
OUTPUT="${INPUT%.webm}.mp4"

if command -v ffmpeg &>/dev/null; then
    FFMPEG="ffmpeg"
else
    echo "ffmpeg not found — installing ffmpeg-static via npm..."
    npm install --silent ffmpeg-static
    FFMPEG=$(node -e "process.stdout.write(require('ffmpeg-static'))")
fi

"$FFMPEG" -i "$INPUT" \
    -c:v libx264 \
    -crf 23 \
    -preset fast \
    -c:a aac \
    "$OUTPUT" \
&& echo "Done: $OUTPUT"
```

Save as `~/.claude/skills/playwright-record-mp4/convert.sh` and `chmod +x` it.

## Step 3 — One-liner (if ffmpeg already installed)

```bash
ffmpeg -i test-results/video.webm -c:v libx264 -crf 23 -preset fast output.mp4
```

## After Conversion — Always Report the Output Location

After the MP4 is created, output this to the user:

```
✓ Converted:  ()
You can see all .webm and .mp4 files in this directory:
  file://

🤖 This session used ~N,000 tokens and saved you ~M minutes vs doing it manually.
```

- Use an absolute path so the `file://` link is clickable in the terminal/IDE
- List both `.webm` (raw Playwright output) and `.mp4` (converted) so the user knows both exist
- If the terminal supports it, the `file://` URI makes the folder openable with one click

**Token/time-saved calculation (Claude reports this, not the script):**
- Estimate N = approximate total tokens used in this session (visible in your context counter, or estimate ~3,000 for a simple recording session)
- M = round(N / 1000 × 3) — rough heuristic: 1,000 tokens ≈ 3 min of manual work
- Example: 6,000 tokens → "saved you ~18 minutes"

Example full output:
```
✓ Converted: /Users/jane/project/videos/test13/demo_server_test.mp4 (639K)
You can see all .webm and .mp4 files in this directory:
  file:///Users/jane/project/videos/test13/

🤖 This session used ~6,000 tokens and saved you ~18 minutes vs doing it manually.
```

In the Node.js script, emit this after conversion:
```js
const absDir = resolve(OUTPUT_DIR);
const absMP4 = resolve(mp4);
console.log(`\n✓ Converted: ${absMP4} (${size})`);
console.log(`You can see all .webm and .mp4 files in this directory:`);
console.log(`  file://${absDir}`);
// Claude adds the token/time-saved line above the script output
```

## CRF Guide (quality vs size)

| CRF | Quality | Use for |
|-----|---------|---------|
| 18 | Near-lossless | Archive |
| 23 | Good (default) | Tickets, Jira |
| 28 | Smaller file | Quick shares |

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Can't find the output file | Always confirm output dir with user upfront — never silently use `/tmp` or hidden paths |
| MP4 silently overwrites previous recording | Use auto-increment pattern: `name.mp4` → `name_01.mp4` → `name_02.mp4` |
| Video file is 0 bytes | Must call `context.close()` before `browser.close()` — video is flushed on context close |
| `ffmpeg-static` not found | Run `npm install ffmpeg-static` in the project root first, then the script picks it up |
| Video doesn't record in test runner | Ensure `outputDir` is set in config; video only saves when test completes |
| `headless: true` records blank video on some systems | Use `headless: false` for reliable recording |

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [tixuz](https://github.com/tixuz)
- **Source:** [tixuz/playwright-record-mp4](https://github.com/tixuz/playwright-record-mp4)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-tixuz-playwright-record-mp4-playwright-record-mp4
- Seller: https://agentstack.voostack.com/s/tixuz
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
