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.
Files changed (68) hide show
  1. package/README.md +56 -56
  2. package/dist/Dockerfile +1 -2
  3. package/dist/cli.d.ts +22 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +1164 -423
  6. package/dist/cli.js.map +1 -1
  7. package/dist/e2e/instrument.e2e.js +12 -0
  8. package/dist/e2e/instrument.e2e.js.map +1 -1
  9. package/dist/index.d.ts +7 -7
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/playwright.config.d.ts +1 -1
  14. package/dist/src/asset.d.ts +27 -67
  15. package/dist/src/asset.d.ts.map +1 -1
  16. package/dist/src/asset.js +44 -45
  17. package/dist/src/asset.js.map +1 -1
  18. package/dist/src/caption.d.ts +164 -54
  19. package/dist/src/caption.d.ts.map +1 -1
  20. package/dist/src/caption.js +304 -131
  21. package/dist/src/caption.js.map +1 -1
  22. package/dist/src/events.d.ts +67 -25
  23. package/dist/src/events.d.ts.map +1 -1
  24. package/dist/src/events.js +34 -18
  25. package/dist/src/events.js.map +1 -1
  26. package/dist/src/instrument.d.ts.map +1 -1
  27. package/dist/src/instrument.js +142 -35
  28. package/dist/src/instrument.js.map +1 -1
  29. package/dist/src/logger.d.ts.map +1 -1
  30. package/dist/src/logger.js +2 -1
  31. package/dist/src/logger.js.map +1 -1
  32. package/dist/src/recording.d.ts +1 -1
  33. package/dist/src/recording.d.ts.map +1 -1
  34. package/dist/src/recordingData.d.ts +145 -0
  35. package/dist/src/recordingData.d.ts.map +1 -0
  36. package/dist/src/recordingData.js +2 -0
  37. package/dist/src/recordingData.js.map +1 -0
  38. package/dist/src/types.d.ts +133 -66
  39. package/dist/src/types.d.ts.map +1 -1
  40. package/dist/src/video.d.ts.map +1 -1
  41. package/dist/src/video.js +28 -20
  42. package/dist/src/video.js.map +1 -1
  43. package/dist/src/voices.d.ts +344 -41
  44. package/dist/src/voices.d.ts.map +1 -1
  45. package/dist/src/voices.js +261 -30
  46. package/dist/src/voices.js.map +1 -1
  47. package/dist/test-fixtures/screenci.config.d.ts +5 -0
  48. package/dist/test-fixtures/screenci.config.d.ts.map +1 -0
  49. package/dist/test-fixtures/screenci.config.js +4 -0
  50. package/dist/test-fixtures/screenci.config.js.map +1 -0
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/package.json +35 -5
  53. package/skills/playwright-cli/SKILL.md +348 -0
  54. package/skills/screenci/SKILL.md +56 -0
  55. package/skills/screenci/references/init.md +46 -0
  56. package/skills/screenci/references/record.md +43 -0
  57. package/dist/reporter.d.ts +0 -9
  58. package/dist/reporter.d.ts.map +0 -1
  59. package/dist/reporter.js +0 -49
  60. package/dist/reporter.js.map +0 -1
  61. package/dist/src/caption.test-d.d.ts +0 -2
  62. package/dist/src/caption.test-d.d.ts.map +0 -1
  63. package/dist/src/caption.test-d.js +0 -50
  64. package/dist/src/caption.test-d.js.map +0 -1
  65. package/dist/src/captionHash.d.ts +0 -12
  66. package/dist/src/captionHash.d.ts.map +0 -1
  67. package/dist/src/captionHash.js +0 -17
  68. package/dist/src/captionHash.js.map +0 -1
package/dist/src/asset.js CHANGED
@@ -1,74 +1,73 @@
1
+ import { access } from 'fs/promises';
2
+ import { dirname, resolve } from 'path';
1
3
  let activeRecorder = null;
4
+ const registeredAssetPaths = new Set();
2
5
  export function setActiveAssetRecorder(recorder) {
3
6
  activeRecorder = recorder;
4
7
  }
