screenci 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +227 -0
- package/cli.ts +1111 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +896 -0
- package/dist/cli.js.map +1 -0
- package/dist/e2e/instrument.e2e.d.ts +2 -0
- package/dist/e2e/instrument.e2e.d.ts.map +1 -0
- package/dist/e2e/instrument.e2e.js +661 -0
- package/dist/e2e/instrument.e2e.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/playwright.config.d.ts +3 -0
- package/dist/playwright.config.d.ts.map +1 -0
- package/dist/playwright.config.js +21 -0
- package/dist/playwright.config.js.map +1 -0
- package/dist/reporter.d.ts +9 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +49 -0
- package/dist/reporter.js.map +1 -0
- package/dist/src/asset.d.ts +90 -0
- package/dist/src/asset.d.ts.map +1 -0
- package/dist/src/asset.js +74 -0
- package/dist/src/asset.js.map +1 -0
- package/dist/src/autoZoom.d.ts +40 -0
- package/dist/src/autoZoom.d.ts.map +1 -0
- package/dist/src/autoZoom.js +88 -0
- package/dist/src/autoZoom.js.map +1 -0
- package/dist/src/caption.d.ts +152 -0
- package/dist/src/caption.d.ts.map +1 -0
- package/dist/src/caption.js +240 -0
- package/dist/src/caption.js.map +1 -0
- package/dist/src/caption.test-d.d.ts +2 -0
- package/dist/src/caption.test-d.d.ts.map +1 -0
- package/dist/src/caption.test-d.js +50 -0
- package/dist/src/caption.test-d.js.map +1 -0
- package/dist/src/config.d.ts +42 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +147 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/defaults.d.ts +63 -0
- package/dist/src/defaults.d.ts.map +1 -0
- package/dist/src/defaults.js +66 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/dimensions.d.ts +29 -0
- package/dist/src/dimensions.d.ts.map +1 -0
- package/dist/src/dimensions.js +47 -0
- package/dist/src/dimensions.js.map +1 -0
- package/dist/src/events.d.ts +203 -0
- package/dist/src/events.d.ts.map +1 -0
- package/dist/src/events.js +227 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/hide.d.ts +27 -0
- package/dist/src/hide.d.ts.map +1 -0
- package/dist/src/hide.js +49 -0
- package/dist/src/hide.js.map +1 -0
- package/dist/src/instrument.d.ts +15 -0
- package/dist/src/instrument.d.ts.map +1 -0
- package/dist/src/instrument.js +910 -0
- package/dist/src/instrument.js.map +1 -0
- package/dist/src/logger.d.ts +7 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +13 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/reporter.d.ts +9 -0
- package/dist/src/reporter.d.ts.map +1 -0
- package/dist/src/reporter.js +50 -0
- package/dist/src/reporter.js.map +1 -0
- package/dist/src/sanitize.d.ts +5 -0
- package/dist/src/sanitize.d.ts.map +1 -0
- package/dist/src/sanitize.js +11 -0
- package/dist/src/sanitize.js.map +1 -0
- package/dist/src/types.d.ts +544 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/video.d.ts +138 -0
- package/dist/src/video.d.ts.map +1 -0
- package/dist/src/video.js +415 -0
- package/dist/src/video.js.map +1 -0
- package/dist/src/voices.d.ts +60 -0
- package/dist/src/voices.d.ts.map +1 -0
- package/dist/src/voices.js +42 -0
- package/dist/src/voices.js.map +1 -0
- package/dist/src/xvfb.d.ts +22 -0
- package/dist/src/xvfb.d.ts.map +1 -0
- package/dist/src/xvfb.js +87 -0
- package/dist/src/xvfb.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +45 -4
- package/bin/index.js +0 -3
- package/index.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# screenci
|
|
2
|
+
|
|
3
|
+
Your UI changed. Your demo videos didn't. screenci fixes that.
|
|
4
|
+
|
|
5
|
+
Record product walkthroughs as code. When the UI ships, run `screenci record` and your videos regenerate. No clicky re-recordings, no stale screenshots, no passive-aggressive Slack messages from the docs team.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install screenci
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Init a new project
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx screenci init my-project
|
|
17
|
+
cd my-project
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This scaffolds a ready-to-run project:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
my-project/
|
|
25
|
+
screenci.config.ts ← video settings
|
|
26
|
+
videos/
|
|
27
|
+
example.video.ts ← your first video script
|
|
28
|
+
Dockerfile ← container image for CI recording
|
|
29
|
+
package.json
|
|
30
|
+
.gitignore
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Write a video
|
|
34
|
+
|
|
35
|
+
Video scripts are Playwright test files with a `.video.ts` extension. If you already know Playwright, you already know 90% of this.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// videos/onboarding.video.ts
|
|
39
|
+
import { video } from 'screenci'
|
|
40
|
+
|
|
41
|
+
video('Onboarding flow', async ({ page }) => {
|
|
42
|
+
await page.goto('https://app.example.com/signup')
|
|
43
|
+
await page.fill('input[name="email"]', 'jane@example.com')
|
|
44
|
+
await page.click('button[type="submit"]')
|
|
45
|
+
await page.waitForURL('**/dashboard')
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Each `video()` call → one `.mp4`. The title becomes the filename.
|
|
50
|
+
|
|
51
|
+
## Run it
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Dry-run: opens Playwright UI so you can see what you're recording
|
|
55
|
+
npm run dev
|
|
56
|
+
|
|
57
|
+
# Record: actually captures the screen
|
|
58
|
+
cd my-project && npm run record
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Recordings land in `.screenci/<video-name>/recording.mp4` alongside a `data.json` with all the interaction events.
|
|
62
|
+
|
|
63
|
+
## Configure
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// screenci.config.ts
|
|
67
|
+
import { defineConfig } from 'screenci'
|
|
68
|
+
|
|
69
|
+
export default defineConfig({
|
|
70
|
+
projectName: 'my-project',
|
|
71
|
+
videoDir: './videos',
|
|
72
|
+
use: {
|
|
73
|
+
baseURL: 'https://app.example.com',
|
|
74
|
+
recordOptions: {
|
|
75
|
+
aspectRatio: '16:9', // '16:9' | '9:16' | '1:1' | '4:3' | ...
|
|
76
|
+
quality: '1080p', // '720p' | '1080p' | '1440p' | '2160p'
|
|
77
|
+
fps: 30, // 24 | 30 | 60
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
screenci enforces `workers: 1`, `retries: 0`, and `fullyParallel: false` — FFmpeg records one screen at a time. Don't fight it.
|
|
84
|
+
|
|
85
|
+
## Captions & AI voiceovers
|
|
86
|
+
|
|
87
|
+
`createCaptions()` maps caption keys to text. At render time screenci sends the text through ElevenLabs and lines up the audio with your recording.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { video, createCaptions } from 'screenci'
|
|
91
|
+
|
|
92
|
+
const captions = createCaptions({
|
|
93
|
+
intro: 'Welcome to the dashboard.',
|
|
94
|
+
addButton: 'Click here to create a new project.',
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
video('Dashboard walkthrough', async ({ page }) => {
|
|
98
|
+
await page.goto('/dashboard')
|
|
99
|
+
|
|
100
|
+
await captions.intro.start()
|
|
101
|
+
// ...anything you do here plays over the voiceover...
|
|
102
|
+
await captions.intro.end()
|
|
103
|
+
|
|
104
|
+
await page.locator('#new-project').click()
|
|
105
|
+
await captions.addButton.start()
|
|
106
|
+
await captions.addButton.end()
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### With a voice
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { createCaptions, voices } from 'screenci'
|
|
114
|
+
|
|
115
|
+
const captions = createCaptions(
|
|
116
|
+
{ voice: voices.en.Jude },
|
|
117
|
+
{
|
|
118
|
+
intro: 'Welcome to the dashboard.',
|
|
119
|
+
addButton: 'Click here to create a new project.',
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Multi-language (type-safe)
|
|
125
|
+
|
|
126
|
+
TypeScript will yell at you if any language is missing a key. That's a feature.
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { createCaptions, voices } from 'screenci'
|
|
130
|
+
|
|
131
|
+
const captions = createCaptions({
|
|
132
|
+
en: {
|
|
133
|
+
voice: voices.en.Jude,
|
|
134
|
+
captions: {
|
|
135
|
+
intro: 'Welcome to the dashboard.',
|
|
136
|
+
addButton: 'Click here to create a new project.',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
fi: {
|
|
140
|
+
voice: voices.fi.Martti,
|
|
141
|
+
captions: {
|
|
142
|
+
intro: 'Tervetuloa hallintapaneeliin.',
|
|
143
|
+
addButton: 'Klikkaa tästä luodaksesi uuden projektin.',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Sync actions to audio
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
// Wait until the voiceover is 60% done, then perform the action
|
|
153
|
+
await captions.intro.waitUntil('60%')
|
|
154
|
+
await page.locator('#cta').click()
|
|
155
|
+
await captions.intro.end()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Hide the boring parts
|
|
159
|
+
|
|
160
|
+
`hide()` cuts a section from the final video. Perfect for logins, page loads, and test setup.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { video, hide } from 'screenci'
|
|
164
|
+
|
|
165
|
+
video('Dashboard demo', async ({ page }) => {
|
|
166
|
+
await hide(async () => {
|
|
167
|
+
// viewer never sees this
|
|
168
|
+
await page.goto('/login')
|
|
169
|
+
await page.fill('input[name="email"]', 'admin@example.com')
|
|
170
|
+
await page.fill('input[name="password"]', 'hunter2')
|
|
171
|
+
await page.click('button[type="submit"]')
|
|
172
|
+
await page.waitForURL('**/dashboard')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
// video starts here — dashboard is already open
|
|
176
|
+
await page.locator('#reports').click()
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Zoom the camera
|
|
181
|
+
|
|
182
|
+
`autoZoom()` follows interactions with a smooth camera pan. Wrap a form or a page section, not individual clicks.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { video, autoZoom } from 'screenci'
|
|
186
|
+
|
|
187
|
+
video('Profile settings', async ({ page }) => {
|
|
188
|
+
await page.goto('/settings/profile')
|
|
189
|
+
|
|
190
|
+
await autoZoom(
|
|
191
|
+
async () => {
|
|
192
|
+
await page.locator('#name').fill('Jane Doe')
|
|
193
|
+
await page.locator('#bio').fill('Engineer')
|
|
194
|
+
await page.locator('button[type="submit"]').click()
|
|
195
|
+
},
|
|
196
|
+
{ duration: 400, amount: 0.4, easing: 'ease-in-out' }
|
|
197
|
+
)
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## API
|
|
202
|
+
|
|
203
|
+
| Export | What it does |
|
|
204
|
+
| ---------------- | ---------------------------------------------------- |
|
|
205
|
+
| `defineConfig` | Wraps Playwright config with screenci defaults |
|
|
206
|
+
| `video` | Declares a video recording test |
|
|
207
|
+
| `createCaptions` | Creates typed caption controllers with AI voiceovers |
|
|
208
|
+
| `hide` | Cuts a section from the final video |
|
|
209
|
+
| `autoZoom` | Smooth camera pan that follows interactions |
|
|
210
|
+
| `voices` | Available voice constants (`voices.en.Jude`, etc.) |
|
|
211
|
+
|
|
212
|
+
The `page` fixture inside `video()` is a `ScreenCIPage` — a Playwright `Page` with animated cursor support wired in on all locator methods.
|
|
213
|
+
|
|
214
|
+
## Output
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
.screenci/
|
|
218
|
+
<video-name>/
|
|
219
|
+
recording.mp4 ← the raw screen capture
|
|
220
|
+
data.json ← interaction events + caption metadata
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Upload to screenci.com for rendering, voiceover generation, and the permanent embed link:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npm run upload-latest
|
|
227
|
+
```
|