Product demo videos,
as build artifacts.
Describe your demo in files. Capture your real app in CI. Let the voiceover drive the cut. Then regenerate the whole film — in every language — on every release.
The pipeline behind Screenwright shipped a 4-minute product film in 21 locales — captured from the real app, regenerated from files, directed once, by one developer. Watch it in the wild →
Narration is generated per BCP-47 locale — 87 locales available today (23 GA · 64 preview) on the default engine, Gemini TTS.
Show the 64 preview locales
Demo videos rot.
Every sprint moves a button. Every new market needs a new voice. Whatever you recorded last quarter is already lying about your product.
Beautiful. Once.
Hand-recorded demos age the day you ship. Re-recording means re-doing the cursor choreography, the zooms, the voiceover — per language. Nobody does. So the video lies.
Captured by hand, frozen in time.
Chrome-extension captures can't run in CI. The video is an export, not an artifact. When the UI changes, a human clicks through everything again.
They already walk the product. Perfectly. Every time.
Your test suite performs the exact flow your demo needs, on every commit. Screenwright turns that determinism into a film — with a voice, a cut, and a director.
Four files. One film. Every release.
Everything is a file in your repo. The video is output — never input.
The voice commands the cut
Write the script as beats. TTS reads each line and measures it — every shot takes exactly the time its line takes. Change a sentence, the whole film re-times itself. Durations are never hand-written. Anywhere.
// voice/locales/en-US.json
"b12": {
"text": "And here’s the invoice total — sales tax already included.",
"marks": { "total": 4 } // word the camera reacts to
}In your CI, from your real app
Declarative Playwright flows with selectors derived from your i18n keys — never transcribed text. A frozen clock and seeded data make every capture identical. The runner executes inside your CI: what leaves is a capture bundle you can inspect — redacted before upload.
{ "op": "fill", "target": { "i18nKey": "invoice.form.customer" }, "value": "Acme Inc." },
{ "op": "click", "target": { "role": "button", "i18nKey": "invoice.actions.issue" } },
{ "op": "screenshot", "id": "invoice-issued",
"elements": ["invoice.total"] } // bounding box recorded per localeDirect it in 20 minutes
A timeline editor in beat-space: click a word, drag a rectangle, and you've made a punch-in — anchored to the word and the UI element, not to seconds and pixels. Your polish survives every regeneration.
{ "op": "punch_in",
"at": { "type": "word", "beat": "b12", "mark": "total", "offsetMs": -120 },
"target": { "type": "element", "element": "invoice.total", "padding": 0.18 },
"params": { "zoom": 1.9, "ease": "punch" } }
// lands on “Gesamtbetrag” in German, on “total” in EnglishForever. In every language.
New release? The GitHub Action re-captures and re-renders. New market? One command. If the demo breaks, demo-lint fails your build and names the exact step, key and locale — a free end-to-end test that happens to produce a film.
# .github/workflows/release.yml - uses: screenwright/capture-action@v1 with: film: invoice-tour locales: all # 21 locales, one direction
An editor that doesn't betray you
at the next render.
Other tools make you choose: reproducible or beautiful. Screenwright's editor writes an overrides file, anchored to your script and your UI — so the machine can regenerate everything and your taste stays.
Beat-space timeline
The ruler is the voiceover, not the clock. You physically cannot type a duration — the voice owns time, your keyframes own attention.
Word + element anchors
Punch-ins fire on the spoken word and frame the actual DOM element, per locale. German text runs 18% longer? The crop adapts. Or warns you. Never lies.
Reconciliation, not conflicts
UI changed under a keyframe? Orphaned anchors are listed with a suggested re-anchor — accept or reject per item. Nothing moves silently, nothing is silently lost.
One direction, 21 locales
A single structural timeline. Switch locale to audit any market; lint flags the punch-in that would crop the Japanese UI — computed from element maps, before rendering.
Agent-native (MCP)
An MCP server ships with the CLI: your coding agent writes the first cut — it probes your app, drafts script + shots, reads contact sheets frame by frame. You direct the last 20 minutes — the fun part.
QA that watches every beat
A vision jury reviews one frame per beat, per locale — currency, language, coherence. An ASR pass re-listens to every line and diffs it against the script.
Your demo is a sensor.
Screenwright also serves the film: edge CDN, embeddable player, per-locale manifests. And because a film is made of beats anchored to product features — not anonymous pixels — the way people watch it becomes product data. Data your product team reads in a dashboard, and your agent will query over remote MCP.
Edge CDN + embeddable player
One script tag. Per-locale manifests pick the right master, poster, subtitles and a light variant for slow networks. Publishing a new market never rebuilds your site — and playback is iPhone-safe by construction.
Attention, mapped to features
Watch-through, drop-off and replays are collected per beat — and every beat is anchored to the feature on screen. The chart your product team reads isn't “seconds 40–52”: it's “the VAT punch-in”. Roadmap fuel, straight from the audience.
A/B test the cut, per country
Serve variants of the same film — different order, different emphasis — and let watch-through pick the winner per market. What holds Nairobi isn't what holds New York; your demo shouldn't pretend it is.
Priced per film. Never per render.
Rebuilding your film on every release is the whole point — we will never tax it. Rebuilds are free. Seats never gate your devs. Languages are how you grow.
- 1 active film
- 2 locales
- Cloud render + hosting
- Discreet end-card watermark
- 3 active films
- 5 locales per film
- Visual editor, no watermark
- GitHub Action + demo-lint
- CDN hosting + embed player
- 10 active films
- Unlimited locales (fair use)
- QA jury + ASR — monthly allowance, then metered
- Light/poster/VTT variants
- Priority render queue
- Self-hosted capture runner
- SSO / SAML, audit log
- Bring your own TTS key
- SLA + private support
The capture + assembly CLI is Apache-2.0, free forever, and works entirely on your machine — npx screenwright init
The questions engineers ask first.
Do you need access to our staging environment?
No. The primary capture mode runs inside your CI — the same place your e2e tests already run. The runner is a pinned Docker image; what leaves your infrastructure is a capture bundle (screenshots, element maps, event logs) that you can inspect, and that is redacted before upload if you declare regions to blur.
What happens when our UI changes?
That's the product. The next capture re-measures every element; keyframes anchored to
elements follow their new bounding boxes automatically. If an element disappears,
demo-lint fails the build and names the exact shot, element and locale —
a silently wrong film is the one thing Screenwright refuses to produce.
How do translations work?
You direct once. The script is a structure with stable beat IDs; each locale carries its own text, word marks and TTS pronunciation hints. Timing is re-measured per language, and the whole film re-times itself — a punch-in fires on “total” in English and on “Gesamtbetrag” in German, because it's anchored to the mark, not the word index.
Which voices? Who owns the audio?
Gemini TTS by default — clean commercial terms; on the paid tier your text is never used for training, and output carries an inaudible SynthID watermark. ElevenLabs via bring-your-own-key. Voices are pinned per film: a provider retiring a voice can never silently change your narrator. You own your masters — they're portable MP4s.
Can our coding agents drive Screenwright?
Yes — that's the native workflow. An MCP server ships with the CLI: agents probe
your app, draft the script and shots, run demo-lint, and review contact sheets
beat by beat — without ever watching a video. A hosted remote MCP is on the preview
roadmap: same tools, same contract, plus the product data — per-beat attention and A/B
results — so your agent can propose the next cut from how the audience actually watched
the last one. You approve the diff like you approve a PR.
Can we self-host?
The capture + assembly CLI is Apache-2.0 and runs entirely on your hardware. The cloud adds the visual editor, render farm, TTS ops, QA jury and hosting. Enterprise plans include a self-hosted capture runner for air-gapped staging.
Born shipping a real product.
Screenwright wasn't dreamed up on a whiteboard. It's the pipeline we built inside CrankPal — the workshop-management platform for bike shops — when we needed a product film for 21 markets and refused to record it 21 times. The film shipped: captured from the real app in CI, cut by the voiceover, regenerated on every release, directed once by one developer.
Screenwright is that pipeline, productized — together with the editor we wished we'd had while making it. CrankPal is customer zero: every feature ships to crankpal.com before it ships to you.
Your demo, always current.
In every language you sell in.
Screenwright is in private preview. Early teams get onboarding with the founders and lifetime preview pricing.
Talk to us.
Early access & everything else
hello@screenwright.io
We read everything and reply from Milan — usually within a day.
Company
CrankPal S.r.l.
Via Benedetto Marcello 6, 20124 Milan, Italy
VAT IT14801630964 · REA MI-2807869
crankpal.com