Pipeline Stages

Auto Zoom

Automatically zoom into user actions with smooth easing transitions.

The .autoZoom() stage detects user interactions from the Playwright trace and zooms into the relevant UI area. The viewer's attention is drawn to exactly where the action happens.

Basic usage

await Recast
  .from('./traces')
  .parse()
  .autoZoom()
  .render({ format: 'mp4' })
  .toFile('demo.mp4')

Auto-zoom from trace

Automatically zoom into input elements (fill/type actions) detected from the trace. The zoom window follows the actual action duration — zooms in when the user starts typing, zooms out when they move on.

.autoZoom({
  inputLevel: 1.4,    // Zoom level for fill/type actions
  clickLevel: 1.0,    // 1.0 = no zoom on clicks (default)
  centerBias: 0.3,    // Blend coordinates toward center (0-1)
})

Configuration options

OptionTypeDefaultDescription
inputLevelnumber1.4Zoom level for fill/type actions
clickLevelnumber1.0Zoom level for click actions
idleLevelnumber1.0Zoom level when no action is happening
centerBiasnumber0Blend zoom coordinates toward viewport center (0-1)
easingEasingSpec'ease-in-out'Easing function for zoom transitions
transitionMsnumber400Zoom in/out transition duration in ms

Easing options

Zoom transitions support several easing modes:

// Built-in presets
.autoZoom({ easing: 'linear' })
.autoZoom({ easing: 'ease-in' })
.autoZoom({ easing: 'ease-out' })
.autoZoom({ easing: 'ease-in-out' })  // default

// Cubic bezier
.autoZoom({ easing: { cubicBezier: [0.42, 0, 0.58, 1] } })

// Custom JS function
.autoZoom({ easing: { fn: t => t * t } })

Zoom-to-zoom panning

When two zoom targets are close together in time, the camera pans smoothly between them instead of zooming out and back in. This creates a natural follow-along feel.

Zoom from report data

Apply zoom coordinates from an external source:

const reportSteps = [
  { zoom: null },                             // Step 1: no zoom
  { zoom: { x: 0.5, y: 0.8, level: 1.4 } },  // Step 2: zoom to input area
  { zoom: null },                             // Step 3: no zoom
  { zoom: { x: 0.78, y: 0.45, level: 1.3 } }, // Step 4: zoom to sidebar
]

await Recast
  .from('./traces')
  .parse()
  .subtitlesFromSrt('./narration.srt')
  .enrichZoomFromReport(reportSteps)
  .render({ format: 'mp4' })
  .toFile('demo.mp4')

Zoom from step helpers

Capture zoom coordinates during test execution using the zoom() helper:

import { zoom } from 'playwright-recast'

When('the user opens the sidebar', async ({ page }) => {
  const sidebar = page.locator('.sidebar-panel')
  await zoom(sidebar, 1.3)
  await sidebar.click()
})

The helper records the element's bounding box as a Playwright annotation. Apply these coordinates with .enrichZoomFromReport().

Zoom coordinates

All zoom coordinates use viewport-relative fractions (0.0-1.0):

FieldDescriptionDefault
xCenter X (0 = left, 1 = right)0.5
yCenter Y (0 = top, 1 = bottom)0.5
levelZoom level (1.0 = no zoom, 2.0 = 2x)1.0

The renderer applies zoom by cropping the video to (width/level x height/level) centered at (x, y), then scaling back to the output resolution.

Tips

  • Use centerBias to prevent zoom targets near edges from cropping important content. A value of 0.3 blends 30% toward the center.
  • Cursor overlay and click effects are applied before zoom cropping, so overlay coordinates stay accurate during zoomed segments.
  • For fill actions that lack cursor coordinates (programmatic fills), auto-zoom falls back to viewport center.

On this page