8
+ export function resetRegisteredAssetPaths() {
9
+ registeredAssetPaths.clear();
10
+ }
11
+ export async function validateRegisteredAssetPaths(testFilePath) {
12
+ const testDir = dirname(testFilePath);
13
+ for (const assetPath of registeredAssetPaths) {
14
+ const candidates = [assetPath, resolve(testDir, assetPath)];
15
+ let exists = false;
16
+ for (const candidate of candidates) {
17
+ try {
18
+ await access(candidate);
19
+ exists = true;
20
+ break;
21
+ }
22
+ catch {
23
+ // try next candidate
24
+ }
25
+ }
26
+ if (!exists) {
27
+ throw new Error(`Asset file not found: ${assetPath}`);
28
+ }
29
+ }
30
+ }
5
31
  /**
6
32
  * Creates a set of typed asset controllers, one per key in the map.
7
33
  *
8
- * Each controller exposes `show()` and `hide()` methods. It is also
9
- * directly awaitable `await assets.logo` is shorthand for
10
- * `await assets.logo.show()`.
11
- *
12
- * **Image assets** require a `duration` (in ms). Calling `show()` will
13
- * automatically record the assetEnd after that many milliseconds. Calling
14
- * `hide()` before the timer fires cancels the auto-hide.
15
- *
16
- * **Video assets** do not require a `duration` — the video's natural length
17
- * determines how long it plays. Call `hide()` explicitly to stop it.
34
+ * Awaiting a controller marks the asset in the recording timeline.
35
+ * The renderer places the asset at that point and plays it for its natural duration.
18
36
  *
19
37
  * @example
20
38
  * ```ts
21
39
  * const assets = createAssets({
22
- * logo: { path: './logo.png', audio: 0, fullScreen: false, duration: 3000 },
23
- * intro: { path: './intro.mp4', audio: 1.0, fullScreen: true },
40
+ * logo: { path: './logo.png', audio: 0, fullScreen: false },
41
+ * intro: { path: './intro.mp4', audio: 1.0, fullScreen: true },
24
42
  * })
25
43
  *
26
- * await assets.logo // shows logo for 3 s, then auto-hides
27
- * await page.goto('/dashboard')
28
- * assets.intro.show() // start video overlay (non-blocking for caller)
29
- * await assets.intro.hide() // hide video overlay manually
44
+ * video('Product demo', async ({ page }) => {
45
+ * await assets.intro
46
+ * await page.goto('/dashboard')
47
+ * await assets.logo
48
+ * })
30
49
  * ```
31
50
  */
32
51
  export function createAssets(assetsMap) {
33
52
  const result = {};
34
53
  for (const name in assetsMap) {
35
54
  const config = assetsMap[name];
55
+ registeredAssetPaths.add(config.path);
36
56
  result[name] = createAssetController(name, config);
37
57
  }
38
58
  return result;
39
59
  }
