@scenar/cli 0.10.0 → 0.11.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/example-bundle/assets/index-DxmqjG-8.js +388 -0
- package/example-bundle/assets/style-B2sxnVVZ.css +1 -0
- package/example-bundle/embed.js +1 -1
- package/example-bundle/index.html +2 -2
- package/example-bundle/logo.png +0 -0
- package/example-bundle/pack-manifest.json +33 -9
- package/example-bundle/soundtrack/music.mp3 +0 -0
- package/example-bundle/soundtrack/sfx/click.mp3 +0 -0
- package/example-bundle/soundtrack/sfx/keystroke.mp3 +0 -0
- package/package.json +4 -4
- package/src/__tests__/collect-pack-shots.test.ts +8 -0
- package/src/__tests__/elevenlabs-provider.test.ts +187 -0
- package/src/__tests__/embed-snippet.test.ts +5 -0
- package/src/__tests__/find-authored-soundtrack.test.ts +54 -0
- package/src/__tests__/find-authored-title-cards.test.ts +65 -0
- package/src/__tests__/load-bundle.test.ts +67 -0
- package/src/__tests__/narrate-command.test.ts +65 -1
- package/src/__tests__/narration-cache.test.ts +134 -0
- package/src/__tests__/pack-bundle-contract.test.ts +2 -0
- package/src/__tests__/pack-generate-embed-entry.test.ts +95 -16
- package/src/__tests__/presenter-command.test.ts +366 -0
- package/src/__tests__/render-command.test.ts +11 -0
- package/src/__tests__/render-generate-entry.test.ts +102 -0
- package/src/__tests__/resolve-provider.test.ts +32 -3
- package/src/__tests__/scenario-validator.test.ts +174 -0
- package/src/__tests__/stage-assets.test.ts +269 -0
- package/src/commands/narrate.js +1 -1
- package/src/commands/narrate.js.map +1 -1
- package/src/commands/narrate.ts +1 -1
- package/src/commands/presenter.d.ts +3 -0
- package/src/commands/presenter.d.ts.map +1 -0
- package/src/commands/presenter.js +89 -0
- package/src/commands/presenter.js.map +1 -0
- package/src/commands/presenter.ts +107 -0
- package/src/commands/render.d.ts.map +1 -1
- package/src/commands/render.js +2 -0
- package/src/commands/render.js.map +1 -1
- package/src/commands/render.ts +6 -0
- package/src/embed/embed-snippet.d.ts +5 -0
- package/src/embed/embed-snippet.d.ts.map +1 -1
- package/src/embed/embed-snippet.js +6 -1
- package/src/embed/embed-snippet.js.map +1 -1
- package/src/embed/embed-snippet.ts +6 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/index.ts +2 -0
- package/src/narrate/run-narrate.d.ts +15 -1
- package/src/narrate/run-narrate.d.ts.map +1 -1
- package/src/narrate/run-narrate.js +11 -4
- package/src/narrate/run-narrate.js.map +1 -1
- package/src/narrate/run-narrate.ts +15 -6
- package/src/pack/bundle-contract.d.ts +1 -0
- package/src/pack/bundle-contract.d.ts.map +1 -1
- package/src/pack/bundle-contract.js +3 -0
- package/src/pack/bundle-contract.js.map +1 -1
- package/src/pack/bundle-contract.ts +3 -0
- package/src/pack/collect-pack-shots.d.ts +5 -1
- package/src/pack/collect-pack-shots.d.ts.map +1 -1
- package/src/pack/collect-pack-shots.js +3 -1
- package/src/pack/collect-pack-shots.js.map +1 -1
- package/src/pack/collect-pack-shots.ts +15 -1
- package/src/pack/generate-embed-entry.d.ts +7 -0
- package/src/pack/generate-embed-entry.d.ts.map +1 -1
- package/src/pack/generate-embed-entry.js +102 -7
- package/src/pack/generate-embed-entry.js.map +1 -1
- package/src/pack/generate-embed-entry.ts +107 -7
- package/src/pack/run-pack.d.ts +1 -0
- package/src/pack/run-pack.d.ts.map +1 -1
- package/src/pack/run-pack.js +100 -9
- package/src/pack/run-pack.js.map +1 -1
- package/src/pack/run-pack.ts +133 -9
- package/src/presenter/heygen-client.d.ts +69 -0
- package/src/presenter/heygen-client.d.ts.map +1 -0
- package/src/presenter/heygen-client.js +154 -0
- package/src/presenter/heygen-client.js.map +1 -0
- package/src/presenter/heygen-client.ts +224 -0
- package/src/presenter/run-presenter.d.ts +67 -0
- package/src/presenter/run-presenter.d.ts.map +1 -0
- package/src/presenter/run-presenter.js +348 -0
- package/src/presenter/run-presenter.js.map +1 -0
- package/src/presenter/run-presenter.ts +536 -0
- package/src/render/generate-entry.d.ts +4 -0
- package/src/render/generate-entry.d.ts.map +1 -1
- package/src/render/generate-entry.js +75 -7
- package/src/render/generate-entry.js.map +1 -1
- package/src/render/generate-entry.ts +84 -7
- package/src/render/run-render.d.ts +6 -0
- package/src/render/run-render.d.ts.map +1 -1
- package/src/render/run-render.js +58 -0
- package/src/render/run-render.js.map +1 -1
- package/src/render/run-render.ts +72 -0
- package/src/render/stage-assets.d.ts +44 -0
- package/src/render/stage-assets.d.ts.map +1 -0
- package/src/render/stage-assets.js +91 -0
- package/src/render/stage-assets.js.map +1 -0
- package/src/render/stage-assets.ts +130 -0
- package/src/tts/echogarden.d.ts.map +1 -1
- package/src/tts/echogarden.js +4 -2
- package/src/tts/echogarden.js.map +1 -1
- package/src/tts/echogarden.ts +5 -2
- package/src/tts/edge-tts.d.ts.map +1 -1
- package/src/tts/edge-tts.js +2 -1
- package/src/tts/edge-tts.js.map +1 -1
- package/src/tts/edge-tts.ts +2 -1
- package/src/tts/elevenlabs.d.ts +15 -0
- package/src/tts/elevenlabs.d.ts.map +1 -0
- package/src/tts/elevenlabs.js +73 -0
- package/src/tts/elevenlabs.js.map +1 -0
- package/src/tts/elevenlabs.ts +105 -0
- package/src/tts/openai.d.ts.map +1 -1
- package/src/tts/openai.js +2 -1
- package/src/tts/openai.js.map +1 -1
- package/src/tts/openai.ts +2 -1
- package/src/tts/resolve-provider.d.ts +1 -1
- package/src/tts/resolve-provider.d.ts.map +1 -1
- package/src/tts/resolve-provider.js +10 -3
- package/src/tts/resolve-provider.js.map +1 -1
- package/src/tts/resolve-provider.ts +12 -4
- package/src/tts/types.d.ts +9 -0
- package/src/tts/types.d.ts.map +1 -1
- package/src/tts/types.ts +10 -0
- package/src/util/confirm.d.ts +11 -0
- package/src/util/confirm.d.ts.map +1 -0
- package/src/util/confirm.js +24 -0
- package/src/util/confirm.js.map +1 -0
- package/src/util/confirm.ts +23 -0
- package/src/util/load-bundle.d.ts +17 -1
- package/src/util/load-bundle.d.ts.map +1 -1
- package/src/util/load-bundle.js +19 -11
- package/src/util/load-bundle.js.map +1 -1
- package/src/util/load-bundle.ts +38 -12
- package/src/util/load-ts.d.ts +77 -0
- package/src/util/load-ts.d.ts.map +1 -1
- package/src/util/load-ts.js +125 -0
- package/src/util/load-ts.js.map +1 -1
- package/src/util/load-ts.ts +165 -0
- package/src/util/narration-cache.d.ts +13 -5
- package/src/util/narration-cache.d.ts.map +1 -1
- package/src/util/narration-cache.js +10 -8
- package/src/util/narration-cache.js.map +1 -1
- package/src/util/narration-cache.ts +22 -6
- package/src/util/presenter-cache.d.ts +44 -0
- package/src/util/presenter-cache.d.ts.map +1 -0
- package/src/util/presenter-cache.js +43 -0
- package/src/util/presenter-cache.js.map +1 -0
- package/src/util/presenter-cache.ts +101 -0
- package/src/util/scenario-assets.d.ts +47 -0
- package/src/util/scenario-assets.d.ts.map +1 -0
- package/src/util/scenario-assets.js +71 -0
- package/src/util/scenario-assets.js.map +1 -0
- package/src/util/scenario-assets.ts +111 -0
- package/src/util/soundtrack-assets.d.ts +34 -0
- package/src/util/soundtrack-assets.d.ts.map +1 -0
- package/src/util/soundtrack-assets.js +48 -0
- package/src/util/soundtrack-assets.js.map +1 -0
- package/src/util/soundtrack-assets.ts +69 -0
- package/src/validate/scenario-validator.d.ts.map +1 -1
- package/src/validate/scenario-validator.js +82 -0
- package/src/validate/scenario-validator.js.map +1 -1
- package/src/validate/scenario-validator.ts +110 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/example-bundle/assets/index-DpJUOVBT.js +0 -388
- package/example-bundle/assets/style-ix_q0zsc.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-entry.js","sourceRoot":"","sources":["../../../src/render/generate-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-entry.js","sourceRoot":"","sources":["../../../src/render/generate-entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,12 +15,16 @@ export interface EntryGeneratorInput {
|
|
|
15
15
|
scenarioId: string;
|
|
16
16
|
/** Whether the scenario has a narration manifest. */
|
|
17
17
|
hasNarration: boolean;
|
|
18
|
+
/** Whether the scenario has a presenter manifest (+ clips). */
|
|
19
|
+
hasPresenter: boolean;
|
|
18
20
|
/** Absolute path to the providers file, or null if none found. */
|
|
19
21
|
providersPath: string | null;
|
|
20
22
|
fps: number;
|
|
21
23
|
width: number;
|
|
22
24
|
height: number;
|
|
23
25
|
compositionId: string;
|
|
26
|
+
/** Burn step captions into the video (`scenar render --captions`). */
|
|
27
|
+
captions: boolean;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
/**
|
|
@@ -52,8 +56,18 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
|
|
|
52
56
|
lines.push(`import { registerRoot } from "remotion";`);
|
|
53
57
|
lines.push(`import { Composition, AbsoluteFill } from "remotion";`);
|
|
54
58
|
lines.push(
|
|
55
|
-
`import { ScenarioComposition, calculateScenarioTimeline } from "@scenar/remotion";`,
|
|
59
|
+
`import { ScenarioComposition, applyTitleCards, calculateScenarioTimeline } from "@scenar/remotion";`,
|
|
56
60
|
);
|
|
61
|
+
lines.push(`import { SCENAR_CLASS } from "@scenar/react";`);
|
|
62
|
+
// The same stylesheet pair the packed embed entry loads: without them,
|
|
63
|
+
// authored step content built on @scenar/react (shells, page templates)
|
|
64
|
+
// renders unstyled — black frames in the MP4 (scenar#23). Remotion's
|
|
65
|
+
// bundler handles plain CSS imports natively; styles.css is the
|
|
66
|
+
// self-contained build, so no Tailwind processing is needed. The
|
|
67
|
+
// composition root carries SCENAR_CLASS (below) so the `.scenar`-scoped
|
|
68
|
+
// theme tokens resolve, exactly as the embed entry scopes its tree.
|
|
69
|
+
lines.push(`import "@scenar/react/theme.css";`);
|
|
70
|
+
lines.push(`import "@scenar/react/styles.css";`);
|
|
57
71
|
lines.push(`import { renderStep } from ${JSON.stringify(renderImport)};`);
|
|
58
72
|
lines.push(`import * as _stepsModule from ${JSON.stringify(stepsImport)};`);
|
|
59
73
|
|
|
@@ -64,6 +78,13 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
|
|
|
64
78
|
lines.push(`const _manifest = undefined;`);
|
|
65
79
|
}
|
|
66
80
|
|
|
81
|
+
if (input.hasPresenter) {
|
|
82
|
+
const presenterManifestPath = `${scenarioPath}/presenter/manifest.json`;
|
|
83
|
+
lines.push(`import _presenterManifest from ${JSON.stringify(presenterManifestPath)};`);
|
|
84
|
+
} else {
|
|
85
|
+
lines.push(`const _presenterManifest = undefined;`);
|
|
86
|
+
}
|
|
87
|
+
|
|
67
88
|
if (input.providersPath) {
|
|
68
89
|
const providersImport = toPosix(input.providersPath).replace(/\.[^.]+$/, "");
|
|
69
90
|
lines.push(
|
|
@@ -89,13 +110,62 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
|
|
|
89
110
|
lines.push(``);
|
|
90
111
|
lines.push(`const _steps: any = _findSteps(_stepsModule as unknown as Record<string, unknown>);`);
|
|
91
112
|
|
|
113
|
+
// --- Soundtrack resolution (mirror of the CLI's findAuthoredSoundtrack) ---
|
|
114
|
+
// Discovered from the very module the bundle bakes in, at module-eval
|
|
115
|
+
// time, so the render can never disagree with the authored config: a
|
|
116
|
+
// scenario-shaped export (createScenario) wins, then a `soundtrack`
|
|
117
|
+
// named export; absent means no soundtrack.
|
|
118
|
+
|
|
119
|
+
lines.push(``);
|
|
120
|
+
lines.push(`function _findSoundtrack(mod: Record<string, unknown>): any {`);
|
|
121
|
+
lines.push(` for (const val of Object.values(mod)) {`);
|
|
122
|
+
lines.push(` if (`);
|
|
123
|
+
lines.push(` typeof val === "object" && val !== null && !Array.isArray(val) &&`);
|
|
124
|
+
lines.push(` "soundtrack" in val &&`);
|
|
125
|
+
lines.push(` Array.isArray((val as any).steps) && (val as any).steps.length > 0 &&`);
|
|
126
|
+
lines.push(` typeof (val as any).steps[0] === "object" && (val as any).steps[0] !== null &&`);
|
|
127
|
+
lines.push(` "delayMs" in (val as any).steps[0]`);
|
|
128
|
+
lines.push(` ) return (val as any).soundtrack;`);
|
|
129
|
+
lines.push(` }`);
|
|
130
|
+
lines.push(` return (mod as any)["soundtrack"];`);
|
|
131
|
+
lines.push(`}`);
|
|
132
|
+
lines.push(``);
|
|
133
|
+
lines.push(`const _soundtrack: any = _findSoundtrack(_stepsModule as unknown as Record<string, unknown>);`);
|
|
134
|
+
|
|
135
|
+
// --- Title cards resolution (mirror of the CLI's findAuthoredTitleCards) ---
|
|
136
|
+
// Same discovery contract as _findSoundtrack. The config is discovered
|
|
137
|
+
// here and applied immediately below — bundle assembly is THE one
|
|
138
|
+
// card-synthesis point (applyTitleCards from @scenar/core, re-exported
|
|
139
|
+
// by @scenar/remotion so no extra dependency is needed).
|
|
140
|
+
|
|
141
|
+
lines.push(``);
|
|
142
|
+
lines.push(`function _findTitleCards(mod: Record<string, unknown>): any {`);
|
|
143
|
+
lines.push(` for (const val of Object.values(mod)) {`);
|
|
144
|
+
lines.push(` if (`);
|
|
145
|
+
lines.push(` typeof val === "object" && val !== null && !Array.isArray(val) &&`);
|
|
146
|
+
lines.push(` "titleCards" in val &&`);
|
|
147
|
+
lines.push(` Array.isArray((val as any).steps) && (val as any).steps.length > 0 &&`);
|
|
148
|
+
lines.push(` typeof (val as any).steps[0] === "object" && (val as any).steps[0] !== null &&`);
|
|
149
|
+
lines.push(` "delayMs" in (val as any).steps[0]`);
|
|
150
|
+
lines.push(` ) return (val as any).titleCards;`);
|
|
151
|
+
lines.push(` }`);
|
|
152
|
+
lines.push(` return (mod as any)["titleCards"];`);
|
|
153
|
+
lines.push(`}`);
|
|
154
|
+
lines.push(``);
|
|
155
|
+
lines.push(`const _titleCards: any = _findTitleCards(_stepsModule as unknown as Record<string, unknown>);`);
|
|
156
|
+
|
|
92
157
|
// --- Bundle + timeline ---
|
|
158
|
+
// Card synthesis runs before the timeline calculation so an intro or
|
|
159
|
+
// outro card lengthens durationInFrames exactly like an authored step.
|
|
93
160
|
|
|
94
161
|
lines.push(``);
|
|
162
|
+
lines.push(`const _applied = applyTitleCards(_steps, _manifest, _titleCards, _presenterManifest);`);
|
|
95
163
|
lines.push(`const _bundle = {`);
|
|
96
164
|
lines.push(` id: ${JSON.stringify(input.scenarioId)},`);
|
|
97
|
-
lines.push(` steps:
|
|
98
|
-
lines.push(` narrationManifest:
|
|
165
|
+
lines.push(` steps: _applied.steps as any,`);
|
|
166
|
+
lines.push(` narrationManifest: _applied.narrationManifest,`);
|
|
167
|
+
lines.push(` soundtrack: _soundtrack,`);
|
|
168
|
+
lines.push(` presenterManifest: _applied.presenterManifest,`);
|
|
99
169
|
lines.push(`};`);
|
|
100
170
|
lines.push(``);
|
|
101
171
|
lines.push(
|
|
@@ -107,11 +177,18 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
|
|
|
107
177
|
lines.push(``);
|
|
108
178
|
lines.push(`function _VideoRoot() {`);
|
|
109
179
|
|
|
180
|
+
// `captions` is baked into the generated JSX (not read at render time):
|
|
181
|
+
// the entry is written per render invocation, so the flag's value IS the
|
|
182
|
+
// render's configuration — same treatment as fps/width/height above.
|
|
183
|
+
const compositionOpen = input.captions
|
|
184
|
+
? `<ScenarioComposition bundle={_bundle} captions>`
|
|
185
|
+
: `<ScenarioComposition bundle={_bundle}>`;
|
|
186
|
+
|
|
110
187
|
if (input.providersPath) {
|
|
111
188
|
lines.push(` return (`);
|
|
112
|
-
lines.push(` <AbsoluteFill>`);
|
|
189
|
+
lines.push(` <AbsoluteFill className={SCENAR_CLASS}>`);
|
|
113
190
|
lines.push(` <_Providers>`);
|
|
114
|
-
lines.push(`
|
|
191
|
+
lines.push(` ${compositionOpen}`);
|
|
115
192
|
lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
|
|
116
193
|
lines.push(` </ScenarioComposition>`);
|
|
117
194
|
lines.push(` </_Providers>`);
|
|
@@ -119,8 +196,8 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
|
|
|
119
196
|
lines.push(` );`);
|
|
120
197
|
} else {
|
|
121
198
|
lines.push(` return (`);
|
|
122
|
-
lines.push(` <AbsoluteFill>`);
|
|
123
|
-
lines.push(`
|
|
199
|
+
lines.push(` <AbsoluteFill className={SCENAR_CLASS}>`);
|
|
200
|
+
lines.push(` ${compositionOpen}`);
|
|
124
201
|
lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
|
|
125
202
|
lines.push(` </ScenarioComposition>`);
|
|
126
203
|
lines.push(` </AbsoluteFill>`);
|
|
@@ -8,6 +8,12 @@ export interface RunRenderOptions {
|
|
|
8
8
|
readonly compositionId?: string;
|
|
9
9
|
readonly entry?: string;
|
|
10
10
|
readonly webpackOverride?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Burn step captions into the video (each step's `narration` text as a
|
|
13
|
+
* subtitle overlay). Only applies to the auto-generated entry; a custom
|
|
14
|
+
* `--entry` owns its own `<ScenarioComposition>` props.
|
|
15
|
+
*/
|
|
16
|
+
readonly captions?: boolean;
|
|
11
17
|
readonly onLog?: (message: string) => void;
|
|
12
18
|
}
|
|
13
19
|
/** The outcome of a successful render. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-render.d.ts","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-render.d.ts","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAyIhF"}
|
package/src/render/run-render.js
CHANGED
|
@@ -2,9 +2,11 @@ import { resolve, join } from "node:path";
|
|
|
2
2
|
import { stat, mkdir, access, writeFile, rm } from "node:fs/promises";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { loadBundle } from "../util/load-bundle.js";
|
|
5
|
+
import { resolveSfxAssetPaths } from "../util/soundtrack-assets.js";
|
|
5
6
|
import { generateRemotionEntry } from "./generate-entry.js";
|
|
6
7
|
import { resolveProvidersPath } from "./resolve-providers.js";
|
|
7
8
|
import { detectRenderExport } from "./detect-render-export.js";
|
|
9
|
+
import { stageRenderAssets } from "./stage-assets.js";
|
|
8
10
|
/**
|
|
9
11
|
* Render a scenario directory to an MP4 via Remotion — the pure orchestration
|
|
10
12
|
* behind `scenar render`, with no process/exit coupling. Throws on any failure
|
|
@@ -25,6 +27,13 @@ export async function runRender(options) {
|
|
|
25
27
|
const fps = options.fps ?? 30;
|
|
26
28
|
const width = options.width ?? 1920;
|
|
27
29
|
const height = options.height ?? 1080;
|
|
30
|
+
const captions = options.captions ?? false;
|
|
31
|
+
// A custom entry owns its own <ScenarioComposition> props, so --captions
|
|
32
|
+
// cannot reach it. Say so instead of silently ignoring the flag.
|
|
33
|
+
if (captions && options.entry) {
|
|
34
|
+
onLog("Warning: --captions has no effect with --entry. " +
|
|
35
|
+
'Pass captions to <ScenarioComposition> in your entry file instead.');
|
|
36
|
+
}
|
|
28
37
|
let tempDir;
|
|
29
38
|
try {
|
|
30
39
|
const bundle = await loadBundle(scenarioDir);
|
|
@@ -37,9 +46,11 @@ export async function runRender(options) {
|
|
|
37
46
|
scenarioId,
|
|
38
47
|
compositionId,
|
|
39
48
|
hasNarration: !!bundle.narrationManifest,
|
|
49
|
+
hasPresenter: !!bundle.presenterManifest,
|
|
40
50
|
fps,
|
|
41
51
|
width,
|
|
42
52
|
height,
|
|
53
|
+
captions,
|
|
43
54
|
});
|
|
44
55
|
tempDir = generated?.tempDir;
|
|
45
56
|
const webpackOverride = options.webpackOverride
|
|
@@ -48,6 +59,47 @@ export async function runRender(options) {
|
|
|
48
59
|
onLog(`Scenario: ${scenarioId}`);
|
|
49
60
|
onLog(`Steps: ${bundle.steps.length}`);
|
|
50
61
|
onLog(`Audio: ${bundle.narrationManifest ? "yes (manifest found)" : "none"}`);
|
|
62
|
+
if (bundle.soundtrack) {
|
|
63
|
+
const parts = [
|
|
64
|
+
bundle.soundtrack.musicSrc ? `music (${bundle.soundtrack.musicSrc})` : null,
|
|
65
|
+
bundle.soundtrack.sfx ? "sfx" : null,
|
|
66
|
+
].filter(Boolean);
|
|
67
|
+
onLog(`Soundtrack: ${parts.length > 0 ? parts.join(" + ") : "configured (silent)"}`);
|
|
68
|
+
}
|
|
69
|
+
if (bundle.titleCards?.intro || bundle.titleCards?.outro) {
|
|
70
|
+
const parts = [
|
|
71
|
+
bundle.titleCards.intro ? "intro" : null,
|
|
72
|
+
bundle.titleCards.outro ? "outro" : null,
|
|
73
|
+
].filter(Boolean);
|
|
74
|
+
onLog(`Cards: ${parts.join(" + ")}`);
|
|
75
|
+
}
|
|
76
|
+
if (captions) {
|
|
77
|
+
onLog(`Captions: burned in (from step narration text)`);
|
|
78
|
+
}
|
|
79
|
+
// Stage every local asset into a Remotion public dir so staticFile()
|
|
80
|
+
// resolution finds real bytes — narration clips, the music asset, the
|
|
81
|
+
// built-in SFX set, and title-card logos. Only for the auto-generated
|
|
82
|
+
// entry: a custom --entry project owns its own public dir convention.
|
|
83
|
+
let publicDir;
|
|
84
|
+
if (generated) {
|
|
85
|
+
const candidatePublicDir = join(generated.tempDir, "public");
|
|
86
|
+
const sfxPaths = bundle.soundtrack?.sfx
|
|
87
|
+
? resolveSfxAssetPaths(scenarioDir)
|
|
88
|
+
: undefined;
|
|
89
|
+
const stagedCount = await stageRenderAssets({
|
|
90
|
+
scenarioDir,
|
|
91
|
+
publicDir: candidatePublicDir,
|
|
92
|
+
hasNarration: !!bundle.narrationManifest,
|
|
93
|
+
hasPresenter: !!bundle.presenterManifest,
|
|
94
|
+
soundtrack: bundle.soundtrack,
|
|
95
|
+
sfxPaths,
|
|
96
|
+
titleCards: bundle.titleCards,
|
|
97
|
+
});
|
|
98
|
+
if (stagedCount > 0) {
|
|
99
|
+
publicDir = candidatePublicDir;
|
|
100
|
+
onLog(`Staged: ${stagedCount} asset file(s) for the render`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
51
103
|
onLog(`Entry: ${generated ? "(auto-generated)" : entryPoint}`);
|
|
52
104
|
if (generated?.providersPath) {
|
|
53
105
|
onLog(`Providers: ${generated.providersPath}`);
|
|
@@ -66,6 +118,7 @@ export async function runRender(options) {
|
|
|
66
118
|
width,
|
|
67
119
|
height,
|
|
68
120
|
webpackOverride,
|
|
121
|
+
publicDir,
|
|
69
122
|
onLog,
|
|
70
123
|
});
|
|
71
124
|
return {
|
|
@@ -114,11 +167,13 @@ async function resolveEntryPoint(input) {
|
|
|
114
167
|
renderFilePath,
|
|
115
168
|
scenarioId: input.scenarioId,
|
|
116
169
|
hasNarration: input.hasNarration,
|
|
170
|
+
hasPresenter: input.hasPresenter,
|
|
117
171
|
providersPath,
|
|
118
172
|
fps: input.fps,
|
|
119
173
|
width: input.width,
|
|
120
174
|
height: input.height,
|
|
121
175
|
compositionId: input.compositionId,
|
|
176
|
+
captions: input.captions,
|
|
122
177
|
});
|
|
123
178
|
// Write the entry inside the scenario directory so webpack's standard
|
|
124
179
|
// node_modules resolution walks up from here into the consumer project.
|
|
@@ -170,6 +225,9 @@ async function renderScenario(config) {
|
|
|
170
225
|
if (config.webpackOverride) {
|
|
171
226
|
bundleOptions.webpackOverride = config.webpackOverride;
|
|
172
227
|
}
|
|
228
|
+
if (config.publicDir) {
|
|
229
|
+
bundleOptions.publicDir = config.publicDir;
|
|
230
|
+
}
|
|
173
231
|
const serveUrl = await bundler.bundle(bundleOptions);
|
|
174
232
|
config.onLog(`Selecting composition: ${config.compositionId}`);
|
|
175
233
|
const composition = await renderer.selectComposition({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-render.js","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAkB,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-render.js","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"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"}
|
package/src/render/run-render.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { resolve, join } from "node:path";
|
|
|
2
2
|
import { stat, mkdir, access, writeFile, rm } from "node:fs/promises";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { loadBundle, type CliBundle } from "../util/load-bundle.js";
|
|
5
|
+
import { resolveSfxAssetPaths } from "../util/soundtrack-assets.js";
|
|
5
6
|
import { generateRemotionEntry } from "./generate-entry.js";
|
|
6
7
|
import { resolveProvidersPath } from "./resolve-providers.js";
|
|
7
8
|
import { detectRenderExport } from "./detect-render-export.js";
|
|
9
|
+
import { stageRenderAssets } from "./stage-assets.js";
|
|
8
10
|
|
|
9
11
|
/** Options for {@link runRender}. Paths may be relative; resolved here. */
|
|
10
12
|
export interface RunRenderOptions {
|
|
@@ -16,6 +18,12 @@ export interface RunRenderOptions {
|
|
|
16
18
|
readonly compositionId?: string;
|
|
17
19
|
readonly entry?: string;
|
|
18
20
|
readonly webpackOverride?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Burn step captions into the video (each step's `narration` text as a
|
|
23
|
+
* subtitle overlay). Only applies to the auto-generated entry; a custom
|
|
24
|
+
* `--entry` owns its own `<ScenarioComposition>` props.
|
|
25
|
+
*/
|
|
26
|
+
readonly captions?: boolean;
|
|
19
27
|
readonly onLog?: (message: string) => void;
|
|
20
28
|
}
|
|
21
29
|
|
|
@@ -55,6 +63,16 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
|
|
|
55
63
|
const fps = options.fps ?? 30;
|
|
56
64
|
const width = options.width ?? 1920;
|
|
57
65
|
const height = options.height ?? 1080;
|
|
66
|
+
const captions = options.captions ?? false;
|
|
67
|
+
|
|
68
|
+
// A custom entry owns its own <ScenarioComposition> props, so --captions
|
|
69
|
+
// cannot reach it. Say so instead of silently ignoring the flag.
|
|
70
|
+
if (captions && options.entry) {
|
|
71
|
+
onLog(
|
|
72
|
+
"Warning: --captions has no effect with --entry. " +
|
|
73
|
+
'Pass captions to <ScenarioComposition> in your entry file instead.',
|
|
74
|
+
);
|
|
75
|
+
}
|
|
58
76
|
|
|
59
77
|
let tempDir: string | undefined;
|
|
60
78
|
try {
|
|
@@ -69,9 +87,11 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
|
|
|
69
87
|
scenarioId,
|
|
70
88
|
compositionId,
|
|
71
89
|
hasNarration: !!bundle.narrationManifest,
|
|
90
|
+
hasPresenter: !!bundle.presenterManifest,
|
|
72
91
|
fps,
|
|
73
92
|
width,
|
|
74
93
|
height,
|
|
94
|
+
captions,
|
|
75
95
|
});
|
|
76
96
|
tempDir = generated?.tempDir;
|
|
77
97
|
|
|
@@ -82,6 +102,48 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
|
|
|
82
102
|
onLog(`Scenario: ${scenarioId}`);
|
|
83
103
|
onLog(`Steps: ${bundle.steps.length}`);
|
|
84
104
|
onLog(`Audio: ${bundle.narrationManifest ? "yes (manifest found)" : "none"}`);
|
|
105
|
+
if (bundle.soundtrack) {
|
|
106
|
+
const parts = [
|
|
107
|
+
bundle.soundtrack.musicSrc ? `music (${bundle.soundtrack.musicSrc})` : null,
|
|
108
|
+
bundle.soundtrack.sfx ? "sfx" : null,
|
|
109
|
+
].filter(Boolean);
|
|
110
|
+
onLog(`Soundtrack: ${parts.length > 0 ? parts.join(" + ") : "configured (silent)"}`);
|
|
111
|
+
}
|
|
112
|
+
if (bundle.titleCards?.intro || bundle.titleCards?.outro) {
|
|
113
|
+
const parts = [
|
|
114
|
+
bundle.titleCards.intro ? "intro" : null,
|
|
115
|
+
bundle.titleCards.outro ? "outro" : null,
|
|
116
|
+
].filter(Boolean);
|
|
117
|
+
onLog(`Cards: ${parts.join(" + ")}`);
|
|
118
|
+
}
|
|
119
|
+
if (captions) {
|
|
120
|
+
onLog(`Captions: burned in (from step narration text)`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Stage every local asset into a Remotion public dir so staticFile()
|
|
124
|
+
// resolution finds real bytes — narration clips, the music asset, the
|
|
125
|
+
// built-in SFX set, and title-card logos. Only for the auto-generated
|
|
126
|
+
// entry: a custom --entry project owns its own public dir convention.
|
|
127
|
+
let publicDir: string | undefined;
|
|
128
|
+
if (generated) {
|
|
129
|
+
const candidatePublicDir = join(generated.tempDir, "public");
|
|
130
|
+
const sfxPaths = bundle.soundtrack?.sfx
|
|
131
|
+
? resolveSfxAssetPaths(scenarioDir)
|
|
132
|
+
: undefined;
|
|
133
|
+
const stagedCount = await stageRenderAssets({
|
|
134
|
+
scenarioDir,
|
|
135
|
+
publicDir: candidatePublicDir,
|
|
136
|
+
hasNarration: !!bundle.narrationManifest,
|
|
137
|
+
hasPresenter: !!bundle.presenterManifest,
|
|
138
|
+
soundtrack: bundle.soundtrack,
|
|
139
|
+
sfxPaths,
|
|
140
|
+
titleCards: bundle.titleCards,
|
|
141
|
+
});
|
|
142
|
+
if (stagedCount > 0) {
|
|
143
|
+
publicDir = candidatePublicDir;
|
|
144
|
+
onLog(`Staged: ${stagedCount} asset file(s) for the render`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
85
147
|
onLog(`Entry: ${generated ? "(auto-generated)" : entryPoint}`);
|
|
86
148
|
if (generated?.providersPath) {
|
|
87
149
|
onLog(`Providers: ${generated.providersPath}`);
|
|
@@ -101,6 +163,7 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
|
|
|
101
163
|
width,
|
|
102
164
|
height,
|
|
103
165
|
webpackOverride,
|
|
166
|
+
publicDir,
|
|
104
167
|
onLog,
|
|
105
168
|
});
|
|
106
169
|
|
|
@@ -137,9 +200,11 @@ interface EntryResolutionInput {
|
|
|
137
200
|
scenarioId: string;
|
|
138
201
|
compositionId: string;
|
|
139
202
|
hasNarration: boolean;
|
|
203
|
+
hasPresenter: boolean;
|
|
140
204
|
fps: number;
|
|
141
205
|
width: number;
|
|
142
206
|
height: number;
|
|
207
|
+
captions: boolean;
|
|
143
208
|
}
|
|
144
209
|
|
|
145
210
|
interface EntryResolutionResult {
|
|
@@ -171,11 +236,13 @@ async function resolveEntryPoint(input: EntryResolutionInput): Promise<EntryReso
|
|
|
171
236
|
renderFilePath,
|
|
172
237
|
scenarioId: input.scenarioId,
|
|
173
238
|
hasNarration: input.hasNarration,
|
|
239
|
+
hasPresenter: input.hasPresenter,
|
|
174
240
|
providersPath,
|
|
175
241
|
fps: input.fps,
|
|
176
242
|
width: input.width,
|
|
177
243
|
height: input.height,
|
|
178
244
|
compositionId: input.compositionId,
|
|
245
|
+
captions: input.captions,
|
|
179
246
|
});
|
|
180
247
|
|
|
181
248
|
// Write the entry inside the scenario directory so webpack's standard
|
|
@@ -232,6 +299,8 @@ interface RenderConfig {
|
|
|
232
299
|
width: number;
|
|
233
300
|
height: number;
|
|
234
301
|
webpackOverride?: (config: unknown) => unknown;
|
|
302
|
+
/** Staged audio dir for Remotion's staticFile() resolution, if any. */
|
|
303
|
+
publicDir?: string;
|
|
235
304
|
onLog: (message: string) => void;
|
|
236
305
|
}
|
|
237
306
|
|
|
@@ -254,6 +323,9 @@ async function renderScenario(config: RenderConfig): Promise<void> {
|
|
|
254
323
|
if (config.webpackOverride) {
|
|
255
324
|
bundleOptions.webpackOverride = config.webpackOverride;
|
|
256
325
|
}
|
|
326
|
+
if (config.publicDir) {
|
|
327
|
+
bundleOptions.publicDir = config.publicDir;
|
|
328
|
+
}
|
|
257
329
|
const serveUrl = await (bundler.bundle as (opts: Record<string, unknown>) => Promise<string>)(
|
|
258
330
|
bundleOptions,
|
|
259
331
|
);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AuthoredSoundtrack, AuthoredTitleCards } from "../util/load-ts.js";
|
|
2
|
+
import { type SfxAssetPaths } from "../util/soundtrack-assets.js";
|
|
3
|
+
export interface StageRenderAssetsInput {
|
|
4
|
+
/** Absolute path to the scenario directory. */
|
|
5
|
+
readonly scenarioDir: string;
|
|
6
|
+
/** Absolute path of the Remotion public dir to stage into (created). */
|
|
7
|
+
readonly publicDir: string;
|
|
8
|
+
/** Whether the scenario has a narration manifest (+ clips to stage). */
|
|
9
|
+
readonly hasNarration: boolean;
|
|
10
|
+
/** Whether the scenario has a presenter manifest (+ clips to stage). */
|
|
11
|
+
readonly hasPresenter?: boolean;
|
|
12
|
+
/** The scenario's authored soundtrack, if any. */
|
|
13
|
+
readonly soundtrack?: AuthoredSoundtrack;
|
|
14
|
+
/**
|
|
15
|
+
* Absolute locations of the built-in SFX assets — required when
|
|
16
|
+
* `soundtrack.sfx` is enabled (the caller resolves them from
|
|
17
|
+
* `@scenar/react` via `resolveSfxAssetPaths`).
|
|
18
|
+
*/
|
|
19
|
+
readonly sfxPaths?: SfxAssetPaths;
|
|
20
|
+
/** The scenario's authored title cards, if any (logo assets to stage). */
|
|
21
|
+
readonly titleCards?: AuthoredTitleCards;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Stage every local asset a render needs into a Remotion public dir, so
|
|
25
|
+
* `staticFile()` resolution inside `ScenarioComposition` finds real files.
|
|
26
|
+
*
|
|
27
|
+
* The layout mirrors how each src is written:
|
|
28
|
+
* - Narration clips: manifest srcs are manifest-relative (`./step-N.mp3`),
|
|
29
|
+
* so the clips stage flat at the public root.
|
|
30
|
+
* - Presenter clips: same convention (`./step-N.mp4`), staged flat at the
|
|
31
|
+
* public root beside the narration clips — the extensions never collide.
|
|
32
|
+
* - Music: `musicSrc` is scenario-relative (`./soundtrack/music.mp3`), so
|
|
33
|
+
* the file stages at that same relative path. Remote URLs stage nothing.
|
|
34
|
+
* - Built-in SFX: staged at {@link SFX_DEST_PATHS}, the composition's
|
|
35
|
+
* default `sfxSrcs`.
|
|
36
|
+
* - Title-card logos: `logoSrc` is scenario-relative like music, staged
|
|
37
|
+
* at its relative path (intro and outro may share one file — it stages
|
|
38
|
+
* once). Remote URLs stage nothing.
|
|
39
|
+
*
|
|
40
|
+
* Returns the number of files staged. Zero means the render needs no
|
|
41
|
+
* local assets and the caller can skip the public dir entirely.
|
|
42
|
+
*/
|
|
43
|
+
export declare function stageRenderAssets(input: StageRenderAssetsInput): Promise<number>;
|
|
44
|
+
//# sourceMappingURL=stage-assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-assets.d.ts","sourceRoot":"","sources":["../../../src/render/stage-assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,sBAAsB;IACrC,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDtF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { copyFile, mkdir, readdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { SFX_DEST_PATHS, resolveMusicAsset, } from "../util/soundtrack-assets.js";
|
|
4
|
+
import { resolveLogoAsset } from "../util/scenario-assets.js";
|
|
5
|
+
/**
|
|
6
|
+
* Stage every local asset a render needs into a Remotion public dir, so
|
|
7
|
+
* `staticFile()` resolution inside `ScenarioComposition` finds real files.
|
|
8
|
+
*
|
|
9
|
+
* The layout mirrors how each src is written:
|
|
10
|
+
* - Narration clips: manifest srcs are manifest-relative (`./step-N.mp3`),
|
|
11
|
+
* so the clips stage flat at the public root.
|
|
12
|
+
* - Presenter clips: same convention (`./step-N.mp4`), staged flat at the
|
|
13
|
+
* public root beside the narration clips — the extensions never collide.
|
|
14
|
+
* - Music: `musicSrc` is scenario-relative (`./soundtrack/music.mp3`), so
|
|
15
|
+
* the file stages at that same relative path. Remote URLs stage nothing.
|
|
16
|
+
* - Built-in SFX: staged at {@link SFX_DEST_PATHS}, the composition's
|
|
17
|
+
* default `sfxSrcs`.
|
|
18
|
+
* - Title-card logos: `logoSrc` is scenario-relative like music, staged
|
|
19
|
+
* at its relative path (intro and outro may share one file — it stages
|
|
20
|
+
* once). Remote URLs stage nothing.
|
|
21
|
+
*
|
|
22
|
+
* Returns the number of files staged. Zero means the render needs no
|
|
23
|
+
* local assets and the caller can skip the public dir entirely.
|
|
24
|
+
*/
|
|
25
|
+
export async function stageRenderAssets(input) {
|
|
26
|
+
let staged = 0;
|
|
27
|
+
if (input.hasNarration) {
|
|
28
|
+
staged += await stageClipDirectory(input.scenarioDir, "narration", ".mp3", input.publicDir);
|
|
29
|
+
}
|
|
30
|
+
if (input.hasPresenter) {
|
|
31
|
+
staged += await stageClipDirectory(input.scenarioDir, "presenter", ".mp4", input.publicDir);
|
|
32
|
+
}
|
|
33
|
+
const musicSrc = input.soundtrack?.musicSrc;
|
|
34
|
+
if (musicSrc) {
|
|
35
|
+
const music = await resolveMusicAsset(input.scenarioDir, musicSrc);
|
|
36
|
+
if (music) {
|
|
37
|
+
const dest = join(input.publicDir, music.destRelPath);
|
|
38
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
39
|
+
await copyFile(music.sourcePath, dest);
|
|
40
|
+
staged += 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (input.soundtrack?.sfx && input.sfxPaths) {
|
|
44
|
+
for (const sound of ["click", "keystroke"]) {
|
|
45
|
+
const dest = join(input.publicDir, SFX_DEST_PATHS[sound]);
|
|
46
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
47
|
+
await copyFile(input.sfxPaths[sound], dest);
|
|
48
|
+
staged += 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const stagedLogos = new Set();
|
|
52
|
+
for (const side of ["intro", "outro"]) {
|
|
53
|
+
const logoSrc = input.titleCards?.[side]?.logoSrc;
|
|
54
|
+
if (!logoSrc)
|
|
55
|
+
continue;
|
|
56
|
+
const logo = await resolveLogoAsset(input.scenarioDir, logoSrc, `titleCards.${side}.logoSrc`);
|
|
57
|
+
if (!logo || stagedLogos.has(logo.destRelPath))
|
|
58
|
+
continue;
|
|
59
|
+
const dest = join(input.publicDir, logo.destRelPath);
|
|
60
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
61
|
+
await copyFile(logo.sourcePath, dest);
|
|
62
|
+
stagedLogos.add(logo.destRelPath);
|
|
63
|
+
staged += 1;
|
|
64
|
+
}
|
|
65
|
+
return staged;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Copy every clip of one track (narration mp3s, presenter mp4s) flat into
|
|
69
|
+
* the public root — manifest srcs are manifest-relative (`./step-N.<ext>`),
|
|
70
|
+
* which `staticFile()` resolves at the root.
|
|
71
|
+
*/
|
|
72
|
+
async function stageClipDirectory(scenarioDir, trackDir, extension, publicDir) {
|
|
73
|
+
const sourceDir = join(scenarioDir, trackDir);
|
|
74
|
+
let entries;
|
|
75
|
+
try {
|
|
76
|
+
entries = await readdir(sourceDir, { withFileTypes: true });
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
let staged = 0;
|
|
82
|
+
await mkdir(publicDir, { recursive: true });
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
if (!entry.isFile() || !entry.name.toLowerCase().endsWith(extension))
|
|
85
|
+
continue;
|
|
86
|
+
await copyFile(join(sourceDir, entry.name), join(publicDir, entry.name));
|
|
87
|
+
staged += 1;
|
|
88
|
+
}
|
|
89
|
+
return staged;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=stage-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-assets.js","sourceRoot":"","sources":["../../../src/render/stage-assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,cAAc,EAEd,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAuB9D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAA6B;IACnE,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,IAAI,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,IAAI,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC5C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACnE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YACtD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,MAAM,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,WAAW,CAAU,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,MAAM,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;YAC5C,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,CAAU,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAClD,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,IAAI,GAAG,MAAM,gBAAgB,CACjC,KAAK,CAAC,WAAW,EACjB,OAAO,EACP,cAAc,IAAI,UAAU,CAC7B,CAAC;QACF,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,SAAS;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACtC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,MAAM,IAAI,CAAC,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,kBAAkB,CAC/B,WAAmB,EACnB,QAAgB,EAChB,SAAiB,EACjB,SAAiB;IAEjB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,SAAS;QAC/E,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,MAAM,IAAI,CAAC,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|