Creating application demo videos with Playwright

Creating application demo videos with Playwright

When I recently built SyntaxRush, I wanted to create a polished demo video to showcase the gameplay and features.

My first thought was the traditional route:

  • Screen record
  • Edit clips
  • Overlay captions
  • Add logos
  • Add background audio
  • Export everything

In short… a lot of manual work.

Then I had a brainwave while running automated tests on another project — Playwright.

If Playwright can automate browsers, capture screenshots, and simulate user journeys… why not use it to generate demo videos automatically?

That’s exactly what I did.

Check out the repo on Github

TL;DR - I used Playwright to automate demo video generation, capture real user interactions, and combine everything with FFmpeg into fully branded marketing videos.


The Idea

Instead of screen recording manually, I:

  1. Built a Playwright spec file
  2. Mocked game states
  3. Captured videos at each stage
  4. Rendered slides with captions, logos and styling
  5. Used FFmpeg to stitch them into a video
  6. Added background audio and fade-out

The result:

  • Smooth demo video
  • Perfectly aligned captions
  • Consistent branding
  • No manual editing
  • Fully reproducible

Step 1 - Using Playwright to Capture Application States

Rather than recording a live session, I defined state-based scenes and captured them individually.

Each slide contains:

  • Title
  • Subtitle
  • Feature bullet points
  • Desktop screenshot
  • Mobile screenshot

From the spec file:

const states: StateDefinition[] = [
  {
    key: "01-lobby",
    title: "Lobby setup in seconds",
    subtitle: "Host and players join fast with teams and room status visible immediately.",
    features: [
      "Room code and share link for quick joins",
      "Team A & B rosters with live presence",
      "Host controls when the game starts",
    ],
  }
]

Each state seeds the application and then Playwright captures both desktop and mobile views.

The spec programmatically:

  • Starts browser
  • Injects session
  • Navigates to room
  • Waits for UI
  • Captes screenshot

This allows fully deterministic demo scenes.


Step 2 - Rendering Styled Slides with HTML Canvas

Instead of stitching raw screenshots, I render a full branded slide using Playwright itself.

The spec dynamically generates an HTML layout including:

  • Gradient background
  • Title & subtitle
  • Feature list
  • Desktop mock frame
  • Mobile phone frame
  • Logos
  • Typography
  • Spacing

Playwright then screen records the composed slide, not just the app.

This means:

  • Perfect layout
  • No video editor required
  • Consistent branding
  • Easy updates

Each slide is rendered at 1920×1080:

const context = await browser.newContext({
  viewport: { width: 1920, height: 1080 },
});

Step 3 - Generating a Video Manifest

Once slides are created, the spec builds an FFmpeg concat manifest.

Each slide gets a duration:

manifestLines.push(`file '${slidePath}'`);
manifestLines.push(`duration ${SLIDE_DURATION_SECONDS}`);

This allows precise timing without manual editing.


Step 4 - Rendering the Video with FFmpeg

After Playwright captures the slides, a Node script uses FFmpeg to generate the final video.

The script:

  • Reads slide durations
  • Calculates total runtime
  • Trims audio to match
  • Fades audio out at end
  • Exports MP4

Example from the render script:

const filter = `[1:a]atrim=start=19,asetpts=PTS-STARTPTS,atrim=duration=${total.toFixed(4)},afade=t=out:st=${fadeStart}:d=${effectiveFade}[a]`;

This trims the soundtrack, aligns it to slide duration, and fades out smoothly.

FFmpeg then combines everything:

"-c:v", "libx264",
"-crf", "20",
"-c:a", "aac",
"-movflags", "+faststart",

Result:

  • High quality MP4
  • Optimised for web
  • Smooth playback
  • Fast start for social platforms

Step 5 - npm Scripts for Automation

Everything is wrapped in simple npm scripts:

"demo:video:capture": "playwright test e2e/demo-video.spec.ts --project=chromium",
"demo:video:render": "node scripts/render-demo-video.mjs",
"demo:video": "npm run demo:video:capture && npm run demo:video:render",
"demo:video:mobile:capture": "PLAYWRIGHT_CHROMIUM_USE_HEADLESS_SHELL=0 playwright test e2e/demo-video-mobile.spec.ts --project=chromium",
"demo:video:mobile:render": "node scripts/render-demo-video.mjs --mobile",
"demo:video:mobile": "npm run demo:video:mobile:capture && npm run demo:video:mobile:render"

Now generating a demo video is literally:

npm run demo:video

or

npm run demo:video:mobile


Two Video Variants

This approach made it easy to generate:

Desktop + Mobile Demo

  • Full feature slides
  • Rich captions
  • Logos
  • Perfect for website

Social Media Reel Version

  • Portrait format
  • Less text
  • Faster pacing
  • Instagram / TikTok ready

No manual editing required - just different specs.


Why This Approach Is Powerful

This workflow gives you:

  • Fully automated demo videos
  • Pixel-perfect consistency
  • Repeatable builds
  • Version-controlled demos
  • No video editing software
  • Easy localisation
  • Easy feature updates

Every time SyntaxRush changes, I can regenerate the demo video in seconds.


When This Is Useful

This technique works great for:

  • SaaS product demos
  • App walkthroughs
  • Feature announcements
  • Landing page videos
  • Social media reels
  • Release previews
  • Documentation videos

Final Thoughts

Playwright isn’t just for testing.

It can be used as a powerful content generation tool.

By combining:

  • Playwright
  • HTML layouts
  • Mocked application state
  • FFmpeg
  • npm scripts

You can build a fully automated demo video pipeline.

No screen recording.
No editing timeline.
No manual work.

Just:

npm run demo:video

…and your marketing video is ready.


If you’re building apps and want consistent demo videos, this approach is a huge time saver.