screenwright 0.1.45 → 0.2.1

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 (67) hide show
  1. package/dist/src/commands/compose.d.ts.map +1 -1
  2. package/dist/src/commands/compose.js +66 -41
  3. package/dist/src/commands/compose.js.map +1 -1
  4. package/dist/src/commands/preview.d.ts.map +1 -1
  5. package/dist/src/commands/preview.js +9 -12
  6. package/dist/src/commands/preview.js.map +1 -1
  7. package/dist/src/composition/DemoVideo.d.ts.map +1 -1
  8. package/dist/src/composition/DemoVideo.js +24 -78
  9. package/dist/src/composition/DemoVideo.js.map +1 -1
  10. package/dist/src/composition/frame-resolve.d.ts +37 -0
  11. package/dist/src/composition/frame-resolve.d.ts.map +1 -0
  12. package/dist/src/composition/frame-resolve.js +114 -0
  13. package/dist/src/composition/frame-resolve.js.map +1 -0
  14. package/dist/src/composition/remotion-root.d.ts.map +1 -1
  15. package/dist/src/composition/remotion-root.js +7 -14
  16. package/dist/src/composition/remotion-root.js.map +1 -1
  17. package/dist/src/composition/render.d.ts.map +1 -1
  18. package/dist/src/composition/render.js +2 -6
  19. package/dist/src/composition/render.js.map +1 -1
  20. package/dist/src/index.d.ts +1 -1
  21. package/dist/src/index.d.ts.map +1 -1
  22. package/dist/src/runtime/action-helpers.d.ts +15 -5
  23. package/dist/src/runtime/action-helpers.d.ts.map +1 -1
  24. package/dist/src/runtime/action-helpers.js +218 -60
  25. package/dist/src/runtime/action-helpers.js.map +1 -1
  26. package/dist/src/runtime/instrumented-page.d.ts +3 -2
  27. package/dist/src/runtime/instrumented-page.d.ts.map +1 -1
  28. package/dist/src/runtime/instrumented-page.js +105 -101
  29. package/dist/src/runtime/instrumented-page.js.map +1 -1
  30. package/dist/src/runtime/narration-preprocess.d.ts +30 -0
  31. package/dist/src/runtime/narration-preprocess.d.ts.map +1 -0
  32. package/dist/src/runtime/narration-preprocess.js +79 -0
  33. package/dist/src/runtime/narration-preprocess.js.map +1 -0
  34. package/dist/src/runtime/timeline-collector.d.ts +1 -7
  35. package/dist/src/runtime/timeline-collector.d.ts.map +1 -1
  36. package/dist/src/runtime/timeline-collector.js +2 -17
  37. package/dist/src/runtime/timeline-collector.js.map +1 -1
  38. package/dist/src/timeline/schema.d.ts +143 -162
  39. package/dist/src/timeline/schema.d.ts.map +1 -1
  40. package/dist/src/timeline/schema.js +12 -18
  41. package/dist/src/timeline/schema.js.map +1 -1
  42. package/dist/src/timeline/types.d.ts +15 -18
  43. package/dist/src/timeline/types.d.ts.map +1 -1
  44. package/dist/src/timeline/types.js.map +1 -1
  45. package/dist/src/version.d.ts +1 -1
  46. package/dist/src/version.d.ts.map +1 -1
  47. package/dist/src/version.js +1 -1
  48. package/dist/src/version.js.map +1 -1
  49. package/dist/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +1 -1
  51. package/skill/SKILL.md +3 -3
  52. package/dist/src/composition/SceneSlide.d.ts +0 -12
  53. package/dist/src/composition/SceneSlide.d.ts.map +0 -1
  54. package/dist/src/composition/SceneSlide.js +0 -71
  55. package/dist/src/composition/SceneSlide.js.map +0 -1
  56. package/dist/src/composition/frame-lookup.d.ts +0 -8
  57. package/dist/src/composition/frame-lookup.d.ts.map +0 -1
  58. package/dist/src/composition/frame-lookup.js +0 -26
  59. package/dist/src/composition/frame-lookup.js.map +0 -1
  60. package/dist/src/composition/time-remap.d.ts +0 -87
  61. package/dist/src/composition/time-remap.d.ts.map +0 -1
  62. package/dist/src/composition/time-remap.js +0 -218
  63. package/dist/src/composition/time-remap.js.map +0 -1
  64. package/dist/src/voiceover/narration-timing.d.ts +0 -18
  65. package/dist/src/voiceover/narration-timing.d.ts.map +0 -1
  66. package/dist/src/voiceover/narration-timing.js +0 -40
  67. package/dist/src/voiceover/narration-timing.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenwright",
