Just published playwright-recorder-plus on npm. Sharing in case anyone has been hitting the same pain.
The problem. Playwright's built-in recordVideo is hardcoded to -c:v vp8 -b:v 1M -deadline realtime -speed 8 -threads 1. The maintainers have declined to expose tuning options multiple times (#8683, #12056, #17217, #31424). For CI test artifacts the defaults are fine; for tutorial videos, demo recordings, and bug repros the output looks crushed and there's no way to fix it without forking Playwright.
What this does. Wraps Playwright 1.59+'s public page.screencast API and pipes the JPEG frames into a separately-shipped ffmpeg you control. So you get:
- Configurable encoder — H.264 default (mp4), VP9 via the
webpreset, AV1 / x265 / anything viaffmpegArgs pause()/resume(),autoStart: false,crop,fps- Inline audio scheduling —
recorder.audio(path, { offset })for click sounds, narration, etc.; muxed in by ffmpeg in a second pass - Multi-page contexts — auto-attaches popups via
attachRecorderForContext - Wall-clock-faithful timing — frame numbering anchored to
recorder.start()(not the first CDP frame), with same-slot dedup and tail padding, so the encoded video duration matches real time even when the page is static after start
Architecture. Fixed two-pass: first pass is locked at H.264 ultrafast so capture cannot fall behind realtime; second pass transcodes to your target codec and muxes audio in the background. recorder.stop() returns as soon as the first pass flushes; await recorder.finalized to wait for the final file.
Cross-browser smoke tests for chromium / firefox / webkit. MIT-licensed. Ships its own ffmpeg via ffmpeg-static, no system install required.
Feedback / issues / PRs welcome.