@t3lnet/sceneforge 1.0.0
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 +5 -0
- package/dist/index.cjs +2137 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +706 -0
- package/dist/index.d.ts +706 -0
- package/dist/index.js +2064 -0
- package/dist/index.js.map +1 -0
- package/package.json +36 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Page } from '@playwright/test';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Core type definitions for demo YAML format.
|
|
6
|
+
* These types define the schema used by demo definition YAML files
|
|
7
|
+
* and are shared between all tools (CLI, extension, etc).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Complete demo definition matching the YAML schema.
|
|
11
|
+
*/
|
|
12
|
+
interface DemoDefinition {
|
|
13
|
+
version: number;
|
|
14
|
+
name: string;
|
|
15
|
+
title: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
steps: DemoStep[];
|
|
18
|
+
/** Media configuration for intro/outro and background music */
|
|
19
|
+
media?: MediaConfig;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A logical step in the demo with a script and multiple actions.
|
|
23
|
+
*/
|
|
24
|
+
interface DemoStep {
|
|
25
|
+
id: string;
|
|
26
|
+
script: string;
|
|
27
|
+
actions: DemoAction[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A single action within a step.
|
|
31
|
+
*/
|
|
32
|
+
interface DemoAction {
|
|
33
|
+
action: ActionType;
|
|
34
|
+
path?: string;
|
|
35
|
+
target?: StepTarget;
|
|
36
|
+
text?: string;
|
|
37
|
+
file?: string;
|
|
38
|
+
duration?: number;
|
|
39
|
+
highlight?: boolean;
|
|
40
|
+
waitFor?: WaitCondition;
|
|
41
|
+
drag?: DragConfig;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Supported action types.
|
|
45
|
+
*/
|
|
46
|
+
type ActionType = "navigate" | "click" | "type" | "upload" | "wait" | "hover" | "scroll" | "scrollTo" | "drag";
|
|
47
|
+
/**
|
|
48
|
+
* Target element specification.
|
|
49
|
+
*/
|
|
50
|
+
interface StepTarget {
|
|
51
|
+
type: "button" | "link" | "input" | "text" | "selector";
|
|
52
|
+
text?: string;
|
|
53
|
+
selector?: string;
|
|
54
|
+
name?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Wait condition configuration.
|
|
58
|
+
*/
|
|
59
|
+
interface WaitCondition {
|
|
60
|
+
type: "text" | "selector" | "navigation" | "idle" | "selectorHidden" | "textHidden";
|
|
61
|
+
value?: string;
|
|
62
|
+
timeout?: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Drag action configuration.
|
|
66
|
+
*/
|
|
67
|
+
interface DragConfig {
|
|
68
|
+
deltaX: number;
|
|
69
|
+
deltaY: number;
|
|
70
|
+
steps?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Element information captured during recording.
|
|
74
|
+
*/
|
|
75
|
+
interface ElementInfo {
|
|
76
|
+
tagName: string;
|
|
77
|
+
id?: string;
|
|
78
|
+
className?: string;
|
|
79
|
+
textContent?: string;
|
|
80
|
+
ariaLabel?: string;
|
|
81
|
+
placeholder?: string;
|
|
82
|
+
name?: string;
|
|
83
|
+
type?: string;
|
|
84
|
+
href?: string;
|
|
85
|
+
role?: string;
|
|
86
|
+
dataTestId?: string;
|
|
87
|
+
boundingRect: {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
width: number;
|
|
91
|
+
height: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A recorded user interaction (used during recording).
|
|
96
|
+
*/
|
|
97
|
+
interface RecordedInteraction {
|
|
98
|
+
type: "click" | "input" | "navigation" | "scroll" | "drag";
|
|
99
|
+
timestamp: number;
|
|
100
|
+
selector: string;
|
|
101
|
+
selectorCandidates: SelectorCandidate[];
|
|
102
|
+
elementInfo: ElementInfo;
|
|
103
|
+
value?: string;
|
|
104
|
+
url?: string;
|
|
105
|
+
scrollDelta?: {
|
|
106
|
+
deltaX: number;
|
|
107
|
+
deltaY: number;
|
|
108
|
+
};
|
|
109
|
+
dragDelta?: {
|
|
110
|
+
deltaX: number;
|
|
111
|
+
deltaY: number;
|
|
112
|
+
duration: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Selector generation strategy.
|
|
117
|
+
*/
|
|
118
|
+
type SelectorStrategy = "data-testid" | "aria-label" | "role-text" | "placeholder" | "css-class" | "xpath" | "text" | "id";
|
|
119
|
+
/**
|
|
120
|
+
* A selector candidate with priority and strategy info.
|
|
121
|
+
*/
|
|
122
|
+
interface SelectorCandidate {
|
|
123
|
+
selector: string;
|
|
124
|
+
priority: number;
|
|
125
|
+
strategy: SelectorStrategy | string;
|
|
126
|
+
description?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Recording privacy configuration for the extension.
|
|
130
|
+
*/
|
|
131
|
+
interface PrivacyConfig {
|
|
132
|
+
redactSensitiveInputs: boolean;
|
|
133
|
+
allowlist: string[];
|
|
134
|
+
denylist: string[];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Selector strategy configuration for the extension.
|
|
138
|
+
*/
|
|
139
|
+
interface SelectorConfig {
|
|
140
|
+
enabledStrategies: string[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Recording state for the extension.
|
|
144
|
+
*/
|
|
145
|
+
interface RecordingState {
|
|
146
|
+
isRecording: boolean;
|
|
147
|
+
isPicking: boolean;
|
|
148
|
+
isPaused: boolean;
|
|
149
|
+
privacyConfig: PrivacyConfig;
|
|
150
|
+
selectorConfig: SelectorConfig;
|
|
151
|
+
lastError?: {
|
|
152
|
+
message: string;
|
|
153
|
+
time: string;
|
|
154
|
+
};
|
|
155
|
+
currentDemo: DemoDefinition | null;
|
|
156
|
+
currentStepIndex: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Result of element picker.
|
|
160
|
+
*/
|
|
161
|
+
interface PickerResult {
|
|
162
|
+
selector: string;
|
|
163
|
+
selectorCandidates: SelectorCandidate[];
|
|
164
|
+
elementInfo: ElementInfo;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Result of testing a selector.
|
|
168
|
+
*/
|
|
169
|
+
interface TestSelectorResponse {
|
|
170
|
+
found: boolean;
|
|
171
|
+
count: number;
|
|
172
|
+
elementInfo?: {
|
|
173
|
+
tagName: string;
|
|
174
|
+
textContent?: string;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Intro/outro video segment configuration.
|
|
179
|
+
*/
|
|
180
|
+
interface VideoSegment {
|
|
181
|
+
/** Path to the video file (relative to YAML or absolute) */
|
|
182
|
+
file: string;
|
|
183
|
+
/** Optional duration in seconds (uses full length if omitted) */
|
|
184
|
+
duration?: number;
|
|
185
|
+
/** Whether to fade in/out the segment */
|
|
186
|
+
fade?: boolean;
|
|
187
|
+
/** Fade duration in seconds (default: 0.5) */
|
|
188
|
+
fadeDuration?: number;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Background music configuration.
|
|
192
|
+
*/
|
|
193
|
+
interface BackgroundMusic {
|
|
194
|
+
/** Path to the audio file (relative to YAML or absolute) */
|
|
195
|
+
file: string;
|
|
196
|
+
/** Volume level 0.0-1.0 (default: 0.15 for background) */
|
|
197
|
+
volume?: number;
|
|
198
|
+
/** When to start the music */
|
|
199
|
+
startAt?: MusicStartPoint;
|
|
200
|
+
/** When to stop the music */
|
|
201
|
+
endAt?: MusicEndPoint;
|
|
202
|
+
/** Whether to loop the audio if it's shorter than the video */
|
|
203
|
+
loop?: boolean;
|
|
204
|
+
/** Fade in duration in seconds */
|
|
205
|
+
fadeIn?: number;
|
|
206
|
+
/** Fade out duration in seconds */
|
|
207
|
+
fadeOut?: number;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Music start point configuration.
|
|
211
|
+
*/
|
|
212
|
+
type MusicStartPoint = {
|
|
213
|
+
type: "beginning";
|
|
214
|
+
} | {
|
|
215
|
+
type: "afterIntro";
|
|
216
|
+
} | {
|
|
217
|
+
type: "step";
|
|
218
|
+
stepId: string;
|
|
219
|
+
} | {
|
|
220
|
+
type: "time";
|
|
221
|
+
seconds: number;
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Music end point configuration.
|
|
225
|
+
*/
|
|
226
|
+
type MusicEndPoint = {
|
|
227
|
+
type: "end";
|
|
228
|
+
} | {
|
|
229
|
+
type: "beforeOutro";
|
|
230
|
+
} | {
|
|
231
|
+
type: "step";
|
|
232
|
+
stepId: string;
|
|
233
|
+
} | {
|
|
234
|
+
type: "time";
|
|
235
|
+
seconds: number;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Media configuration for final video production.
|
|
239
|
+
*/
|
|
240
|
+
interface MediaConfig {
|
|
241
|
+
/** Intro video segment to prepend */
|
|
242
|
+
intro?: VideoSegment;
|
|
243
|
+
/** Outro video segment to append */
|
|
244
|
+
outro?: VideoSegment;
|
|
245
|
+
/** Background music configuration */
|
|
246
|
+
backgroundMusic?: BackgroundMusic;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* YAML parsing and serialization for demo definitions.
|
|
251
|
+
* Shared between CLI and extension.
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Parses a YAML string into a DemoDefinition.
|
|
256
|
+
*/
|
|
257
|
+
declare function parseFromYAML(yamlString: string, options?: {
|
|
258
|
+
resolveSecrets?: (key: string) => string | undefined;
|
|
259
|
+
}): DemoDefinition;
|
|
260
|
+
/**
|
|
261
|
+
* Serializes a DemoDefinition to a YAML string.
|
|
262
|
+
*/
|
|
263
|
+
declare function serializeToYAML(demo: DemoDefinition): string;
|
|
264
|
+
/**
|
|
265
|
+
* Validates a demo definition, throwing on errors.
|
|
266
|
+
*/
|
|
267
|
+
declare function validateDemoDefinition(definition: DemoDefinition): void;
|
|
268
|
+
/**
|
|
269
|
+
* Creates a default empty demo definition.
|
|
270
|
+
*/
|
|
271
|
+
declare function createEmptyDemo(): DemoDefinition;
|
|
272
|
+
/**
|
|
273
|
+
* Creates a default empty step.
|
|
274
|
+
*/
|
|
275
|
+
declare function createEmptyStep(id?: string): DemoStep;
|
|
276
|
+
|
|
277
|
+
declare const DEMO_SCHEMA_VERSION = 1;
|
|
278
|
+
type DemoDefinitionInput = Omit<DemoDefinition, "version"> & {
|
|
279
|
+
version?: number;
|
|
280
|
+
};
|
|
281
|
+
declare const demoDefinitionSchema: z.ZodType<DemoDefinition, z.ZodTypeDef, DemoDefinitionInput>;
|
|
282
|
+
declare function formatValidationError(error: unknown): string;
|
|
283
|
+
declare function parseDemoDefinition(input: unknown): DemoDefinition;
|
|
284
|
+
declare function safeParseDemoDefinition(input: unknown): z.SafeParseReturnType<DemoDefinitionInput, DemoDefinition>;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Target resolution utilities.
|
|
288
|
+
* Converts StepTarget configurations to CSS/Playwright selectors.
|
|
289
|
+
*/
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Resolves a target configuration to a selector string.
|
|
293
|
+
* Works with both Playwright locators and standard CSS selectors.
|
|
294
|
+
*/
|
|
295
|
+
declare function resolveTarget(target: StepTarget): string;
|
|
296
|
+
/**
|
|
297
|
+
* Replaces template variables in paths.
|
|
298
|
+
* Supports: {baseURL}.
|
|
299
|
+
*/
|
|
300
|
+
declare function resolvePath(pathTemplate: string, variables: Record<string, string | undefined>): string;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Helper functions for creating common actions.
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Creates a click action.
|
|
308
|
+
*/
|
|
309
|
+
declare function createClickAction(selector: string, highlight?: boolean): DemoAction;
|
|
310
|
+
/**
|
|
311
|
+
* Creates a type/input action.
|
|
312
|
+
*/
|
|
313
|
+
declare function createTypeAction(selector: string, text: string): DemoAction;
|
|
314
|
+
/**
|
|
315
|
+
* Creates a navigate action.
|
|
316
|
+
*/
|
|
317
|
+
declare function createNavigateAction(path: string): DemoAction;
|
|
318
|
+
/**
|
|
319
|
+
* Creates a wait action with a fixed duration.
|
|
320
|
+
*/
|
|
321
|
+
declare function createWaitAction(duration: number): DemoAction;
|
|
322
|
+
/**
|
|
323
|
+
* Creates a wait action with a condition.
|
|
324
|
+
*/
|
|
325
|
+
declare function createWaitForAction(type: WaitCondition["type"], value?: string, timeout?: number): DemoAction;
|
|
326
|
+
/**
|
|
327
|
+
* Creates an upload action.
|
|
328
|
+
* Note: selector is optional - defaults to first file input on page.
|
|
329
|
+
*/
|
|
330
|
+
declare function createUploadAction(file: string, selector?: string): DemoAction;
|
|
331
|
+
/**
|
|
332
|
+
* Creates a hover action.
|
|
333
|
+
*/
|
|
334
|
+
declare function createHoverAction(selector: string): DemoAction;
|
|
335
|
+
/**
|
|
336
|
+
* Creates a scroll action.
|
|
337
|
+
*/
|
|
338
|
+
declare function createScrollAction(duration?: number): DemoAction;
|
|
339
|
+
/**
|
|
340
|
+
* Creates a scroll-to action.
|
|
341
|
+
*/
|
|
342
|
+
declare function createScrollToAction(selector: string): DemoAction;
|
|
343
|
+
/**
|
|
344
|
+
* Creates a drag action.
|
|
345
|
+
*/
|
|
346
|
+
declare function createDragAction(selector: string, deltaX: number, deltaY: number, steps?: number): DemoAction;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Demo runner for Playwright.
|
|
350
|
+
* Executes demo definitions using Playwright for video recording.
|
|
351
|
+
*/
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Context passed to the demo runner.
|
|
355
|
+
*/
|
|
356
|
+
interface DemoContext {
|
|
357
|
+
page: Page;
|
|
358
|
+
baseURL: string;
|
|
359
|
+
outputDir: string;
|
|
360
|
+
videoPath?: string;
|
|
361
|
+
videoRecordingStartTime?: number;
|
|
362
|
+
assetBaseDir?: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Result of running a demo.
|
|
366
|
+
*/
|
|
367
|
+
interface DemoResult {
|
|
368
|
+
success: boolean;
|
|
369
|
+
demoName: string;
|
|
370
|
+
videoPath?: string;
|
|
371
|
+
scriptPath?: string;
|
|
372
|
+
error?: Error;
|
|
373
|
+
duration: number;
|
|
374
|
+
}
|
|
375
|
+
interface RunDemoOptions {
|
|
376
|
+
generateScripts?: boolean;
|
|
377
|
+
scriptOutputDir?: string;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Step timing info for video splitting.
|
|
381
|
+
*/
|
|
382
|
+
interface StepTiming {
|
|
383
|
+
id: string;
|
|
384
|
+
script: string;
|
|
385
|
+
startTime: number;
|
|
386
|
+
endTime?: number;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Loads and parses a YAML demo definition file.
|
|
390
|
+
*/
|
|
391
|
+
declare function loadDemoDefinition(filePath: string, options?: {
|
|
392
|
+
resolveSecrets?: (key: string) => string | undefined;
|
|
393
|
+
}): Promise<DemoDefinition>;
|
|
394
|
+
/**
|
|
395
|
+
* Runs a complete demo from a definition.
|
|
396
|
+
*/
|
|
397
|
+
declare function runDemo(definition: DemoDefinition, context: DemoContext, options?: RunDemoOptions): Promise<DemoResult>;
|
|
398
|
+
/**
|
|
399
|
+
* Runs a demo from a YAML file path.
|
|
400
|
+
*/
|
|
401
|
+
declare function runDemoFromFile(definitionPath: string, context: DemoContext, options?: RunDemoOptions): Promise<DemoResult>;
|
|
402
|
+
/**
|
|
403
|
+
* Discovers all demo definition files in a directory.
|
|
404
|
+
*/
|
|
405
|
+
declare function discoverDemos(demoDir: string): Promise<string[]>;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Injects the demo cursor overlay into the page.
|
|
409
|
+
* Call this once after page load.
|
|
410
|
+
*/
|
|
411
|
+
declare function injectCursorOverlay(page: Page): Promise<void>;
|
|
412
|
+
/**
|
|
413
|
+
* Smoothly moves the demo cursor to specified coordinates using actual mouse movement.
|
|
414
|
+
* This creates a visible animation in the recorded video.
|
|
415
|
+
*/
|
|
416
|
+
declare function moveCursorTo(page: Page, x: number, y: number, options?: {
|
|
417
|
+
steps?: number;
|
|
418
|
+
trailEnabled?: boolean;
|
|
419
|
+
}): Promise<void>;
|
|
420
|
+
/**
|
|
421
|
+
* Triggers the click ripple animation at the current cursor position.
|
|
422
|
+
*/
|
|
423
|
+
declare function triggerClickRipple(page: Page): Promise<void>;
|
|
424
|
+
/**
|
|
425
|
+
* Highlights an element with a pulsing ring effect.
|
|
426
|
+
*/
|
|
427
|
+
declare function highlightElement(page: Page, selector: string): Promise<void>;
|
|
428
|
+
/**
|
|
429
|
+
* Removes the demo cursor overlay.
|
|
430
|
+
*/
|
|
431
|
+
declare function removeCursorOverlay(page: Page): Promise<void>;
|
|
432
|
+
/**
|
|
433
|
+
* Performs a demo click action with visible cursor movement:
|
|
434
|
+
* 1. Moves cursor smoothly to element center
|
|
435
|
+
* 2. Optionally highlights element
|
|
436
|
+
* 3. Triggers click ripple
|
|
437
|
+
* 4. Performs actual click
|
|
438
|
+
*/
|
|
439
|
+
declare function demoClick(page: Page, selector: string, options?: {
|
|
440
|
+
highlight?: boolean;
|
|
441
|
+
delayAfter?: number;
|
|
442
|
+
delayBefore?: number;
|
|
443
|
+
timeoutMs?: number;
|
|
444
|
+
}): Promise<void>;
|
|
445
|
+
/**
|
|
446
|
+
* Performs a demo hover action with visible cursor movement.
|
|
447
|
+
*/
|
|
448
|
+
declare function demoHover(page: Page, selector: string, options?: {
|
|
449
|
+
highlight?: boolean;
|
|
450
|
+
timeoutMs?: number;
|
|
451
|
+
}): Promise<void>;
|
|
452
|
+
/**
|
|
453
|
+
* Types text with visible cursor at the input location.
|
|
454
|
+
*/
|
|
455
|
+
declare function demoType(page: Page, selector: string, text: string, options?: {
|
|
456
|
+
highlight?: boolean;
|
|
457
|
+
delayBetweenChars?: number;
|
|
458
|
+
}): Promise<void>;
|
|
459
|
+
|
|
460
|
+
interface RetryOptions {
|
|
461
|
+
retries?: number;
|
|
462
|
+
minDelayMs?: number;
|
|
463
|
+
maxDelayMs?: number;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Configuration for voice synthesis
|
|
467
|
+
*/
|
|
468
|
+
interface VoiceSynthesisConfig {
|
|
469
|
+
apiKey: string;
|
|
470
|
+
voiceId: string;
|
|
471
|
+
modelId?: string;
|
|
472
|
+
outputFormat?: "mp3_44100_128" | "mp3_44100_192" | "pcm_16000" | "pcm_22050" | "pcm_24000";
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Script segment from the generated JSON
|
|
476
|
+
*/
|
|
477
|
+
interface ScriptSegment$1 {
|
|
478
|
+
stepId: string;
|
|
479
|
+
text: string;
|
|
480
|
+
startTimeMs: number;
|
|
481
|
+
endTimeMs: number;
|
|
482
|
+
estimatedDurationMs: number;
|
|
483
|
+
pauseBeforeMs?: number;
|
|
484
|
+
pauseAfterMs?: number;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Generated script JSON structure
|
|
488
|
+
*/
|
|
489
|
+
interface GeneratedScript {
|
|
490
|
+
demoName: string;
|
|
491
|
+
title: string;
|
|
492
|
+
generatedAt: string;
|
|
493
|
+
totalDurationMs: number;
|
|
494
|
+
segments: ScriptSegment$1[];
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Result of synthesizing a segment
|
|
498
|
+
*/
|
|
499
|
+
interface SynthesizedSegment {
|
|
500
|
+
stepId: string;
|
|
501
|
+
audioPath: string;
|
|
502
|
+
durationMs: number;
|
|
503
|
+
text: string;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Result of full voice synthesis
|
|
507
|
+
*/
|
|
508
|
+
interface VoiceSynthesisResult {
|
|
509
|
+
demoName: string;
|
|
510
|
+
segments: SynthesizedSegment[];
|
|
511
|
+
combinedAudioPath?: string;
|
|
512
|
+
soundEffectsPath?: string;
|
|
513
|
+
backgroundMusicPath?: string;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* ElevenLabs voice synthesizer for demo narration
|
|
517
|
+
*/
|
|
518
|
+
declare class VoiceSynthesizer {
|
|
519
|
+
private client;
|
|
520
|
+
private config;
|
|
521
|
+
constructor(config: VoiceSynthesisConfig);
|
|
522
|
+
/**
|
|
523
|
+
* List available voices (useful for finding voice IDs)
|
|
524
|
+
*/
|
|
525
|
+
listVoices(): Promise<Array<{
|
|
526
|
+
voiceId: string;
|
|
527
|
+
name: string;
|
|
528
|
+
category: string;
|
|
529
|
+
}>>;
|
|
530
|
+
/**
|
|
531
|
+
* Synthesize a single text segment to audio
|
|
532
|
+
*/
|
|
533
|
+
synthesizeSegment(text: string, outputPath: string, options?: {
|
|
534
|
+
stability?: number;
|
|
535
|
+
similarityBoost?: number;
|
|
536
|
+
style?: number;
|
|
537
|
+
useSpeakerBoost?: boolean;
|
|
538
|
+
}): Promise<{
|
|
539
|
+
durationMs: number;
|
|
540
|
+
}>;
|
|
541
|
+
/**
|
|
542
|
+
* Generate a sound effect from text description
|
|
543
|
+
*/
|
|
544
|
+
generateSoundEffect(description: string, outputPath: string, options?: {
|
|
545
|
+
durationSeconds?: number;
|
|
546
|
+
promptInfluence?: number;
|
|
547
|
+
retry?: RetryOptions;
|
|
548
|
+
}): Promise<void>;
|
|
549
|
+
/**
|
|
550
|
+
* Synthesize all segments from a script JSON file
|
|
551
|
+
*/
|
|
552
|
+
synthesizeScript(scriptPath: string, outputDir: string, options?: {
|
|
553
|
+
voiceSettings?: {
|
|
554
|
+
stability?: number;
|
|
555
|
+
similarityBoost?: number;
|
|
556
|
+
style?: number;
|
|
557
|
+
};
|
|
558
|
+
generateClickSounds?: boolean;
|
|
559
|
+
onProgress?: (current: number, total: number, stepId: string) => void;
|
|
560
|
+
maxConcurrency?: number;
|
|
561
|
+
retry?: RetryOptions;
|
|
562
|
+
}): Promise<VoiceSynthesisResult>;
|
|
563
|
+
/**
|
|
564
|
+
* Generate a UI click sound effect
|
|
565
|
+
*/
|
|
566
|
+
generateClickSound(outputPath: string): Promise<void>;
|
|
567
|
+
/**
|
|
568
|
+
* Generate ambient background music
|
|
569
|
+
*/
|
|
570
|
+
generateBackgroundMusic(outputPath: string, options?: {
|
|
571
|
+
style?: "corporate" | "tech" | "calm" | "upbeat";
|
|
572
|
+
durationSeconds?: number;
|
|
573
|
+
}): Promise<void>;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Create a timing manifest for video editing
|
|
577
|
+
* Maps audio files to their intended start times in the video
|
|
578
|
+
*/
|
|
579
|
+
interface AudioTimingManifest {
|
|
580
|
+
demoName: string;
|
|
581
|
+
segments: Array<{
|
|
582
|
+
stepId: string;
|
|
583
|
+
audioFile: string;
|
|
584
|
+
videoStartTimeMs: number;
|
|
585
|
+
audioDurationMs: number;
|
|
586
|
+
text: string;
|
|
587
|
+
}>;
|
|
588
|
+
soundEffects?: {
|
|
589
|
+
clickSound?: string;
|
|
590
|
+
};
|
|
591
|
+
backgroundMusic?: string;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Generate a timing manifest from synthesized results and original script
|
|
595
|
+
*/
|
|
596
|
+
declare function generateTimingManifest(scriptPath: string, synthesisResult: VoiceSynthesisResult, outputPath: string): Promise<AudioTimingManifest>;
|
|
597
|
+
/**
|
|
598
|
+
* Default export for easy instantiation
|
|
599
|
+
*/
|
|
600
|
+
declare function createVoiceSynthesizer(config: VoiceSynthesisConfig): VoiceSynthesizer;
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* A single segment of narration with timing information.
|
|
604
|
+
*/
|
|
605
|
+
interface ScriptSegment {
|
|
606
|
+
stepId: string;
|
|
607
|
+
text: string;
|
|
608
|
+
startTimeMs: number;
|
|
609
|
+
endTimeMs: number;
|
|
610
|
+
estimatedDurationMs: number;
|
|
611
|
+
pauseBeforeMs?: number;
|
|
612
|
+
pauseAfterMs?: number;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Video step boundary for splitting videos per step.
|
|
616
|
+
*/
|
|
617
|
+
interface StepBoundary {
|
|
618
|
+
stepId: string;
|
|
619
|
+
stepIndex: number;
|
|
620
|
+
videoStartMs: number;
|
|
621
|
+
videoEndMs: number;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Complete script output with metadata.
|
|
625
|
+
*/
|
|
626
|
+
interface ScriptOutput {
|
|
627
|
+
demoName: string;
|
|
628
|
+
title: string;
|
|
629
|
+
generatedAt: string;
|
|
630
|
+
totalDurationMs: number;
|
|
631
|
+
segments: ScriptSegment[];
|
|
632
|
+
stepBoundaries: StepBoundary[];
|
|
633
|
+
videoMetadata?: {
|
|
634
|
+
videoPath: string;
|
|
635
|
+
durationMs: number;
|
|
636
|
+
alignmentOffsetMs: number;
|
|
637
|
+
recordingStartTimeMs?: number;
|
|
638
|
+
alignedAt?: string;
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Tracks narration segments during demo execution.
|
|
643
|
+
*/
|
|
644
|
+
declare class ScriptGenerator {
|
|
645
|
+
private segments;
|
|
646
|
+
private stepBoundaries;
|
|
647
|
+
private currentStepId;
|
|
648
|
+
private currentStepStartMs;
|
|
649
|
+
private demoName;
|
|
650
|
+
private title;
|
|
651
|
+
private startTime;
|
|
652
|
+
constructor(demoName: string, title: string, startTimeMs?: number);
|
|
653
|
+
/**
|
|
654
|
+
* Marks the start of a step (for video splitting).
|
|
655
|
+
*/
|
|
656
|
+
startStep(stepId: string): void;
|
|
657
|
+
/**
|
|
658
|
+
* Marks the end of all steps (call at demo completion).
|
|
659
|
+
*/
|
|
660
|
+
finishAllSteps(): void;
|
|
661
|
+
/**
|
|
662
|
+
* Estimates reading duration for text.
|
|
663
|
+
* Based on ~150 words per minute average speaking rate.
|
|
664
|
+
*/
|
|
665
|
+
private estimateReadingDuration;
|
|
666
|
+
/**
|
|
667
|
+
* Adds a narration segment with automatic timing.
|
|
668
|
+
*/
|
|
669
|
+
addSegment(stepId: string, text: string, options?: {
|
|
670
|
+
timing?: "on_start" | "on_complete";
|
|
671
|
+
pauseBeforeMs?: number;
|
|
672
|
+
pauseAfterMs?: number;
|
|
673
|
+
}): void;
|
|
674
|
+
/**
|
|
675
|
+
* Updates the end time of the last segment.
|
|
676
|
+
* Call this when a step completes to capture actual duration.
|
|
677
|
+
*/
|
|
678
|
+
completeLastSegment(): void;
|
|
679
|
+
/**
|
|
680
|
+
* Generates the complete script output.
|
|
681
|
+
*/
|
|
682
|
+
getOutput(): ScriptOutput;
|
|
683
|
+
/**
|
|
684
|
+
* Exports script as JSON.
|
|
685
|
+
*/
|
|
686
|
+
exportJSON(outputPath: string): Promise<void>;
|
|
687
|
+
/**
|
|
688
|
+
* Exports script as SRT subtitle format.
|
|
689
|
+
*/
|
|
690
|
+
exportSRT(outputPath: string): Promise<void>;
|
|
691
|
+
/**
|
|
692
|
+
* Exports script in a format suitable for AI voice generation services.
|
|
693
|
+
* Includes SSML-like pause markers.
|
|
694
|
+
*/
|
|
695
|
+
exportAIVoiceScript(outputPath: string): Promise<void>;
|
|
696
|
+
/**
|
|
697
|
+
* Exports script as human-readable markdown for voice actors.
|
|
698
|
+
*/
|
|
699
|
+
exportMarkdown(outputPath: string): Promise<void>;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Creates a new ScriptGenerator instance.
|
|
703
|
+
*/
|
|
704
|
+
declare function createScriptGenerator(demoName: string, title: string, startTimeMs?: number): ScriptGenerator;
|
|
705
|
+
|
|
706
|
+
export { type ActionType, type AudioTimingManifest, DEMO_SCHEMA_VERSION, type DemoAction, type DemoContext, type DemoDefinition, type DemoResult, type DemoStep, type DragConfig, type ElementInfo, type GeneratedScript, type PickerResult, type PrivacyConfig, type RecordedInteraction, type RecordingState, type RunDemoOptions, ScriptGenerator, type ScriptOutput, type ScriptSegment, type SelectorCandidate, type SelectorConfig, type SelectorStrategy, type StepBoundary, type StepTarget, type StepTiming, type SynthesizedSegment, type TestSelectorResponse, type ScriptSegment$1 as VoiceScriptSegment, type VoiceSynthesisConfig, type VoiceSynthesisResult, VoiceSynthesizer, type WaitCondition, createClickAction, createDragAction, createEmptyDemo, createEmptyStep, createHoverAction, createNavigateAction, createScriptGenerator, createScrollAction, createScrollToAction, createTypeAction, createUploadAction, createVoiceSynthesizer, createWaitAction, createWaitForAction, demoClick, demoDefinitionSchema, demoHover, demoType, discoverDemos, formatValidationError, generateTimingManifest, highlightElement, injectCursorOverlay, loadDemoDefinition, moveCursorTo, parseDemoDefinition, parseFromYAML, removeCursorOverlay, resolvePath, resolveTarget, runDemo, runDemoFromFile, safeParseDemoDefinition, serializeToYAML, triggerClickRipple, validateDemoDefinition };
|