playwright-capture
v1.0.0
Published
Playwright virtual-time recording library - frame-accurate video capture using CDP HeadlessExperimental.beginFrame
Maintainers
Readme
playwright-capture
Playwright virtual-time recording library. Frame-accurate video capture using CDP HeadlessExperimental.beginFrame.
Features
- Execution time and video duration are independent (e.g., 7s execution produces a 15s video)
- No frame drops, no timing jitter
- Deterministic output from the same input
Prerequisites
- ffmpeg installed on the system
- Linux (macOS requires Docker — see below)
- Node.js 18+
Install
npm install playwright-captureUsage
With Playwright Fixture (recommended)
import { test, expect } from "playwright-capture";
test("recording test", async ({ virtualPage, virtualRecorder }) => {
await virtualPage.goto("https://example.com");
await virtualRecorder.recordDuration(3000); // Record for 3 seconds
// Wrap Playwright actions with pumpFrames()
await virtualRecorder.pumpFrames(async () => {
await virtualPage.click("button");
});
await virtualRecorder.recordDuration(3000); // Record 3 more seconds
});Using VirtualRecorder directly
import { VirtualRecorder } from "playwright-capture";
const recorder = new VirtualRecorder({
outputPath: "recordings/output.mp4",
fps: 30,
viewport: { width: 1280, height: 720 },
});
const { page } = await recorder.launch();
await page.goto("https://example.com");
await recorder.recordDuration(3000);
await recorder.stop();macOS: Docker usage
HeadlessExperimental.beginFrame does not work on macOS. Use Docker instead.
Get the Dockerfile from the repository and build:
curl -o Dockerfile https://raw.githubusercontent.com/bluegreenhq/playwright-capture/main/Dockerfile
docker build -t playwright-capture .
docker run --rm -v $(pwd)/test-results:/app/test-results playwright-capture npx playwright testLimitations
- Chromium only (Firefox and WebKit are not supported)
- Not available on macOS without Docker
HeadlessExperimentalis an experimental Chrome DevTools Protocol API- Playwright actions (click, press, etc.) must be wrapped in
pumpFrames()because the browser does not automatically render frames in beginFrame mode