3
- "version": "0.1.45",
3
+ "version": "0.2.1",
4
4
  "description": "Turn Playwright E2E tests into polished product demo videos",
5
5
  "license": "MIT",
6
6
  "author": "Guillaume Dupuy",
package/skill/SKILL.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: screenwright
3
3
  description: Turn Playwright E2E tests into polished product demo videos
4
4
  user_invocable: true
5
- version: 0.1.45
5
+ version: 0.2.1
6
6
  ---
7
7
 
8
8
  # Screenwright
@@ -16,8 +16,8 @@ Check if the CLI is available and compatible:
16
16
  screenwright --version || npx screenwright --version
17
17
  ```
18
18
 
19
- This skill requires CLI version **0.1.x**. If the CLI is not installed or the major/minor version doesn't match, tell the user:
20
- > Install the compatible version: `npm install -g screenwright@0.1`
19
+ This skill requires CLI version **0.2.x**. If the CLI is not installed or the major/minor version doesn't match, tell the user:
20
+ > Install the compatible version: `npm install -g screenwright@0.2`
21
21
  > Then run `screenwright init` to download the voice model.
22
22
 
23
23
  ## Output Directory
@@ -1,12 +0,0 @@
1
- import React from 'react';
2
- interface Props {
3
- title: string;
4
- description?: string;
5
- brandColor: string;
6
- textColor: string;
7
- fontFamily?: string;
8
- titleFontSize?: number;
9
- }
10
- export declare const SceneSlide: React.FC<Props>;
11
- export {};
12
- //# sourceMappingURL=SceneSlide.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SceneSlide.d.ts","sourceRoot":"","sources":["../../../src/composition/SceneSlide.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAiBnD,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAwGtC,CAAC"}
@@ -1,71 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from 'react';
3
- import { delayRender, continueRender } from 'remotion';
4
- const SYSTEM_FONTS = 'system-ui, -apple-system, sans-serif';
5
- const FONT_TIMEOUT_MS = 5000;
6
- export const SceneSlide = ({ title, description, brandColor, textColor, fontFamily, titleFontSize = 64, }) => {
7
- const [handle] = useState(() => fontFamily ? delayRender('Loading font') : null);
8
- useEffect(() => {
9
- if (!fontFamily || !handle)
10
- return;
11
- const encoded = encodeURIComponent(fontFamily);
12
- const link = document.createElement('link');
13
- link.rel = 'stylesheet';
14
- link.href = `https://fonts.googleapis.com/css2?family=${encoded}&display=swap`;
15
- const timeout = setTimeout(() => {
16
- console.warn(`Font "${fontFamily}" timed out after ${FONT_TIMEOUT_MS}ms, using fallback`);
17
- continueRender(handle);
18
- }, FONT_TIMEOUT_MS);
19
- link.onload = () => {
20
- document.fonts.ready.then(() => {
21
- clearTimeout(timeout);
22
- continueRender(handle);
23
- });
24
- };
25
- link.onerror = () => {
26
- console.warn(`Failed to load font "${fontFamily}", using fallback`);
27
- clearTimeout(timeout);
28
- continueRender(handle);
29
- };
30
- document.head.appendChild(link);
31
- return () => {
32
- clearTimeout(timeout);
33
- document.head.removeChild(link);
34
- };
35
- }, [fontFamily, handle]);
36
- const resolvedFont = fontFamily ? `"${fontFamily}", ${SYSTEM_FONTS}` : SYSTEM_FONTS;
37
- return (_jsx("div", { style: {
38
- position: 'absolute',
39
- inset: 0,
40
- display: 'flex',
41
- flexDirection: 'column',
42
- alignItems: 'center',
43
- justifyContent: 'center',
44
- backgroundColor: brandColor,
45
- fontFamily: resolvedFont,
46
- }, children: _jsxs("div", { style: {
47
- textAlign: 'center',
48
- padding: '0 10%',
49
- }, children: [_jsx("h1", { style: {
50
- color: textColor,
51
- fontSize: titleFontSize,
52
- fontWeight: 700,
53
- margin: 0,
54
- lineHeight: 1.2,
55
- }, children: title }), description && (_jsxs(_Fragment, { children: [_jsx("div", { style: {
56
- width: 80,
57
- height: 4,
58
- backgroundColor: textColor,
59
- opacity: 0.4,
60
- margin: '24px auto',
61
- borderRadius: 2,
62
- } }), _jsx("p", { style: {
63
- color: textColor,
64
- fontSize: Math.round(titleFontSize * 0.44),
65
- fontWeight: 400,
66
- margin: 0,
67
- opacity: 0.85,
68
- lineHeight: 1.5,
69
- }, children: description })] }))] }) }));
70
- };
71
- //# sourceMappingURL=SceneSlide.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SceneSlide.js","sourceRoot":"","sources":["../../../src/composition/SceneSlide.tsx"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- import type { FrameEntry } from '../timeline/types.js';
2
- /**
3
- * Binary search for the frame with the largest timestampMs <= timeMs.
4
- * Returns first frame if timeMs is before all entries, last if after all.
5
- * Throws on empty manifest.
6
- */
7
- export declare function findClosestFrame(manifest: readonly FrameEntry[], timeMs: number): FrameEntry;
8
- //# sourceMappingURL=frame-lookup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frame-lookup.d.ts","sourceRoot":"","sources":["../../../src/composition/frame-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAmB5F"}
@@ -1,26 +0,0 @@
1
- /**
2
- * Binary search for the frame with the largest timestampMs <= timeMs.
3
- * Returns first frame if timeMs is before all entries, last if after all.
4
- * Throws on empty manifest.
5
- */
6
- export function findClosestFrame(manifest, timeMs) {
7
- if (manifest.length === 0)
8
- throw new Error('Empty frame manifest');
9
- let lo = 0;
10
- let hi = manifest.length - 1;
11
- if (timeMs <= manifest[0].timestampMs)
12
- return manifest[0];
13
- if (timeMs >= manifest[hi].timestampMs)
14
- return manifest[hi];
15
- while (lo <= hi) {
16
- const mid = (lo + hi) >>> 1;
17
- if (manifest[mid].timestampMs <= timeMs) {
18
- lo = mid + 1;
19
- }
20
- else {
21
- hi = mid - 1;
22
- }
23
- }
24
- return manifest[hi];
25
- }
26
- //# sourceMappingURL=frame-lookup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frame-lookup.js","sourceRoot":"","sources":["../../../src/composition/frame-lookup.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAA+B,EAAE,MAAc;IAC9E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAEnE,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAE7B,IAAI,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1D,IAAI,MAAM,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE5D,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,IAAI,MAAM,EAAE,CAAC;YACxC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC"}
@@ -1,87 +0,0 @@
1
- import type { SceneEvent, SceneSlideConfig, TimelineEvent, TransitionType } from '../timeline/types.js';
2
- export declare const DEFAULT_SLIDE_DURATION_MS = 2000;
3
- export declare function msToFrames(ms: number, fps: number): number;
4
- export interface ResolvedSlideScene {
5
- timestampMs: number;
6
- slideDurationMs: number;
7
- /** Position in the original events array (for stable sort order). */
8
- eventIndex: number;
9
- }
10
- export interface ResolvedTransition {
11
- timestampMs: number;
12
- transitionDurationMs: number;
13
- transition: TransitionType;
14
- /** Snapshot file path for exit content (before transition). */
15
- beforeSnapshot: string | null;
16
- /** Snapshot file path for entrance content (after transition). */
17
- afterSnapshot: string | null;
18
- /** Source time where the frame manifest has valid post-transition content.
19
- * When an adjacent action follows, this is its settledAtMs (skipping
20
- * garbage frames captured during page.goto / click settling). */
21
- afterSourceMs: number;
22
- /** True when a visual action exists before this transition. */
23
- hasContentBefore: boolean;
24
- /** True when a visual action exists after this transition. */
25
- hasContentAfter: boolean;
26
- /** Position in the original events array (for stable sort order). */
27
- eventIndex: number;
28
- }
29
- export interface SlideSegment {
30
- slideStartMs: number;
31
- slideEndMs: number;
32
- slideDurationMs: number;
33
- sceneTitle: string;
34
- sceneDescription?: string;
35
- slideConfig: SceneSlideConfig;
36
- }
37
- export interface TransitionSegment {
38
- outputStartMs: number;
39
- outputEndMs: number;
40
- durationMs: number;
41
- transition: TransitionType;
42
- beforeSnapshot: string | null;
43
- afterSnapshot: string | null;
44
- /** Index into the slides array for the adjacent slide before, or null. */
45
- adjacentSlideBefore: number | null;
46
- /** Index into the slides array for the adjacent slide after, or null. */
47
- adjacentSlideAfter: number | null;
48
- hasContentBefore: boolean;
49
- hasContentAfter: boolean;
50
- }
51
- /**
52
- * Filter scenes that have a `slide` field and resolve their duration.
53
- * Pass allEvents to get correct eventIndex for stable ordering with transitions.
54
- */
55
- export declare function resolveSlideScenes(scenes: SceneEvent[], allEvents?: readonly TimelineEvent[]): ResolvedSlideScene[];
56
- /**
57
- * Walk timeline events and resolve each transition's snapshot references.
58
- *
59
- * Uses **array position** to find surrounding actions. Adjacency matters:
60
- * if the next action is directly adjacent (no narration/wait/scene between,
61
- * cursor_target events are transparent), use its settledSnapshot. Otherwise
62
- * fall back to the transition's own pageSnapshot.
63
- */
64
- export declare function resolveTransitions(events: TimelineEvent[]): ResolvedTransition[];
65
- /**
66
- * Map an output-time position back to its source-time position.
67
- * During an insertion (slide or transition), returns the insertion's
68
- * source timestamp (freeze-frame). Otherwise subtracts accumulated offsets.
69
- */
70
- export declare function sourceTimeMs(outputTimeMs: number, slideScenes: ResolvedSlideScene[], transitions?: ResolvedTransition[]): number;
71
- export declare function totalSlideDurationMs(slideScenes: ResolvedSlideScene[]): number;
72
- export declare function totalTransitionDurationMs(transitions: ResolvedTransition[]): number;
73
- /**
74
- * Compute output-time intervals for both slides and transitions,
75
- * accounting for all preceding insertions.
76
- */
77
- export declare function computeOutputSegments(scenes: SceneEvent[], transitions: ResolvedTransition[], allEvents?: readonly TimelineEvent[]): {
78
- slides: SlideSegment[];
79
- transitions: TransitionSegment[];
80
- };
81
- /**
82
- * Shift every event's timestampMs forward by accumulated insertion
83
- * durations (slides + transitions) that precede it.
84
- * Returns a new array (no mutation).
85
- */
86
- export declare function remapEvents<T extends TimelineEvent>(events: T[], slideScenes: ResolvedSlideScene[], transitions?: ResolvedTransition[]): T[];
87
- //# sourceMappingURL=time-remap.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"time-remap.d.ts","sourceRoot":"","sources":["../../../src/composition/time-remap.ts"],"names":[],"mappings":"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"}
@@ -1,218 +0,0 @@
1
- export const DEFAULT_SLIDE_DURATION_MS = 2000;
2
- export function msToFrames(ms, fps) {
3
- return Math.round((ms / 1000) * fps);
4
- }
5
- /**
6
- * Filter scenes that have a `slide` field and resolve their duration.
7
- * Pass allEvents to get correct eventIndex for stable ordering with transitions.
8
- */
9
- export function resolveSlideScenes(scenes, allEvents) {
10
- return scenes
11
- .filter(s => s.slide !== undefined)
12
- .map(s => ({
13
- timestampMs: s.timestampMs,
14
- slideDurationMs: s.slide.duration ?? DEFAULT_SLIDE_DURATION_MS,
15
- eventIndex: allEvents ? allEvents.indexOf(s) : 0,
16
- }));
17
- }
18
- /**
19
- * Walk timeline events and resolve each transition's snapshot references.
20
- *
21
- * Uses **array position** to find surrounding actions. Adjacency matters:
22
- * if the next action is directly adjacent (no narration/wait/scene between,
23
- * cursor_target events are transparent), use its settledSnapshot. Otherwise
24
- * fall back to the transition's own pageSnapshot.
25
- */
26
- export function resolveTransitions(events) {
27
- const result = [];
28
- for (let i = 0; i < events.length; i++) {
29
- const event = events[i];
30
- if (event.type !== 'transition')
31
- continue;
32
- let lastBefore = null;
33
- for (let j = i - 1; j >= 0; j--) {
34
- if (events[j].type === 'action') {
35
- lastBefore = events[j];
36
- break;
37
- }
38
- }
39
- let firstAfter = null;
40
- let adjacent = true;
41
- for (let j = i + 1; j < events.length; j++) {
42
- if (events[j].type === 'action') {
43
- firstAfter = events[j];
44
- break;
45
- }
46
- if (events[j].type !== 'cursor_target')
47
- adjacent = false;
48
- }
49
- const te = event;
50
- result.push({
51
- timestampMs: event.timestampMs,
52
- transitionDurationMs: event.durationMs,
53
- transition: event.transition,
54
- beforeSnapshot: lastBefore?.settledSnapshot ?? te.pageSnapshot ?? null,
55
- afterSnapshot: firstAfter && adjacent
56
- ? (firstAfter.settledSnapshot ?? null)
57
- : (te.pageSnapshot ?? null),
58
- afterSourceMs: firstAfter && adjacent && firstAfter.settledAtMs !== undefined
59
- ? firstAfter.settledAtMs
60
- : event.timestampMs,
61
- hasContentBefore: lastBefore !== null,
62
- hasContentAfter: firstAfter !== null,
63
- eventIndex: i,
64
- });
65
- }
66
- return result;
67
- }
68
- function buildSortedInsertions(slideScenes, transitions) {
69
- const ins = [];
70
- for (const ss of slideScenes) {
71
- ins.push({ sourceTimeMs: ss.timestampMs, durationMs: ss.slideDurationMs, kind: 'slide', eventIndex: ss.eventIndex });
72
- }
73
- for (const t of transitions) {
74
- ins.push({ sourceTimeMs: t.timestampMs, durationMs: t.transitionDurationMs, kind: 'transition', eventIndex: t.eventIndex, afterSourceMs: t.afterSourceMs });
75
- }
76
- ins.sort((a, b) => a.sourceTimeMs - b.sourceTimeMs || a.eventIndex - b.eventIndex);
77
- return ins;
78
- }
79
- /**
80
- * Map an output-time position back to its source-time position.
81
- * During an insertion (slide or transition), returns the insertion's
82
- * source timestamp (freeze-frame). Otherwise subtracts accumulated offsets.
83
- */
84
- export function sourceTimeMs(outputTimeMs, slideScenes, transitions = []) {
85
- const insertions = buildSortedInsertions(slideScenes, transitions);
86
- let accumulated = 0;
87
- for (const ins of insertions) {
88
- const start = ins.sourceTimeMs + accumulated;
89
- const end = start + ins.durationMs;
90
- if (outputTimeMs < start)
91
- return outputTimeMs - accumulated;
92
- if (outputTimeMs < end)
93
- return ins.sourceTimeMs;
94
- accumulated += ins.durationMs;
95
- // Transition insertions skip source time past the next action's settling period.
96
- const skip = (ins.afterSourceMs ?? ins.sourceTimeMs) - ins.sourceTimeMs;
97
- if (skip > 0)
98
- accumulated -= skip;
99
- }
100
- return outputTimeMs - accumulated;
101
- }
102
- export function totalSlideDurationMs(slideScenes) {
103
- let total = 0;
104
- for (const ss of slideScenes)
105
- total += ss.slideDurationMs;
106
- return total;
107
- }
108
- export function totalTransitionDurationMs(transitions) {
109
- let total = 0;
110
- for (const t of transitions) {
111
- total += t.transitionDurationMs;
112
- // Subtract source time consumed by settling skip
113
- const skip = t.afterSourceMs - t.timestampMs;
114
- if (skip > 0)
115
- total -= skip;
116
- }
117
- return total;
118
- }
119
- /**
120
- * Compute output-time intervals for both slides and transitions,
121
- * accounting for all preceding insertions.
122
- */
123
- export function computeOutputSegments(scenes, transitions, allEvents) {
124
- const slideScenes = resolveSlideScenes(scenes, allEvents);
125
- const insertions = buildSortedInsertions(slideScenes, transitions);
126
- // Build queues sorted by eventIndex (matching insertion sort order within each kind).
127
- const slideQueue = scenes.filter(s => s.slide);
128
- if (allEvents) {
129
- slideQueue.sort((a, b) => allEvents.indexOf(a) - allEvents.indexOf(b));
130
- }
131
- const transQueue = [...transitions].sort((a, b) => a.eventIndex - b.eventIndex);
132
- let si = 0;
133
- let ti = 0;
134
- const slides = [];
135
- const transSegs = [];
136
- const segOrder = [];
137
- let accumulated = 0;
138
- for (const ins of insertions) {
139
- const outputStart = ins.sourceTimeMs + accumulated;
140
- const outputEnd = outputStart + ins.durationMs;
141
- if (ins.kind === 'slide') {
142
- const sc = slideQueue[si++];
143
- if (sc) {
144
- segOrder.push({ kind: 'slide', index: slides.length });
145
- slides.push({
146
- slideStartMs: outputStart,
147
- slideEndMs: outputEnd,
148
- slideDurationMs: ins.durationMs,
149
- sceneTitle: sc.title,
150
- sceneDescription: sc.description,
151
- slideConfig: sc.slide,
152
- });
153
- }
154
- }
155
- else {
156
- const rt = transQueue[ti++];
157
- if (rt) {
158
- segOrder.push({ kind: 'transition', index: transSegs.length });
159
- transSegs.push({
160
- outputStartMs: outputStart,
161
- outputEndMs: outputEnd,
162
- durationMs: ins.durationMs,
163
- transition: rt.transition,
164
- beforeSnapshot: rt.beforeSnapshot,
165
- afterSnapshot: rt.afterSnapshot,
166
- adjacentSlideBefore: null,
167
- adjacentSlideAfter: null,
168
- hasContentBefore: rt.hasContentBefore,
169
- hasContentAfter: rt.hasContentAfter,
170
- });
171
- }
172
- }
173
- accumulated += ins.durationMs;
174
- const skip = (ins.afterSourceMs ?? ins.sourceTimeMs) - ins.sourceTimeMs;
175
- if (skip > 0)
176
- accumulated -= skip;
177
- }
178
- // Second pass: link transitions to adjacent slides when they share
179
- // the same source timestamp (no video content gap between them).
180
- for (let k = 0; k < segOrder.length; k++) {
181
- if (segOrder[k].kind !== 'transition')
182
- continue;
183
- const seg = transSegs[segOrder[k].index];
184
- if (k > 0 && segOrder[k - 1].kind === 'slide'
185
- && insertions[k].sourceTimeMs === insertions[k - 1].sourceTimeMs) {
186
- seg.adjacentSlideBefore = segOrder[k - 1].index;
187
- }
188
- if (k < segOrder.length - 1 && segOrder[k + 1].kind === 'slide'
189
- && insertions[k].sourceTimeMs === insertions[k + 1].sourceTimeMs) {
190
- seg.adjacentSlideAfter = segOrder[k + 1].index;
191
- }
192
- }
193
- return { slides, transitions: transSegs };
194
- }
195
- /**
196
- * Shift every event's timestampMs forward by accumulated insertion
197
- * durations (slides + transitions) that precede it.
198
- * Returns a new array (no mutation).
199
- */
200
- export function remapEvents(events, slideScenes, transitions = []) {
201
- const insertions = buildSortedInsertions(slideScenes, transitions);
202
- return events.map(event => {
203
- let offset = 0;
204
- for (const ins of insertions) {
205
- if (event.timestampMs >= ins.sourceTimeMs) {
206
- offset += ins.durationMs;
207
- const skip = (ins.afterSourceMs ?? ins.sourceTimeMs) - ins.sourceTimeMs;
208
- if (skip > 0)
209
- offset -= skip;
210
- }
211
- else {
212
- break;
213
- }
214
- }
215
- return { ...event, timestampMs: event.timestampMs + offset };
216
- });
217
- }
218
- //# sourceMappingURL=time-remap.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"time-remap.js","sourceRoot":"","sources":["../../../src/composition/time-remap.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,MAAM,UAAU,UAAU,CAAC,EAAU,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;AACvC,CAAC;AAqDD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAoB,EACpB,SAAoC;IAEpC,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC;SAClC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,eAAe,EAAE,CAAC,CAAC,KAAM,CAAC,QAAQ,IAAI,yBAAyB;QAC/D,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACjD,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAuB;IACxD,MAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS;QAE1C,IAAI,UAAU,GAAuB,IAAI,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAgB,CAAC;gBAAC,MAAM;YAAC,CAAC;QACpF,CAAC;QAED,IAAI,UAAU,GAAuB,IAAI,CAAC;QAC1C,IAAI,QAAQ,GAAG,IAAI,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAgB,CAAC;gBAAC,MAAM;YAAC,CAAC;YAClF,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe;gBAAE,QAAQ,GAAG,KAAK,CAAC;QAC3D,CAAC;QAED,MAAM,EAAE,GAAG,KAAwB,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC;YACV,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,oBAAoB,EAAE,KAAK,CAAC,UAAU;YACtC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,cAAc,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE,CAAC,YAAY,IAAI,IAAI;YACtE,aAAa,EAAE,UAAU,IAAI,QAAQ;gBACnC,CAAC,CAAC,CAAC,UAAU,CAAC,eAAe,IAAI,IAAI,CAAC;gBACtC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,IAAI,IAAI,CAAC;YAC7B,aAAa,EAAE,UAAU,IAAI,QAAQ,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS;gBAC3E,CAAC,CAAC,UAAU,CAAC,WAAW;gBACxB,CAAC,CAAC,KAAK,CAAC,WAAW;YACrB,gBAAgB,EAAE,UAAU,KAAK,IAAI;YACrC,eAAe,EAAE,UAAU,KAAK,IAAI;YACpC,UAAU,EAAE,CAAC;SACd,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAgBD,SAAS,qBAAqB,CAC5B,WAAiC,EACjC,WAAiC;IAEjC,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;IACvH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;IAC9J,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACnF,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,YAAoB,EACpB,WAAiC,EACjC,cAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,qBAAqB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACnE,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC;QAC7C,MAAM,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC;QACnC,IAAI,YAAY,GAAG,KAAK;YAAE,OAAO,YAAY,GAAG,WAAW,CAAC;QAC5D,IAAI,YAAY,GAAG,GAAG;YAAE,OAAO,GAAG,CAAC,YAAY,CAAC;QAChD,WAAW,IAAI,GAAG,CAAC,UAAU,CAAC;QAC9B,iFAAiF;QACjF,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC;QACxE,IAAI,IAAI,GAAG,CAAC;YAAE,WAAW,IAAI,IAAI,CAAC;IACpC,CAAC;IACD,OAAO,YAAY,GAAG,WAAW,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAiC;IACpE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,WAAW;QAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,WAAiC;IACzE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,CAAC,oBAAoB,CAAC;QAChC,iDAAiD;QACjD,MAAM,IAAI,GAAG,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,WAAW,CAAC;QAC7C,IAAI,IAAI,GAAG,CAAC;YAAE,KAAK,IAAI,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAoB,EACpB,WAAiC,EACjC,SAAoC;IAEpC,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,qBAAqB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAEnE,sFAAsF;IACtF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,SAAS,EAAE,CAAC;QACd,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAChF,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,CAAC,CAAC;IAEX,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,SAAS,GAAwB,EAAE,CAAC;IAI1C,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC;QACnD,MAAM,SAAS,GAAG,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC;QAE/C,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5B,IAAI,EAAE,EAAE,CAAC;gBACP,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBACvD,MAAM,CAAC,IAAI,CAAC;oBACV,YAAY,EAAE,WAAW;oBACzB,UAAU,EAAE,SAAS;oBACrB,eAAe,EAAE,GAAG,CAAC,UAAU;oBAC/B,UAAU,EAAE,EAAE,CAAC,KAAK;oBACpB,gBAAgB,EAAE,EAAE,CAAC,WAAW;oBAChC,WAAW,EAAE,EAAE,CAAC,KAAM;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5B,IAAI,EAAE,EAAE,CAAC;gBACP,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC/D,SAAS,CAAC,IAAI,CAAC;oBACb,aAAa,EAAE,WAAW;oBAC1B,WAAW,EAAE,SAAS;oBACtB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,UAAU,EAAE,EAAE,CAAC,UAAU;oBACzB,cAAc,EAAE,EAAE,CAAC,cAAc;oBACjC,aAAa,EAAE,EAAE,CAAC,aAAa;oBAC/B,mBAAmB,EAAE,IAAI;oBACzB,kBAAkB,EAAE,IAAI;oBACxB,gBAAgB,EAAE,EAAE,CAAC,gBAAgB;oBACrC,eAAe,EAAE,EAAE,CAAC,eAAe;iBACpC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,WAAW,IAAI,GAAG,CAAC,UAAU,CAAC;QAC9B,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC;QACxE,IAAI,IAAI,GAAG,CAAC;YAAE,WAAW,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,mEAAmE;IACnE,iEAAiE;IACjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS;QAChD,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO;eACtC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;YACrE,GAAG,CAAC,mBAAmB,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO;eACxD,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;YACrE,GAAG,CAAC,kBAAkB,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,MAAW,EACX,WAAiC,EACjC,cAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,qBAAqB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACxB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,WAAW,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC;gBACzB,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC;gBACxE,IAAI,IAAI,GAAG,CAAC;oBAAE,MAAM,IAAI,IAAI,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,GAAG,MAAM,EAAE,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,18 +0,0 @@
1
- import type { Timeline } from '../timeline/types.js';
2
- import type { OpenaiVoice } from '../config/config-schema.js';
3
- export interface NarrationOptions {
4
- modelPath?: string;
5
- tempDir: string;
6
- ttsProvider?: 'piper' | 'openai';
7
- openaiVoice?: OpenaiVoice;
8
- openaiTtsInstructions?: string;
9
- }
10
- /**
11
- * Generate voiceover audio files for all narration events in a timeline.
12
- * Updates each narration event with the audioFile path and actual duration.
13
- * After TTS, ensures each narration_sync wait is at least as long as the
14
- * actual audio so clips never overlap.
15
- * Returns a new timeline with updated narration events.
16
- */
17
- export declare function generateNarration(timeline: Timeline, opts: NarrationOptions): Promise<Timeline>;
18
- //# sourceMappingURL=narration-timing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"narration-timing.d.ts","sourceRoot":"","sources":["../../../src/voiceover/narration-timing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAA6B,MAAM,sBAAsB,CAAC;AAGhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,QAAQ,CAAC,CAiCnB"}
@@ -1,40 +0,0 @@
1
- import { join } from 'node:path';
2
- import { synthesize as piperSynthesize } from './piper-engine.js';
3
- import { synthesize as openaiSynthesize } from './openai-engine.js';
4
- /**
5
- * Generate voiceover audio files for all narration events in a timeline.
6
- * Updates each narration event with the audioFile path and actual duration.
7
- * After TTS, ensures each narration_sync wait is at least as long as the
8
- * actual audio so clips never overlap.
9
- * Returns a new timeline with updated narration events.
10
- */
11
- export async function generateNarration(timeline, opts) {
12
- const provider = opts.ttsProvider ?? 'piper';
13
- const ext = provider === 'openai' ? '.mp3' : '.wav';
14
- const events = [...timeline.events];
15
- for (let i = 0; i < events.length; i++) {
16
- const event = events[i];
17
- if (event.type !== 'narration')
18
- continue;
19
- const narration = event;
20
- const outputPath = join(opts.tempDir, `narration-${narration.id}${ext}`);
21
- const result = provider === 'openai'
22
- ? await openaiSynthesize(narration.text, outputPath, opts.openaiVoice, opts.openaiTtsInstructions)
23
- : await piperSynthesize(narration.text, outputPath, opts.modelPath);
24
- events[i] = {
25
- ...narration,
26
- audioFile: result.audioPath,
27
- audioDurationMs: result.durationMs,
28
- };
29
- // Ensure the following narration_sync wait covers the actual audio duration
30
- const next = events[i + 1];
31
- if (next?.type === 'wait' && next.reason === 'narration_sync') {
32
- const wait = next;
33
- if (wait.durationMs < result.durationMs) {
34
- events[i + 1] = { ...wait, durationMs: result.durationMs };
35
- }
36
- }
37
- }
38
- return { ...timeline, events };
39
- }
40
- //# sourceMappingURL=narration-timing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"narration-timing.js","sourceRoot":"","sources":["../../../src/voiceover/narration-timing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,UAAU,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAWpE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAkB,EAClB,IAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QAEzC,MAAM,SAAS,GAAG,KAAuB,CAAC;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,SAAS,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,QAAQ,KAAK,QAAQ;YAClC,CAAC,CAAC,MAAM,gBAAgB,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,CAAC;YAClG,CAAC,CAAC,MAAM,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtE,MAAM,CAAC,CAAC,CAAC,GAAG;YACV,GAAG,SAAS;YACZ,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,eAAe,EAAE,MAAM,CAAC,UAAU;SACnC,CAAC;QAEF,4EAA4E;QAC5E,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3B,IAAI,IAAI,EAAE,IAAI,KAAK,MAAM,IAAK,IAAkB,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;YAC7E,MAAM,IAAI,GAAG,IAAiB,CAAC;YAC/B,IAAI,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBACxC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,CAAC;AACjC,CAAC"}