Examples

These code blocks are imported from runnable files in this repository.

Playwright script

examples/playwright.tsuses the explicit Playwright backend. The 2.0 native default is covered in the getting-started guide. It uses defineSuiteCut() without Playwright Test, a reporter, fixtures, or a Playwright configuration file. It records a local page, uses SuiteCut's cursor and highlight, captures a checkpoint, and prints the manifest path.

TypeScript
import { defineSuiteCut } from 'suitecut/playwright'

const record = defineSuiteCut({
  browserName: 'chromium',
  launch: { headless: true },
  context: { colorScheme: 'light' },
  capture: {
    viewport: { width: 1280, height: 720 },
    size: { width: 1280, height: 720 },
    framesPerSecond: 30,
    quality: 90,
  },
  output: {
    directory: '.suitecut/playwright-example',
    manifestPath: '.suitecut/playwright-example.json',
    pathKind: 'manifest-relative',
  },
})

const result = await record('plain Playwright recording', async ({ page, suitecut }) => {
  await page.setContent(`
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>SuiteCut plain Playwright example</title>
        <style>
          body { font: 18px system-ui; margin: 0; padding: 64px; }
          main { max-width: 720px; margin: 0 auto; }
          button { font: inherit; padding: 12px 18px; }
          #status { margin-top: 24px; }
        </style>
      </head>
      <body>
        <main>
          <h1>Record a browser flow</h1>
          <p>This script owns Playwright's browser lifecycle. There is no test runner.</p>
          <button type="button">Create report</button>
          <p id="status" aria-live="polite">No report yet.</p>
          <script>
            document.querySelector('button').addEventListener('click', () => {
              document.querySelector('#status').textContent = 'Report created.'
            })
          </script>
        </main>
      </body>
    </html>
  `)

  const create = page.getByRole('button', { name: 'Create report' })
  await suitecut.highlight(create, { durationMs: 700 })
  await suitecut.click(create)
  await suitecut.hold(400)
  await suitecut.checkpoint('Report created')
})

console.log(`Manifest: ${result.manifestPath}`)
Terminal
npm run build
node --experimental-strip-types examples/playwright.ts

suitecut render \
  --manifest .suitecut/playwright-example.json \
  --output .suitecut/videos/playwright-example.mp4

OpenAI Status livestream

examples/playwright/openai-status-livestream.ts publishes the public OpenAI Status page at 1080p with tab audio. It highlights the system status, stays live untilCtrl+C, and reconnects after an ingest interruption.

TypeScript
import { record } from 'suitecut/playwright'

const streamUrl = process.env.SUITECUT_STREAM_URL
if (!streamUrl) {
  throw new Error('Set SUITECUT_STREAM_URL to your full RTMP or RTMPS publish URL.')
}

const statusUrl = process.env.SUITECUT_STATUS_URL ?? 'https://status.openai.com/'
const headed = process.env.SUITECUT_HEADED === '1'
const controller = new AbortController()
const stop = (): void => controller.abort()
process.once('SIGINT', stop)
process.once('SIGTERM', stop)

try {
  await record(
    'OpenAI Status livestream',
    async ({ page, suitecut, signal }) => {
      await page.goto(statusUrl, { waitUntil: 'domcontentloaded' })
      await suitecut.hold(2_000)

      const systemStatus = page.getByRole('heading', { name: 'System status' })
      if ((await systemStatus.count()) > 0) {
        await suitecut.scrollTo(systemStatus, { behavior: 'smooth', settleMs: 800 })
        await suitecut.highlight(systemStatus, { durationMs: 1_200 })
      }

      await new Promise<void>((resolve) => {
        if (signal?.aborted === true) resolve()
        else signal?.addEventListener('abort', () => resolve(), { once: true })
      })
    },
    {
      launch: { headless: !headed },
      capture: {
        viewport: { width: 1920, height: 1080 },
        framesPerSecond: 30,
        stream: {
          url: streamUrl,
          audio: true,
          bitrateKbps: 4500,
          onDiagnostic: (event) => console.log(event.event, event.bottleneck),
          reconnect: { initialDelayMs: 1_000, maxDelayMs: 30_000, maxAttempts: 0 },
        },
      },
      signal: controller.signal,
    },
  )
} catch (error) {
  if (!controller.signal.aborted) throw error
} finally {
  process.off('SIGINT', stop)
  process.off('SIGTERM', stop)
}
Terminal
SUITECUT_STREAM_URL='rtmps://your-ingest/app/your-stream-key' \
pnpm example:livestream:status

Playwright Test in three browsers

examples/browser-support.spec.ts is the focused browser matrix. The repository runs the same recording in Chromium, Firefox, and WebKit, then verifies every attempt, source-video artifact, event set, dimension, frame rate, and duration.

TypeScript
import { expect, test } from 'suitecut/test'

test.use({
  suitecutCapture: {
    viewport: { width: 960, height: 540 },
    framesPerSecond: 30,
    quality: 85,
  },
})

test('records a SuiteCut flow in every supported browser', async ({ page, suitecut }) => {
  await page.setContent(`
    <main style="display:grid;place-content:center;min-height:100vh;font:20px system-ui">
      <button type="button" style="padding:16px 24px">Create report</button>
      <p role="status">Waiting</p>
    </main>
    <script>
      document.querySelector('button').addEventListener('click', () => {
        document.querySelector('[role=status]').textContent = 'Report created'
      })
    </script>
  `)

  const createReport = page.getByRole('button', { name: 'Create report' })
  await suitecut.checkpoint('Browser ready')
  await suitecut.highlight(createReport, { durationMs: 450, label: 'Create report' })
  await suitecut.click(createReport, {
    moveDurationMs: 120,
    settleMs: 80,
    waitForAnimations: false,
  })
  await expect(page.getByRole('status')).toHaveText('Report created')
  await suitecut.hold(200)
})
Terminal
npm run test:browsers

More repository examples

Select a test or retry

Terminal
suitecut render \
  --manifest .suitecut/latest-run.json \
  --test-id <playwright-test-id> \
  --retry 0 \
  --output .suitecut/videos/tour.webm \
  --container webm

Choose a container and encoders

Terminal
suitecut render \
  --manifest .suitecut/latest-run.json \
  --output .suitecut/videos/tour.mov \
  --container mov \
  --video-codec prores_ks \
  --audio-codec pcm_s24le \
  --pixel-format yuv422p10le

SuiteCut infers MP4, WebM, MOV, or MKV from the output extension. You can select any compatible encoder in the installed FFmpeg build. --color-range controls sample range, not the video or audio codec.