screenci 0.0.10 → 0.0.12
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 +56 -56
- package/dist/Dockerfile +1 -2
- package/dist/cli.d.ts +22 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1164 -423
- package/dist/cli.js.map +1 -1
- package/dist/e2e/instrument.e2e.js +12 -0
- package/dist/e2e/instrument.e2e.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/playwright.config.d.ts +1 -1
- package/dist/src/asset.d.ts +27 -67
- package/dist/src/asset.d.ts.map +1 -1
- package/dist/src/asset.js +44 -45
- package/dist/src/asset.js.map +1 -1
- package/dist/src/caption.d.ts +164 -54
- package/dist/src/caption.d.ts.map +1 -1
- package/dist/src/caption.js +304 -131
- package/dist/src/caption.js.map +1 -1
- package/dist/src/events.d.ts +67 -25
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/events.js +34 -18
- package/dist/src/events.js.map +1 -1
- package/dist/src/instrument.d.ts.map +1 -1
- package/dist/src/instrument.js +142 -35
- package/dist/src/instrument.js.map +1 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +2 -1
- package/dist/src/logger.js.map +1 -1
- package/dist/src/recording.d.ts +1 -1
- package/dist/src/recording.d.ts.map +1 -1
- package/dist/src/recordingData.d.ts +145 -0
- package/dist/src/recordingData.d.ts.map +1 -0
- package/dist/src/recordingData.js +2 -0
- package/dist/src/recordingData.js.map +1 -0
- package/dist/src/types.d.ts +133 -66
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/video.d.ts.map +1 -1
- package/dist/src/video.js +28 -20
- package/dist/src/video.js.map +1 -1
- package/dist/src/voices.d.ts +344 -41
- package/dist/src/voices.d.ts.map +1 -1
- package/dist/src/voices.js +261 -30
- package/dist/src/voices.js.map +1 -1
- package/dist/test-fixtures/screenci.config.d.ts +5 -0
- package/dist/test-fixtures/screenci.config.d.ts.map +1 -0
- package/dist/test-fixtures/screenci.config.js +4 -0
- package/dist/test-fixtures/screenci.config.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -5
- package/skills/playwright-cli/SKILL.md +348 -0
- package/skills/screenci/SKILL.md +56 -0
- package/skills/screenci/references/init.md +46 -0
- package/skills/screenci/references/record.md +43 -0
- package/dist/reporter.d.ts +0 -9
- package/dist/reporter.d.ts.map +0 -1
- package/dist/reporter.js +0 -49
- package/dist/reporter.js.map +0 -1
- package/dist/src/caption.test-d.d.ts +0 -2
- package/dist/src/caption.test-d.d.ts.map +0 -1
- package/dist/src/caption.test-d.js +0 -50
- package/dist/src/caption.test-d.js.map +0 -1
- package/dist/src/captionHash.d.ts +0 -12
- package/dist/src/captionHash.d.ts.map +0 -1
- package/dist/src/captionHash.js +0 -17
- package/dist/src/captionHash.js.map +0 -1
package/README.md
CHANGED
|
@@ -82,79 +82,79 @@ export default defineConfig({
|
|
|
82
82
|
|
|
83
83
|
screenci enforces `workers: 1`, `retries: 0`, and `fullyParallel: false` — FFmpeg records one screen at a time. Don't fight it.
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## AI voiceovers
|
|
86
86
|
|
|
87
|
-
`
|
|
87
|
+
`createVoiceOvers()` maps keys to narration text (or audio files). Define it once near the top of the file, then `await voiceOvers.key` inside `video()` wherever that spoken line should begin. The audio keeps playing while your next actions run. Use `await voiceOvers.waitEnd()` only when an action must wait for the current line to finish.
|
|
88
88
|
|
|
89
89
|
```ts
|
|
90
|
-
import { video,
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
import { video, createVoiceOvers, voices } from 'screenci'
|
|
91
|
+
|
|
92
|
+
const voiceOvers = createVoiceOvers({
|
|
93
|
+
voice: { name: voices.Aria },
|
|
94
|
+
languages: {
|
|
95
|
+
en: {
|
|
96
|
+
captions: {
|
|
97
|
+
intro: 'Welcome to the dashboard.',
|
|
98
|
+
addButton: 'Click here to create a new project.',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
95
102
|
})
|
|
96
103
|
|
|
97
104
|
video('Dashboard walkthrough', async ({ page }) => {
|
|
98
105
|
await page.goto('/dashboard')
|
|
99
106
|
|
|
100
|
-
await
|
|
101
|
-
|
|
102
|
-
await captions.intro.end()
|
|
103
|
-
|
|
107
|
+
await voiceOvers.intro
|
|
108
|
+
await page.locator('#reports').click()
|
|
104
109
|
await page.locator('#new-project').click()
|
|
105
|
-
|
|
106
|
-
await
|
|
110
|
+
|
|
111
|
+
await voiceOvers.addButton
|
|
112
|
+
await voiceOvers.waitEnd()
|
|
107
113
|
})
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
Use this pattern:
|
|
111
117
|
|
|
112
118
|
```ts
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
)
|
|
119
|
+
const voiceOvers = createVoiceOvers({ ... })
|
|
120
|
+
|
|
121
|
+
video('Example', async ({ page }) => {
|
|
122
|
+
await voiceOvers.intro // starts narration now
|
|
123
|
+
await page.click('#next') // runs while intro audio is still playing
|
|
124
|
+
|
|
125
|
+
await voiceOvers.details // auto-ends intro, then starts details
|
|
126
|
+
await voiceOvers.waitEnd() // only if the next action must wait
|
|
127
|
+
await page.click('#confirm')
|
|
128
|
+
})
|
|
122
129
|
```
|
|
123
130
|
|
|
124
131
|
### Multi-language (type-safe)
|
|
125
132
|
|
|
126
|
-
TypeScript
|
|
133
|
+
TypeScript enforces that every language has the same keys. Missing a translation is a compile error.
|
|
127
134
|
|
|
128
135
|
```ts
|
|
129
|
-
import {
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
import { createVoiceOvers, voices } from 'screenci'
|
|
137
|
+
|
|
138
|
+
const voiceOvers = createVoiceOvers({
|
|
139
|
+
voice: { name: voices.Ava },
|
|
140
|
+
languages: {
|
|
141
|
+
en: {
|
|
142
|
+
captions: {
|
|
143
|
+
intro: 'Welcome to the dashboard.',
|
|
144
|
+
addButton: 'Click here to create a new project.',
|
|
145
|
+
},
|
|
137
146
|
},
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
147
|
+
fi: {
|
|
148
|
+
voice: { name: voices.Nora },
|
|
149
|
+
captions: {
|
|
150
|
+
intro: 'Tervetuloa hallintapaneeliin.',
|
|
151
|
+
addButton: 'Klikkaa tästä luodaksesi uuden projektin.',
|
|
152
|
+
},
|
|
144
153
|
},
|
|
145
154
|
},
|
|
146
155
|
})
|
|
147
156
|
```
|
|
148
157
|
|
|
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
158
|
## Hide the boring parts
|
|
159
159
|
|
|
160
160
|
`hide()` cuts a section from the final video. Perfect for logins, page loads, and test setup.
|
|
@@ -200,14 +200,14 @@ video('Profile settings', async ({ page }) => {
|
|
|
200
200
|
|
|
201
201
|
## API
|
|
202
202
|
|
|
203
|
-
| Export
|
|
204
|
-
|
|
|
205
|
-
| `defineConfig`
|
|
206
|
-
| `video`
|
|
207
|
-
| `
|
|
208
|
-
| `hide`
|
|
209
|
-
| `autoZoom`
|
|
210
|
-
| `voices`
|
|
203
|
+
| Export | What it does |
|
|
204
|
+
| ------------------ | ------------------------------------------------------------------ |
|
|
205
|
+
| `defineConfig` | Wraps Playwright config with screenci defaults |
|
|
206
|
+
| `video` | Declares a video recording test |
|
|
207
|
+
| `createVoiceOvers` | Creates typed voiceover controllers with AI-generated audio |
|
|
208
|
+
| `hide` | Cuts a section from the final video |
|
|
209
|
+
| `autoZoom` | Smooth camera pan that follows interactions |
|
|
210
|
+
| `voices` | Available voice constants (`voices.Ava`, `voices.elevenlabs(...)`) |
|
|
211
211
|
|
|
212
212
|
The `page` fixture inside `video()` is a `ScreenCIPage` — a Playwright `Page` with animated cursor support wired in on all locator methods.
|
|
213
213
|
|
|
@@ -223,5 +223,5 @@ The `page` fixture inside `video()` is a `ScreenCIPage` — a Playwright `Page`
|
|
|
223
223
|
Upload to screenci.com for rendering, voiceover generation, and the permanent embed link:
|
|
224
224
|
|
|
225
225
|
```bash
|
|
226
|
-
npm run
|
|
226
|
+
npm run retry
|
|
227
227
|
```
|
package/dist/Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ── Runtime image ─────────────────────────────────────────────────────────────
|
|
2
2
|
FROM docker.io/library/node:25.2.1-slim
|
|
3
3
|
|
|
4
4
|
WORKDIR /app
|
|
@@ -18,7 +18,6 @@ RUN printf '{"private":true,"workspaces":["screenci"]}' > package.json && npm in
|
|
|
18
18
|
RUN npx playwright install chromium --with-deps
|
|
19
19
|
|
|
20
20
|
# ── screenci build output ─────────────────────────────────────────────────────
|
|
21
|
-
# Copy pre-built dist directly from the screenci package directory.
|
|
22
21
|
COPY dist ./screenci/dist/
|
|
23
22
|
|
|
24
23
|
# Explicit bin wrapper — no npm bin-linking magic needed.
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
|
+
import type { RecordingCustomVoiceRef, RecordingData } from './src/events.js';
|
|
3
|
+
import type { VoiceKey } from './src/voices.js';
|
|
4
|
+
type PreparedUploadAsset = {
|
|
5
|
+
fileHash: string;
|
|
6
|
+
path: string;
|
|
7
|
+
size: number;
|
|
8
|
+
name?: string;
|
|
9
|
+
fileBuffer?: Buffer;
|
|
10
|
+
contentType?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function attachUploadAbortStdinListener(input: Pick<NodeJS.ReadStream, 'on' | 'off' | 'pause'>, onAbort: (signal: NodeJS.Signals) => void): () => void;
|
|
13
|
+
declare const MIN_CONTAINER_RUNTIME_MAJOR_VERSION: {
|
|
14
|
+
readonly podman: 5;
|
|
15
|
+
readonly docker: 28;
|
|
16
|
+
};
|
|
17
|
+
type ContainerRuntimeName = keyof typeof MIN_CONTAINER_RUNTIME_MAJOR_VERSION;
|
|
18
|
+
export declare function stripVoicePath(voice: VoiceKey | RecordingCustomVoiceRef): VoiceKey | RecordingCustomVoiceRef;
|
|
19
|
+
export declare function annotateRecordingDataWithAssetHashes(data: RecordingData, assets: PreparedUploadAsset[]): RecordingData;
|
|
20
|
+
export declare function getDevBackendUrl(): string;
|
|
21
|
+
export declare function getDevFrontendUrl(): string;
|
|
2
22
|
export declare function main(): Promise<void>;
|
|
3
|
-
export declare function detectContainerRuntime(): string;
|
|
23
|
+
export declare function detectContainerRuntime(forcedRuntime?: ContainerRuntimeName): string;
|
|
24
|
+
export {};
|
|
4
25
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AA4D/C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAiBD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EACtD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GACxC,MAAM,IAAI,CAiBZ;AAuED,QAAA,MAAM,mCAAmC;;;CAG/B,CAAA;AAEV,KAAK,oBAAoB,GAAG,MAAM,OAAO,mCAAmC,CAAA;AAyhB5E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,GAAG,uBAAuB,GACxC,QAAQ,GAAG,uBAAuB,CAKpC;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,aAAa,CAqEf;AAmQD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AA8gBD,wBAAsB,IAAI,kBAsQzB;AAyJD,wBAAgB,sBAAsB,CACpC,aAAa,CAAC,EAAE,oBAAoB,GACnC,MAAM,CAoBR"}
|