Documentation / Getting startedView source ↗

Getting started

SuiteCut 2.0 records and streams with an embedded Chromium browser powered by CEF. The native beta is now the default suitecut API. Record a flow with narration, captions, page audio, and checkpoints, then render its saved manifest into a video.

Requirements

  • Node.js 22 or newer.
  • macOS Apple Silicon for the verified native CEF build.
  • CMake 3.21+, Ninja, a C++20 compiler, and the pinned CEF and libyuv SDKs.
  • FFmpeg and FFprobe, installed with suitecut install or available on PATH.

Linux native builds are unverified. Windows native packaging is not implemented. Use suitecut/playwright for existing Chromium, Firefox, and WebKit flows on those platforms.

Install

Terminal
npm install https://github.com/skyaara/suitecut/releases/download/v2.0.0/suitecut-2.0.0.tgz
npx suitecut install
npx suitecut doctor

Install the 2.0 package from the GitHub release asset above. The package contains the native browser source and checksum pins, but no compiled CEF browser. Follow the CEF build instructions to obtain and verify the pinned dependencies and compile the complete browser bundle. Then set its executable path:

Terminal
export SUITECUT_NATIVE_EXECUTABLE="/absolute/path/to/suitecut-browser.app/Contents/MacOS/suitecut-browser"

Keep the complete .app bundle together. You can also passnative.executablePath per recording. A missing browser is an error; SuiteCut never silently switches backends. suitecut install installs checksum-pinned media tools, not CEF. Imports and recording calls do not download software.

Record a flow

Save this as tour.ts. The root recorder launches and closes its primary native browser, including after callback errors. Native defaults are 1920 × 1080 at 60 FPS with I420 capture. Page audio is off by default; the example enables it with capture.audio: true.

TypeScript
import { defineSuiteCut, renderSuiteCut } from 'suitecut'

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

const result = await record('Embedded browser tour', async ({ page, suitecut }) => {
  await page.goto('https://example.com')
  await suitecut.highlight(page.locator('h1'))
  await suitecut.narrate('Welcome to SuiteCut 2.0.')
  await suitecut.checkpoint('Opening screen')
})

await renderSuiteCut({
  manifestPath: result.manifestPath,
  outputPath: '.suitecut/tour.mp4',
})

Native locators use strict CSS selectors in the main document. Await application readiness explicitly. Role/text locators, iframe traversal, popup flows, and custom Playwright setup require the explicit Playwright backend.

Run and render

Terminal
node --experimental-strip-types tour.ts

# Render the saved run again with different output settings:
npx suitecut render \
  --manifest .suitecut/tour.json \
  --output .suitecut/tour-4k.mp4 \
  --width 3840 --height 2160 --fps 60

Rendering is separate from browser capture. The manifest keeps authored timing, page selection, narration, and checkpoints. Recorded page audio follows source selection and mixes with narration. For live output, see Live streaming.

Migrating from 1.x and using Playwright Test

Native beta scripts can change suitecut/beta to suitecut. The beta entry point remains an alias. Existing Playwright scripts should change their import:

TypeScript
import { defineSuiteCut, record } from 'suitecut/playwright'
// Existing Playwright launch, context, capture, and setup options still work.

Or keep root record and pass backend: 'playwright' explicitly. The old beta'ssuitecut/stable alias also retains Playwright behavior. Audio flags are boolean in 2.0: replace 'tab' with true and'silent' with false.

Terminal
npm install playwright
npx playwright install chromium
# For the optional test runner:
npm install --save-dev @playwright/test

suitecut/test and suitecut/reporter keep their existing behavior. Keep Playwright trace and video off when SuiteCut owns capture. See thePlaywright examples for reporter configuration and browser flows.

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

test('records a narrated flow', async ({ page, suitecut }) => {
  test.setTimeout(120_000)
  await page.setContent(`
    <main>
      <h1>Example Domain</h1>
      <p>This page is local to the test.</p>
    </main>
  `)
  await suitecut.narrate('The example page is open.')
  await expect(page.getByRole('heading')).toHaveText('Example Domain')
  await suitecut.checkpoint('Example page loaded')
})

Render size and frame rate

Native browser dimensions, device scale, and FPS belong in native.capture accepts output size, narrationTailMs, and booleanaudio. The final renderer defaults to 1920 × 1080 at 30 FPS; request 4K60 explicitly when using a 4K physical capture.

TypeScript
import { defineSuiteCut } from 'suitecut'

const record = defineSuiteCut({
  native: {
    width: 1920, height: 1080,
    deviceScaleFactor: 2,
    framesPerSecond: 60,
  },
})
Report an issue ↗MIT licensed · CEF + Playwright