A SuiteCut walkthrough

import { record } from 'suitecut/playwright'

await record('product tour', async ({
  page,
  suitecut,
}) => {
  await page.goto('https://suitecut.aakashreddy.com')
  const docs = page.getByRole('link', {
    name: 'Docs', exact: true,
  })

  const speech = {
    provider: 'kokoro', voice: 'af_heart',
  } as const

Fully rendered walkthroughs

Play the video, or hover over a neighboring snippet to jump there.

SuiteCut 2.0 · Embedded CEF is now the default. Record, narrate, and stream with a native browser.Set up 2.0

More control over the recording.

Browser actions

hover · click · type · scrollTo · scrollTop

Move the recorded cursor, click elements, type character by character, and scroll the page using native CSS locators or the explicit Playwright backend.

Presentation and timing

narrate · highlight · zoom · hold · checkpoint

Add speech and captions, highlight elements, crop the video around a locator, hold a view, and capture named checkpoints.

Pages and setup

selectPage · defineSuiteCut

Select registered native sources for later events. Reuse browser, capture, and output options across recordings.

Playwright Test

suitecut/test · suitecut/reporter

Import test and expect, use the suitecut fixture, and configure the reporter to collect recording artifacts into a manifest.

Speech plugins

audioPluginReference · defineSuiteCutAudioPlugin · encodePcm16Wav

Register a speech provider or implement your own synthesis plugin with helpers exported by suitecut/audio-plugin.

Video output

renderSuiteCut · suitecut render

Render a recorded attempt through the API or CLI. Choose MP4, WebM, MOV, or MKV, with output size, frame rate, and codec settings.

Reuse your capture settings.

defineSuiteCut() now uses embedded CEF. Set native dimensions and a target frame rate, then record with narration and optional page audio. Build the CEF executable and set SUITECUT_NATIVE_EXECUTABLE first. Native support is verified on macOS Apple Silicon. Existing Playwright flows use suitecut/playwright, including the walkthrough above.

import { defineSuiteCut } from 'suitecut'

export const record = defineSuiteCut({
  native: { width: 1920, height: 1080, framesPerSecond: 60 },
  capture: { audio: true },
  output: { directory: '.suitecut/recordings' },
})

await record('embedded browser tour', async ({ page, suitecut }) => {
  await page.goto('https://example.com')
  await suitecut.highlight(page.locator('h1'))
  await suitecut.checkpoint('Opening screen')
})

Stream a browser page live.

Launch an embedded browser and use createBroadcast() to publish H.264 video and AAC audio to an RTMP or RTMPS ingest URL. Stop the broadcast and close the source when done.

import { launchBrowser, createBroadcast } from 'suitecut'

const url = process.env.SUITECUT_STREAM_URL
if (!url) throw new Error('Set SUITECUT_STREAM_URL')
const source = await launchBrowser()
let broadcast
try {
  await source.navigate('https://example.com')
  broadcast = await createBroadcast({ source, stream: { url, audio: true } })
  await broadcast.ready()
  await Promise.race([
    source.failure, broadcast.failure,
    new Promise(resolve => setTimeout(resolve, 30_000)),
  ])
} finally {
  await broadcast?.stop()
  await source.close()
}

Streaming saves no source video for later rendering. Audio defaults to silence.stream.audio: true captures page sound directly from CEF. Microphone input and synthesized narration are not mixed into the stream.