demowright 2.0.9 → 2.2.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/dist/config.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{setup-BwdzChHS.mjs → setup-Ce4X1N16.mjs} +0 -1
- package/dist/setup.mjs +1 -1
- package/dist/video-script.d.mts +12 -1
- package/dist/video-script.mjs +38 -14
- package/package.json +7 -3
package/dist/config.mjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as AudioWriter, t as applyHud } from "./setup-
|
|
1
|
+
import { r as AudioWriter, t as applyHud } from "./setup-Ce4X1N16.mjs";
|
|
2
2
|
import { i as getGlobalTtsProvider, s as init_hud_registry } from "./hud-registry-Wfd4b4Nu.mjs";
|
|
3
3
|
import { buildFfmpegCommand, createVideoScript, t as init_video_script } from "./video-script.mjs";
|
|
4
4
|
import { annotate, caption, clickEl, hudWait, moveTo, moveToEl, narrate, subtitle, typeKeys } from "./helpers.mjs";
|
|
@@ -622,7 +622,6 @@ function buildAndSaveAudioTrack(segments, outputPath, contextStartMs, browserAud
|
|
|
622
622
|
for (const seg of segments) {
|
|
623
623
|
const dOff = seg.wavBuf.indexOf("data") + 8;
|
|
624
624
|
if (dOff < 8) continue;
|
|
625
|
-
seg.wavBuf.readUInt32LE(24);
|
|
626
625
|
const ch = seg.wavBuf.readUInt16LE(22);
|
|
627
626
|
const pcmData = seg.wavBuf.subarray(dOff);
|
|
628
627
|
const sampleCount = pcmData.length / 2;
|
package/dist/setup.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as defaultOptions, t as applyHud } from "./setup-
|
|
1
|
+
import { n as defaultOptions, t as applyHud } from "./setup-Ce4X1N16.mjs";
|
|
2
2
|
export { applyHud, defaultOptions };
|
package/dist/video-script.d.mts
CHANGED
|
@@ -10,6 +10,9 @@ interface TitleStep {
|
|
|
10
10
|
kind: "title";
|
|
11
11
|
text: string;
|
|
12
12
|
subtitle?: string;
|
|
13
|
+
/** Optional TTS narration read aloud over the card. When set, card
|
|
14
|
+
* duration becomes max(durationMs, narration audio length). */
|
|
15
|
+
narration?: string;
|
|
13
16
|
durationMs: number;
|
|
14
17
|
background?: string;
|
|
15
18
|
}
|
|
@@ -27,6 +30,9 @@ interface OutroStep {
|
|
|
27
30
|
kind: "outro";
|
|
28
31
|
text: string;
|
|
29
32
|
subtitle?: string;
|
|
33
|
+
/** Optional TTS narration read aloud over the card. When set, card
|
|
34
|
+
* duration becomes max(durationMs, narration audio length). */
|
|
35
|
+
narration?: string;
|
|
30
36
|
durationMs: number;
|
|
31
37
|
background?: string;
|
|
32
38
|
}
|
|
@@ -53,6 +59,8 @@ interface VideoScriptResult {
|
|
|
53
59
|
}
|
|
54
60
|
interface TitleOptions {
|
|
55
61
|
subtitle?: string;
|
|
62
|
+
/** TTS narration read aloud over the card overlay. Duration auto-extends to fit. */
|
|
63
|
+
narration?: string;
|
|
56
64
|
durationMs?: number;
|
|
57
65
|
/** CSS background — default: radial gradient */
|
|
58
66
|
background?: string;
|
|
@@ -60,6 +68,8 @@ interface TitleOptions {
|
|
|
60
68
|
interface OutroOptions {
|
|
61
69
|
text?: string;
|
|
62
70
|
subtitle?: string;
|
|
71
|
+
/** TTS narration read aloud over the card overlay. Duration auto-extends to fit. */
|
|
72
|
+
narration?: string;
|
|
63
73
|
durationMs?: number;
|
|
64
74
|
background?: string;
|
|
65
75
|
}
|
|
@@ -89,7 +99,7 @@ declare class VideoScriptImpl {
|
|
|
89
99
|
private static ttsCache;
|
|
90
100
|
/**
|
|
91
101
|
* Add a title card — full-screen overlay with text + optional subtitle.
|
|
92
|
-
*
|
|
102
|
+
* Pass `narration` in opts to have TTS voiceover during the card.
|
|
93
103
|
*/
|
|
94
104
|
title(text: string, opts?: TitleOptions): this;
|
|
95
105
|
/**
|
|
@@ -104,6 +114,7 @@ declare class VideoScriptImpl {
|
|
|
104
114
|
transition(type?: TransitionType, durationMs?: number): this;
|
|
105
115
|
/**
|
|
106
116
|
* Add an outro card — full-screen overlay, similar to title.
|
|
117
|
+
* Pass `narration` in opts to have TTS voiceover during the card.
|
|
107
118
|
*/
|
|
108
119
|
outro(opts?: OutroOptions): this;
|
|
109
120
|
/**
|
package/dist/video-script.mjs
CHANGED
|
@@ -170,8 +170,6 @@ function generateSrt(timeline) {
|
|
|
170
170
|
}
|
|
171
171
|
function generateChapters(timeline) {
|
|
172
172
|
return timeline.filter((e) => e.kind === "segment" || e.kind === "title" || e.kind === "outro").map((entry) => {
|
|
173
|
-
(entry.startMs / 1e3).toFixed(3);
|
|
174
|
-
((entry.startMs + entry.durationMs) / 1e3).toFixed(3);
|
|
175
173
|
return `[CHAPTER]\nTIMEBASE=1/1000\nSTART=${Math.round(entry.startMs)}\nEND=${Math.round(entry.startMs + entry.durationMs)}\ntitle=${entry.text.slice(0, 80)}`;
|
|
176
174
|
}).join("\n\n");
|
|
177
175
|
}
|
|
@@ -269,13 +267,14 @@ var init_video_script = __esmMin((() => {
|
|
|
269
267
|
static ttsCache = /* @__PURE__ */ new Map();
|
|
270
268
|
/**
|
|
271
269
|
* Add a title card — full-screen overlay with text + optional subtitle.
|
|
272
|
-
*
|
|
270
|
+
* Pass `narration` in opts to have TTS voiceover during the card.
|
|
273
271
|
*/
|
|
274
272
|
title(text, opts) {
|
|
275
273
|
this.steps.push({
|
|
276
274
|
kind: "title",
|
|
277
275
|
text,
|
|
278
276
|
subtitle: opts?.subtitle,
|
|
277
|
+
narration: opts?.narration,
|
|
279
278
|
durationMs: opts?.durationMs ?? 4e3,
|
|
280
279
|
background: opts?.background
|
|
281
280
|
});
|
|
@@ -307,12 +306,14 @@ var init_video_script = __esmMin((() => {
|
|
|
307
306
|
}
|
|
308
307
|
/**
|
|
309
308
|
* Add an outro card — full-screen overlay, similar to title.
|
|
309
|
+
* Pass `narration` in opts to have TTS voiceover during the card.
|
|
310
310
|
*/
|
|
311
311
|
outro(opts) {
|
|
312
312
|
this.steps.push({
|
|
313
313
|
kind: "outro",
|
|
314
314
|
text: opts?.text ?? "Thanks for watching!",
|
|
315
315
|
subtitle: opts?.subtitle,
|
|
316
|
+
narration: opts?.narration,
|
|
316
317
|
durationMs: opts?.durationMs ?? 4e3,
|
|
317
318
|
background: opts?.background
|
|
318
319
|
});
|
|
@@ -328,11 +329,20 @@ var init_video_script = __esmMin((() => {
|
|
|
328
329
|
else if (typeof pageOrProvider === "function" || typeof pageOrProvider === "string") provider = pageOrProvider;
|
|
329
330
|
else provider = getTtsProvider(pageOrProvider);
|
|
330
331
|
if (!provider) return;
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
const ttsSteps = [];
|
|
333
|
+
let segIdx2 = 0;
|
|
334
|
+
for (let i = 0; i < this.steps.length; i++) {
|
|
335
|
+
const s = this.steps[i];
|
|
336
|
+
if (s.kind === "segment") ttsSteps.push({
|
|
337
|
+
id: `step-${segIdx2++}`,
|
|
338
|
+
text: s.text
|
|
339
|
+
});
|
|
340
|
+
else if ((s.kind === "title" || s.kind === "outro") && s.narration) ttsSteps.push({
|
|
341
|
+
id: `card-${i}`,
|
|
342
|
+
text: s.narration
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const results = await Promise.allSettled(ttsSteps.map(async (step) => {
|
|
336
346
|
const cached = VideoScriptImpl.ttsCache.get(step.text);
|
|
337
347
|
if (cached) return {
|
|
338
348
|
id: step.id,
|
|
@@ -354,7 +364,7 @@ var init_video_script = __esmMin((() => {
|
|
|
354
364
|
durationMs: r.value.durationMs
|
|
355
365
|
};
|
|
356
366
|
this.prepared.set(r.value.id, seg);
|
|
357
|
-
const step =
|
|
367
|
+
const step = ttsSteps[idx];
|
|
358
368
|
if (step) VideoScriptImpl.ttsCache.set(step.text, seg);
|
|
359
369
|
}
|
|
360
370
|
idx++;
|
|
@@ -366,7 +376,7 @@ var init_video_script = __esmMin((() => {
|
|
|
366
376
|
* for deferred track building at context close (setup.ts).
|
|
367
377
|
*/
|
|
368
378
|
async run(page) {
|
|
369
|
-
const { timeline, totalMs
|
|
379
|
+
const { timeline, totalMs } = await this.executeSteps(page);
|
|
370
380
|
return {
|
|
371
381
|
timeline,
|
|
372
382
|
totalMs,
|
|
@@ -452,14 +462,28 @@ var init_video_script = __esmMin((() => {
|
|
|
452
462
|
const stepStartMs = Date.now();
|
|
453
463
|
if (step.kind === "title" || step.kind === "outro") {
|
|
454
464
|
const bg = step.background ?? DEFAULT_BG;
|
|
455
|
-
|
|
456
|
-
|
|
465
|
+
const cardTts = step.narration ? this.prepared.get(`card-${i}`) : void 0;
|
|
466
|
+
const effectiveDuration = cardTts ? Math.max(step.durationMs, cardTts.durationMs + 500) : step.durationMs;
|
|
467
|
+
if (active) showCard(page, step.text, step.subtitle, effectiveDuration, bg).catch(() => {});
|
|
468
|
+
if (active && cardTts) {
|
|
469
|
+
const offsetMs = Date.now() - planStartMs;
|
|
470
|
+
audioSegments.push({
|
|
471
|
+
offsetMs,
|
|
472
|
+
wavBuf: cardTts.wavBuf
|
|
473
|
+
});
|
|
474
|
+
storeAudioSegment(page, {
|
|
475
|
+
timestampMs: Date.now(),
|
|
476
|
+
wavBuf: cardTts.wavBuf
|
|
477
|
+
});
|
|
478
|
+
showCaption(page, step.narration, cardTts.durationMs).catch(() => {});
|
|
479
|
+
}
|
|
480
|
+
await page.waitForTimeout(effectiveDuration);
|
|
457
481
|
timeline.push({
|
|
458
482
|
id: stepIds[i],
|
|
459
483
|
kind: step.kind,
|
|
460
|
-
text: step.text,
|
|
484
|
+
text: step.narration ?? step.text,
|
|
461
485
|
startMs: stepStartMs - planStartMs,
|
|
462
|
-
durationMs:
|
|
486
|
+
durationMs: effectiveDuration,
|
|
463
487
|
actionMs: 0,
|
|
464
488
|
overrunMs: 0
|
|
465
489
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "demowright",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Playwright video production plugin — cursor overlay, keystroke badges, TTS narration, and narration-driven video scripts for test recordings",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,13 +42,17 @@
|
|
|
42
42
|
"build": "tsdown",
|
|
43
43
|
"test": "bunx playwright test",
|
|
44
44
|
"demo": "bunx playwright test tests/demo.spec.ts --headed",
|
|
45
|
-
"prepublishOnly": "tsdown"
|
|
45
|
+
"prepublishOnly": "tsdown",
|
|
46
|
+
"lint": "oxlint src",
|
|
47
|
+
"typecheck": "tsgo --noEmit"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"@types/node": "^25.5.2",
|
|
49
51
|
"@typescript/native-preview": "^7.0.0-dev.20260405.1",
|
|
52
|
+
"oxlint": "^1.59.0",
|
|
50
53
|
"semantic-release": "^25.0.3",
|
|
51
|
-
"tsdown": "^0.21.7"
|
|
54
|
+
"tsdown": "^0.21.7",
|
|
55
|
+
"typescript": "^6.0.2"
|
|
52
56
|
},
|
|
53
57
|
"peerDependencies": {
|
|
54
58
|
"@playwright/test": ">=1.40.0"
|