demowright 0.1.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/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/auto-annotate.d.mts +6 -0
- package/dist/auto-annotate.mjs +9 -0
- package/dist/chunk-C0p4GxOx.mjs +29 -0
- package/dist/config.d.mts +7 -0
- package/dist/config.mjs +36 -0
- package/dist/helpers.d.mts +95 -0
- package/dist/helpers.mjs +299 -0
- package/dist/hud-registry-CptkyV32.mjs +90 -0
- package/dist/index.d.mts +54044 -0
- package/dist/index.mjs +29 -0
- package/dist/setup-CfPylVYx.mjs +652 -0
- package/dist/setup-D-Ut4FYK.d.mts +63 -0
- package/dist/setup.d.mts +2 -0
- package/dist/setup.mjs +2 -0
- package/dist/video-script.d.mts +134 -0
- package/dist/video-script.mjs +529 -0
- package/media/01-dashboard.jpg +0 -0
- package/media/02-code-editor.jpg +0 -0
- package/media/03-checkout.jpg +0 -0
- package/package.json +61 -0
- package/register.cjs +145 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { BrowserContext } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
//#region src/hud-overlay.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Client-side HUD overlay scripts.
|
|
6
|
+
*
|
|
7
|
+
* Split into two parts for maximum compatibility:
|
|
8
|
+
* 1. Listener script — registered via addInitScript (no DOM mutation, runs early)
|
|
9
|
+
* 2. DOM injection script — executed via page.evaluate after navigation
|
|
10
|
+
*/
|
|
11
|
+
type HudOptions = {
|
|
12
|
+
cursor: boolean;
|
|
13
|
+
keyboard: boolean;
|
|
14
|
+
cursorStyle: "default" | "dot" | "crosshair";
|
|
15
|
+
keyFadeMs: number;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/audio-writer.d.ts
|
|
19
|
+
declare class AudioWriter {
|
|
20
|
+
private chunks;
|
|
21
|
+
private sampleRate;
|
|
22
|
+
private channels;
|
|
23
|
+
/**
|
|
24
|
+
* Called from the browser via page.exposeFunction.
|
|
25
|
+
* Receives interleaved stereo float32 samples.
|
|
26
|
+
*/
|
|
27
|
+
addChunk(samples: number[], sampleRate: number): void;
|
|
28
|
+
/** Total samples collected (interleaved, so / channels for per-channel) */
|
|
29
|
+
get totalSamples(): number;
|
|
30
|
+
get duration(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Write collected audio to a WAV file.
|
|
33
|
+
*/
|
|
34
|
+
save(filePath: string): void;
|
|
35
|
+
/** Reset for reuse */
|
|
36
|
+
clear(): void;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/setup.d.ts
|
|
40
|
+
/**
|
|
41
|
+
* TTS provider for narrate().
|
|
42
|
+
* - string: URL template — %s is replaced with encodeURIComponent(text).
|
|
43
|
+
* Must return audio (mp3/wav/ogg).
|
|
44
|
+
* Example: "https://api.example.com/tts?text=%s"
|
|
45
|
+
* - function: receives text, returns audio Buffer/ArrayBuffer.
|
|
46
|
+
* - false: disabled (falls back to speechSynthesis, which may not work headless).
|
|
47
|
+
*/
|
|
48
|
+
type TtsProvider = false | string | ((text: string) => Promise<Buffer | ArrayBuffer>);
|
|
49
|
+
type QaHudOptions = HudOptions & {
|
|
50
|
+
actionDelay: number; /** Enable audio capture via Web Audio API. Set to a file path to save WAV, or `true` for auto-path. */
|
|
51
|
+
audio: boolean | string; /** TTS provider for narrate(). See TtsProvider type. */
|
|
52
|
+
tts: TtsProvider; /** Automatically annotate (caption + TTS) the test title at the start of each test. */
|
|
53
|
+
autoAnnotate: boolean; /** Output directory for rendered videos. Default: `.demowright` */
|
|
54
|
+
outputDir: string;
|
|
55
|
+
};
|
|
56
|
+
declare const defaultOptions: QaHudOptions;
|
|
57
|
+
/**
|
|
58
|
+
* Apply the demowright HUD to an existing BrowserContext.
|
|
59
|
+
* Returns an AudioWriter if audio capture is enabled (call .save() after test).
|
|
60
|
+
*/
|
|
61
|
+
declare function applyHud(context: BrowserContext, options?: Partial<QaHudOptions>): Promise<AudioWriter | undefined>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { AudioWriter as a, defaultOptions as i, TtsProvider as n, applyHud as r, QaHudOptions as t };
|
package/dist/setup.d.mts
ADDED
package/dist/setup.mjs
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Page } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
//#region src/video-script.d.ts
|
|
4
|
+
type TtsProviderType = string | ((text: string) => Promise<Buffer | ArrayBuffer>);
|
|
5
|
+
/** Pace function — call between actions to auto-distribute remaining narration time. */
|
|
6
|
+
type PaceFn = () => Promise<void>;
|
|
7
|
+
type SegmentAction = (pace: PaceFn) => Promise<void>;
|
|
8
|
+
type TransitionType = "fade" | "crossfade" | "none";
|
|
9
|
+
interface TitleStep {
|
|
10
|
+
kind: "title";
|
|
11
|
+
text: string;
|
|
12
|
+
subtitle?: string;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
background?: string;
|
|
15
|
+
}
|
|
16
|
+
interface SegmentStep {
|
|
17
|
+
kind: "segment";
|
|
18
|
+
text: string;
|
|
19
|
+
action?: SegmentAction;
|
|
20
|
+
}
|
|
21
|
+
interface TransitionStep {
|
|
22
|
+
kind: "transition";
|
|
23
|
+
type: TransitionType;
|
|
24
|
+
durationMs: number;
|
|
25
|
+
}
|
|
26
|
+
interface OutroStep {
|
|
27
|
+
kind: "outro";
|
|
28
|
+
text: string;
|
|
29
|
+
subtitle?: string;
|
|
30
|
+
durationMs: number;
|
|
31
|
+
background?: string;
|
|
32
|
+
}
|
|
33
|
+
type ScriptStep = TitleStep | SegmentStep | TransitionStep | OutroStep;
|
|
34
|
+
interface TimelineEntry {
|
|
35
|
+
id: string;
|
|
36
|
+
kind: ScriptStep["kind"];
|
|
37
|
+
text: string;
|
|
38
|
+
startMs: number;
|
|
39
|
+
durationMs: number;
|
|
40
|
+
actionMs: number;
|
|
41
|
+
overrunMs: number;
|
|
42
|
+
}
|
|
43
|
+
interface VideoScriptResult {
|
|
44
|
+
timeline: TimelineEntry[];
|
|
45
|
+
totalMs: number;
|
|
46
|
+
srtContent: string;
|
|
47
|
+
srtPath?: string;
|
|
48
|
+
chaptersContent: string;
|
|
49
|
+
mp4Path?: string;
|
|
50
|
+
wavPath?: string;
|
|
51
|
+
/** Full ffmpeg command for post-processing (printed when render completes). */
|
|
52
|
+
ffmpegCommand?: string;
|
|
53
|
+
}
|
|
54
|
+
interface TitleOptions {
|
|
55
|
+
subtitle?: string;
|
|
56
|
+
durationMs?: number;
|
|
57
|
+
/** CSS background — default: radial gradient */
|
|
58
|
+
background?: string;
|
|
59
|
+
}
|
|
60
|
+
interface OutroOptions {
|
|
61
|
+
text?: string;
|
|
62
|
+
subtitle?: string;
|
|
63
|
+
durationMs?: number;
|
|
64
|
+
background?: string;
|
|
65
|
+
}
|
|
66
|
+
interface RenderOptions {
|
|
67
|
+
/** Output directory for generated files. Default: tmp/ */
|
|
68
|
+
outputDir?: string;
|
|
69
|
+
/** Base name for output files (without extension). Default: auto-generated */
|
|
70
|
+
baseName?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a complete ffmpeg command that:
|
|
74
|
+
* 1. Muxes video + audio
|
|
75
|
+
* 2. Applies fade transitions at the correct offsets
|
|
76
|
+
* 3. Burns in SRT subtitles
|
|
77
|
+
* 4. Embeds chapter metadata
|
|
78
|
+
*/
|
|
79
|
+
declare function buildFfmpegCommand(videoPath: string, wavPath: string, srtPath: string, chaptersPath: string, mp4Path: string, timeline: {
|
|
80
|
+
kind: string;
|
|
81
|
+
type?: string;
|
|
82
|
+
startMs: number;
|
|
83
|
+
durationMs: number;
|
|
84
|
+
}[]): string;
|
|
85
|
+
declare class VideoScriptImpl {
|
|
86
|
+
private steps;
|
|
87
|
+
private counter;
|
|
88
|
+
private prepared;
|
|
89
|
+
private static ttsCache;
|
|
90
|
+
/**
|
|
91
|
+
* Add a title card — full-screen overlay with text + optional subtitle.
|
|
92
|
+
* No TTS narration by default (silent title card).
|
|
93
|
+
*/
|
|
94
|
+
title(text: string, opts?: TitleOptions): this;
|
|
95
|
+
/**
|
|
96
|
+
* Add a narrated segment — TTS audio drives timing, callback runs paced actions.
|
|
97
|
+
* Same as NarrationPlan's `.annotate()` but named `.segment()` for clarity.
|
|
98
|
+
*/
|
|
99
|
+
segment(text: string, action?: SegmentAction): this;
|
|
100
|
+
/**
|
|
101
|
+
* Add a transition between segments.
|
|
102
|
+
* Applied as an ffmpeg filter during render.
|
|
103
|
+
*/
|
|
104
|
+
transition(type?: TransitionType, durationMs?: number): this;
|
|
105
|
+
/**
|
|
106
|
+
* Add an outro card — full-screen overlay, similar to title.
|
|
107
|
+
*/
|
|
108
|
+
outro(opts?: OutroOptions): this;
|
|
109
|
+
/**
|
|
110
|
+
* Pre-generate all TTS audio for segment steps.
|
|
111
|
+
* Call before page.goto() so video recording doesn't include TTS wait time.
|
|
112
|
+
*/
|
|
113
|
+
prepare(pageOrProvider?: Page | TtsProviderType): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Execute the script steps — run each step timed to its narration duration.
|
|
116
|
+
* Returns timeline + totalMs. Audio segments are stored in the registry
|
|
117
|
+
* for deferred track building at context close (setup.ts).
|
|
118
|
+
*/
|
|
119
|
+
run(page: Page): Promise<VideoScriptResult>;
|
|
120
|
+
/**
|
|
121
|
+
* Execute the script and produce final output files:
|
|
122
|
+
* WAV audio track, SRT subtitles, chapter metadata.
|
|
123
|
+
* Audio mux with video happens at context close (setup.ts).
|
|
124
|
+
*/
|
|
125
|
+
render(page: Page, opts?: RenderOptions): Promise<VideoScriptResult>;
|
|
126
|
+
private executeSteps;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Create a video script — narration-driven video production with title cards,
|
|
130
|
+
* transitions, auto-subtitles, and chapter markers.
|
|
131
|
+
*/
|
|
132
|
+
declare function createVideoScript(): VideoScriptImpl;
|
|
133
|
+
//#endregion
|
|
134
|
+
export { OutroOptions, PaceFn, RenderOptions, TimelineEntry, TitleOptions, VideoScriptResult, buildFfmpegCommand, createVideoScript };
|