40
60
  function createAssetController(name, config) {
41
- let autoHideTimer = null;
42
- const controller = {
43
- show() {
44
- if (activeRecorder === null)
45
- return Promise.resolve();
46
- activeRecorder.addAssetStart(name, config.path, config.audio, config.fullScreen);
47
- if ('duration' in config && typeof config.duration === 'number') {
48
- return new Promise((resolve) => {
49
- autoHideTimer = setTimeout(() => {
50
- autoHideTimer = null;
51
- activeRecorder?.addAssetEnd(name);
52
- resolve();
53
- }, config.duration);
54
- });
55
- }
61
+ const startFn = () => {
62
+ if (activeRecorder === null)
56
63
  return Promise.resolve();
57
- },
58
- hide() {
59
- if (autoHideTimer !== null) {
60
- clearTimeout(autoHideTimer);
61
- autoHideTimer = null;
62
- }
63
- if (activeRecorder === null)
64
- return Promise.resolve();
65
- activeRecorder.addAssetEnd(name);
66
- return Promise.resolve();
67
- },
68
- then(onfulfilled, onrejected) {
69
- return controller.show().then(onfulfilled, onrejected);
64
+ activeRecorder.addAssetStart(name, config.path, config.audio, config.fullScreen);
65
+ return Promise.resolve();
66
+ };
67
+ return {
68
+ then(resolve, reject) {
69
+ return startFn().then(resolve, reject);
70
70
  },
71
71
  };
72
- return controller;
73
72
  }
74
73
  //# sourceMappingURL=asset.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset.js","sourceRoot":"","sources":["../../src/asset.ts"],"names":[],"mappings":"AA4BA,IAAI,cAAc,GAA0B,IAAI,CAAA;AAEhD,MAAM,UAAU,sBAAsB,CAAC,QAA+B;IACpE,cAAc,GAAG,QAAQ,CAAA;AAC3B,CAAC;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,YAAY,CAE1B,SAA2D;IAC3D,MAAM,MAAM,GAAG,EAAe,CAAA;IAE9B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAiB,CAAA;QAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACpD,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAY,EACZ,MAAmB;IAEnB,IAAI,aAAa,GAAyC,IAAI,CAAA;IAE9D,MAAM,UAAU,GAAoB;QAClC,IAAI;YACF,IAAI,cAAc,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;YACrD,cAAc,CAAC,aAAa,CAC1B,IAAI,EACJ,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,UAAU,CAClB,CAAA;YACD,IAAI,UAAU,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAChE,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBACnC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;wBAC9B,aAAa,GAAG,IAAI,CAAA;wBACpB,cAAc,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;wBACjC,OAAO,EAAE,CAAA;oBACX,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;gBACrB,CAAC,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;QACD,IAAI;YACF,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,YAAY,CAAC,aAAa,CAAC,CAAA;gBAC3B,aAAa,GAAG,IAAI,CAAA;YACtB,CAAC;YACD,IAAI,cAAc,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;YACrD,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YAChC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;QACD,IAAI,CACF,WAA0D,EAC1D,UAA6D;YAE7D,OAAO,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;QACxD,CAAC;KACF,CAAA;IACD,OAAO,UAAU,CAAA;AACnB,CAAC"}
1
+ {"version":3,"file":"asset.js","sourceRoot":"","sources":["../../src/asset.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAQvC,IAAI,cAAc,GAA0B,IAAI,CAAA;AAChD,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE9C,MAAM,UAAU,sBAAsB,CAAC,QAA+B;IACpE,cAAc,GAAG,QAAQ,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,oBAAoB,CAAC,KAAK,EAAE,CAAA;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,YAAoB;IAEpB,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAErC,KAAK,MAAM,SAAS,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;QAC3D,IAAI,MAAM,GAAG,KAAK,CAAA;QAElB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;gBACvB,MAAM,GAAG,IAAI,CAAA;gBACb,MAAK;YACP,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,EAAE,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;AACH,CAAC;AAqBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAE1B,SAAmC;IACnC,MAAM,MAAM,GAAG,EAAe,CAAA;IAE9B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAiB,CAAA;QAC9C,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACrC,MAAM,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACpD,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAY,EACZ,MAAmB;IAEnB,MAAM,OAAO,GAAG,GAAkB,EAAE;QAClC,IAAI,cAAc,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QACrD,cAAc,CAAC,aAAa,CAC1B,IAAI,EACJ,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,UAAU,CAClB,CAAA;QACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC,CAAA;IACD,OAAO;QACL,IAAI,CAAC,OAAO,EAAE,MAAM;YAClB,OAAO,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACxC,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -1,46 +1,22 @@
1
1
  import type { IEventRecorder } from './events.js';
2
- import type { VoiceKey, VoiceForLang, Lang } from './voices.js';
2
+ import type { VoiceKey, VoiceForLang, Lang, CustomVoiceRef, ModelType } from './voices.js';
3
3
  export declare const ONE_FRAME_MS: number;
4
- /** A percentage string, e.g. `'50%'` or `'100%'`. */
5
- export type Percentage = `${number}%`;
6
4
  export declare function setSleepFn(fn: (ms: number) => void): void;
7
5
  export declare function setActiveCaptionRecorder(recorder: IEventRecorder | null): void;
8
6
  export declare function resetCaptionChain(): void;
9
- export interface CaptionController {
10
- /**
11
- * Begins voiceover audio and shows the caption overlay.
12
- *
13
- * @example
14
- * ```ts
15
- * await captions.intro.start()
16
- * await page.goto('/dashboard')
17
- * await captions.intro.end()
18
- * ```
19
- */
20
- start(): Promise<void>;
21
- /**
22
- * Pauses execution until the voiceover audio reaches the given playback position.
23
- *
24
- * Use this to time a page interaction to a specific moment in the narration —
25
- * for example, clicking a button right as the voiceover mentions it.
26
- *
27
- * @param progress - Playback position as a percentage string, e.g. `'50%'`.
28
- *
29
- * @example
30
- * ```ts
31
- * await captions.intro.start()
32
- * await captions.intro.waitUntil('70%') // wait until 70% of audio has played
33
- * await page.locator('#cta').click() // then click
34
- * await captions.intro.end()
35
- * ```
36
- */
37
- waitUntil(progress: string): Promise<void>;
38
- /**
39
- * Hides the caption overlay and stops voiceover playback.
40
- * Always call this after every `start()`.
41
- */
42
- end(): Promise<void>;
43
- }
7
+ export declare function resetRegisteredCustomVoiceRefs(): void;
8
+ export declare function validateCustomVoiceRefs(testFilePath: string): Promise<void>;
9
+ /**
10
+ * A voiceOver controller. Awaiting it starts the voiceover.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * await voiceOvers.intro
15
+ * await page.goto('/dashboard')
16
+ * await voiceOvers.nextStep
17
+ * ```
18
+ */
19
+ export type CaptionController = PromiseLike<void>;
44
20
  /** A single caption value in a multi-language map: either TTS text or a file-based entry. */
45
21
  export type CaptionMapValue = string | {
46
22
  path: string;
@@ -48,6 +24,22 @@ export type CaptionMapValue = string | {
48
24
  };
49
25
  export type Captions<T extends Record<string, CaptionMapValue>> = {
50
26
  [K in keyof T]: CaptionController;
27
+ } & {
28
+ /**
29
+ * Waits for the current voiceOver to finish before the next action.
30
+ *
31
+ * Only needed when an action must happen _after_ a voiceOver ends.
32
+ * Consecutive `await voiceOvers.x` calls sequence automatically — each
33
+ * one ends the previous before starting.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * await voiceOvers.intro
38
+ * await voiceOvers.waitEnd() // wait for intro audio to finish
39
+ * await page.click('#next') // click happens after intro ends
40
+ * ```
41
+ */
42
+ waitEnd(): Promise<void>;
51
43
  };
52
44
  export type VideoCaptionEntry = string | {
53
45
  path: string;
@@ -55,6 +47,78 @@ export type VideoCaptionEntry = string | {
55
47
  };
56
48
  export type VideoCaptions<T extends Record<string, VideoCaptionEntry>> = {
57
49
  [K in keyof T]: CaptionController;
50
+ } & {
51
+ /**
52
+ * Waits for the current voiceOver to finish before the next action.
53
+ * @see {@link Captions.waitEnd}
54
+ */
55
+ waitEnd(): Promise<void>;
56
+ };
57
+ /**
58
+ * Top-level voice configuration shared across all languages.
59
+ * `seed` is not allowed here — use per-language `voice` overrides instead.
60
+ *
61
+ * Use `style` for expressive Gemini synthesis, or `modelType` for an explicit
62
+ * model choice. `style` and `modelType` are mutually exclusive.
63
+ */
64
+ export type TopLevelVoiceConfig = {
65
+ name: VoiceKey | CustomVoiceRef;
66
+ /** Speaking style prompt for Gemini TTS. Implies `expressive` model type. */
67
+ style: string;
68
+ /** Can be omitted when `style` is set — `expressive` is implied. */
69
+ modelType?: 'expressive';
70
+ /**
71
+ * Accent description for Gemini TTS. Only used with `expressive` model type.
72
+ * The more specific, the better — e.g. `'Southern American English'` or `'Received Pronunciation British'`.
73
+ * Omitted from the prompt when not set — the voice uses its natural default.
74
+ */
75
+ accent?: string;
76
+ /**
77
+ * Pacing description for Gemini TTS. Only used with `expressive` model type.
78
+ * Describes the overall speed and tempo — e.g. `'Measured and deliberate'` or `'Brisk and energetic'`.
79
+ */
80
+ pacing?: string;
81
+ } | {
82
+ name: VoiceKey | CustomVoiceRef;
83
+ style?: never;
84
+ accent?: never;
85
+ pacing?: never;
86
+ /** TTS model type — `modelTypes.expressive` (Gemini) or `modelTypes.consistent` (Chirp 3 HD). Defaults to `consistent`. */
87
+ modelType?: ModelType;
88
+ };
89
+ /**
90
+ * Per-language voice override. Can override the top-level voice name and
91
+ * optionally set a `seed` for deterministic synthesis.
92
+ *
93
+ * Use `style` for expressive Gemini synthesis, or `modelType` for an explicit
94
+ * model choice. `style` and `modelType` are mutually exclusive.
95
+ */
96
+ export type LangVoiceOverride = {
97
+ name: VoiceKey | CustomVoiceRef;
98
+ seed?: number;
99
+ /** Speaking style prompt for Gemini TTS. Implies `expressive` model type. */
100
+ style: string;
101
+ /** Can be omitted when `style` is set — `expressive` is implied. */
102
+ modelType?: 'expressive';
103
+ /**
104
+ * Accent description for Gemini TTS. Only used with `expressive` model type.
105
+ * The more specific, the better — e.g. `'Southern American English'` or `'Received Pronunciation British'`.
106
+ * Omitted from the prompt when not set — the voice uses its natural default.
107
+ */
108
+ accent?: string;
109
+ /**
110
+ * Pacing description for Gemini TTS. Only used with `expressive` model type.
111
+ * Describes the overall speed and tempo — e.g. `'Measured and deliberate'` or `'Brisk and energetic'`.
112
+ */
113
+ pacing?: string;
114
+ } | {
115
+ name: VoiceKey | CustomVoiceRef;
116
+ seed?: number;
117
+ style?: never;
118
+ accent?: never;
119
+ pacing?: never;
120
+ /** TTS model type — `modelTypes.expressive` (Gemini) or `modelTypes.consistent` (Chirp 3 HD). Defaults to `consistent`. */
121
+ modelType?: ModelType;
58
122
  };
59
123
  /** Converts a union type to an intersection: `A | B` → `A & B` */
60
124
  type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
@@ -70,33 +134,79 @@ type AllCaptions<M extends Partial<Record<Lang, {
70
134
  captions: infer C;
71
135
  } ? Record<keyof C & string, CaptionMapValue> : never;
72
136
  }[keyof M]> & Record<string, CaptionMapValue>;
137
+ type LangVoiceOverrideForLang<L extends string> = {
138
+ name: (L extends Lang ? VoiceForLang<L> : VoiceKey) | CustomVoiceRef;
139
+ seed?: number;
140
+ style: string;
141
+ modelType?: 'expressive';
142
+ accent?: string;
143
+ pacing?: string;
144
+ } | {
145
+ name: (L extends Lang ? VoiceForLang<L> : VoiceKey) | CustomVoiceRef;
146
+ seed?: number;
147
+ style?: never;
148
+ accent?: never;
149
+ pacing?: never;
150
+ modelType?: ModelType;
151
+ };
152
+ type LanguagesMap<M extends Partial<Record<Lang, {
153
+ captions: Record<string, CaptionMapValue>;
154
+ }>>> = M & {
155
+ [L in keyof M]: {
156
+ voice?: L extends string ? LangVoiceOverrideForLang<L> : never;
157
+ /** BCP-47 region code for TTS synthesis, e.g. `languageRegions.en.US`. */
158
+ region?: string;
159
+ captions: AllCaptions<M>;
160
+ };
161
+ };
73
162
  /**
74
- * Creates a set of typed caption controllers, one per key in the map.
163
+ * Creates a set of typed voiceover controllers, one per key in the map.
75
164
  *
76
- * Each controller has `start()`, `waitUntil(percent)`, and `end()`.
77
- * At render time screenci sends the caption text to ElevenLabs, generates
78
- * a voiceover, and syncs the audio to the recording. You write text; the
79
- * voice is handled for you.
165
+ * Each controller has `start()` and `end()`.
166
+ * At render time screenci generates a voiceover, and syncs the audio to the
167
+ * recording. You write text; the voice is handled for you.
168
+ *
169
+ * The top-level `voice` applies to all languages. Override it per-language via
170
+ * the `voice` field inside each language entry. Only language-level overrides
171
+ * may set `seed`.
80
172
  *
81
173
  * TypeScript enforces that every language has the same caption keys.
82
174
  * Forget a translation key → compile error.
83
175
  *
84
176
  * @example
85
177
  * ```ts
86
- * const captions = createCaptions({
87
- * en: { voice: voices.en.Jude, captions: { intro: 'Welcome.' } },
88
- * fi: { voice: voices.fi.Martti, captions: { intro: 'Tervetuloa.' } },
178
+ * const voiceOvers = createVoiceOvers({
179
+ * voice: { name: voices.Ava, style: 'Clear and friendly' },
180
+ * languages: {
181
+ * en: { captions: { intro: 'Welcome.', next: 'Click here.' } },
182
+ * fi: {
183
+ * voice: { name: voices.Nora, style: 'Selkeä opastus', seed: 42 },
184
+ * captions: { intro: 'Tervetuloa.', next: 'Napsauta tästä.' },
185
+ * },
186
+ * },
89
187
  * })
188
+ *
189
+ * // Await a voiceOver directly to start it:
190
+ * await voiceOvers.intro
191
+ * await page.goto('/dashboard')
192
+ *
193
+ * // Consecutive voiceOvers sequence automatically:
194
+ * await voiceOvers.intro
195
+ * await voiceOvers.next // ends intro, then starts next
196
+ *
197
+ * // Wait for audio to finish before an action:
198
+ * await voiceOvers.intro
199
+ * await voiceOvers.waitEnd()
200
+ * await page.click('#start')
90
201
  * ```
91
202
  */
92
- export declare function createCaptions<M extends Partial<Record<Lang, {
93
- voice: VoiceKey;
203
+ export declare function createVoiceOvers<M extends Partial<Record<Lang, {
204
+ voice?: LangVoiceOverride;
205
+ region?: string;
94
206
  captions: Record<string, CaptionMapValue>;
95
- }>>>(languagesMap: M & {
96
- [L in keyof M]: {
97
- voice: VoiceForLang<L & string>;
98
- captions: AllCaptions<M>;
99
- };
207
+ }>>>(input: {
208
+ voice: TopLevelVoiceConfig;
209
+ languages: LanguagesMap<M>;
100
210
  }): Captions<AllCaptions<M>>;
101
211
  type RequireAllSameVideoKeys<M extends Partial<Record<Lang, {
102
212
  captions: Record<string, VideoCaptionEntry>;
@@ -116,7 +226,7 @@ type RequireAllSameVideoKeys<M extends Partial<Record<Lang, {
116
226
  * If `subtitle` is provided, words are spread with equal timing across the
117
227
  * audio duration (no word-level TTS data available).
118
228
  *
119
- * Same constraints as `createCaptions`: cannot overlap with other captions,
229
+ * Same constraints as `createVoiceOvers`: cannot overlap with other captions,
120
230
  * and cannot fall inside input events.
121
231
  *
122
232
  * Two overloads:
@@ -1 +1 @@
1
- {"version":3,"file":"caption.d.ts","sourceRoot":"","sources":["../../src/caption.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"caption.d.ts","sourceRoot":"","sources":["../../src/caption.ts"],"names":[],"mappings":"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"}