screenci 0.0.10 → 0.0.11
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 +44 -58
- package/dist/Dockerfile +16 -2
- package/dist/cli.d.ts +21 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1199 -420
- 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 +34 -4
- package/skills/playwright-cli/SKILL.md +348 -0
- package/skills/screenci/SKILL.md +55 -0
- package/skills/screenci/references/init.md +47 -0
- package/skills/screenci/references/record.md +41 -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/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
|
-
*
|
|
9
|
-
*
|
|
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',
|
|
23
|
-
* intro: { path: './intro.mp4',
|
|
40
|
+
* logo: { path: './logo.png', audio: 0, fullScreen: false },
|
|
41
|
+
* intro: { path: './intro.mp4', audio: 1.0, fullScreen: true },
|
|
24
42
|
* })
|
|
25
43
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
package/dist/src/asset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.js","sourceRoot":"","sources":["../../src/asset.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/src/caption.d.ts
CHANGED
|
@@ -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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
163
|
+
* Creates a set of typed voiceover controllers, one per key in the map.
|
|
75
164
|
*
|
|
76
|
-
* Each controller has `start()
|
|
77
|
-
* At render time screenci
|
|
78
|
-
*
|
|
79
|
-
*
|
|
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
|
|
87
|
-
*
|
|
88
|
-
*
|
|
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
|
|
93
|
-
voice
|
|
203
|
+
export declare function createVoiceOvers<M extends Partial<Record<Lang, {
|
|
204
|
+
voice?: LangVoiceOverride;
|
|
205
|
+
region?: string;
|
|
94
206
|
captions: Record<string, CaptionMapValue>;
|
|
95
|
-
}>>>(
|
|
96
|
-
|
|
97
|
-
|
|
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 `
|
|
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":"AAAA,OAAO,KAAK,EACV,cAAc,
|
|
1
|
+
{"version":3,"file":"caption.d.ts","sourceRoot":"","sources":["../../src/caption.ts"],"names":[],"mappings":"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"}
|