demo-composer 0.1.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.
@@ -0,0 +1,511 @@
1
+ import Ffmpeg from 'fluent-ffmpeg';
2
+ import { join } from 'node:path';
3
+ import { mkdir, writeFile } from 'node:fs/promises';
4
+ import { chromium } from 'playwright';
5
+ import { createTempDir, getConfiguration } from './configuration.js';
6
+ import { renderOverlayImages } from './overlay.js';
7
+ import { titleCardHtml as defaultTitleCardHtml, subtitleHtml as defaultSubtitleHtml, introCardHtml as defaultIntroCardHtml, conclusionCardHtml as defaultConclusionCardHtml, popupShadowHtml as defaultPopupShadowHtml, } from './templates.js';
8
+ let renderBrowser;
9
+ async function getRenderBrowser() {
10
+ if (!renderBrowser) {
11
+ renderBrowser = await chromium.launch({ headless: true });
12
+ }
13
+ return renderBrowser;
14
+ }
15
+ async function renderHtmlToImage(html, outputPath, width, height) {
16
+ const { deviceScaleFactor } = getConfiguration();
17
+ const browser = await getRenderBrowser();
18
+ const page = await browser.newPage({ viewport: { width, height }, deviceScaleFactor });
19
+ await page.setContent(html, { waitUntil: 'load' });
20
+ await page.screenshot({ path: outputPath, type: 'png', omitBackground: true });
21
+ await page.close();
22
+ }
23
+ function resolveTemplates(overrides) {
24
+ return {
25
+ titleCardHtml: overrides?.titleCardHtml ?? defaultTitleCardHtml,
26
+ subtitleHtml: overrides?.subtitleHtml ?? defaultSubtitleHtml,
27
+ introCardHtml: overrides?.introCardHtml ?? defaultIntroCardHtml,
28
+ conclusionCardHtml: overrides?.conclusionCardHtml ?? defaultConclusionCardHtml,
29
+ popupShadowHtml: overrides?.popupShadowHtml ?? defaultPopupShadowHtml,
30
+ };
31
+ }
32
+ function ffmpegPromise(command) {
33
+ return new Promise((resolve, reject) => {
34
+ const stderrLines = [];
35
+ command
36
+ .on('stderr', (line) => stderrLines.push(line))
37
+ .on('end', () => resolve())
38
+ .on('error', (err) => {
39
+ const detail = stderrLines.slice(-30).join('\n');
40
+ reject(new Error(`${err.message}\n\nffmpeg stderr:\n${detail}`));
41
+ })
42
+ .run();
43
+ });
44
+ }
45
+ async function getMediaDuration(filePath) {
46
+ return new Promise((resolve, reject) => {
47
+ Ffmpeg.ffprobe(filePath, (err, metadata) => {
48
+ if (err)
49
+ return reject(err);
50
+ resolve(metadata.format.duration ?? 0);
51
+ });
52
+ });
53
+ }
54
+ async function createBookendCard(renderImage, audio, outputPath, postAudioPauseSeconds = 0) {
55
+ const config = getConfiguration();
56
+ const audioDuration = await getMediaDuration(audio.filePath);
57
+ const duration = Math.max(audioDuration + 1, 3) + postAudioPauseSeconds;
58
+ const tmpDir = await createTempDir('bookend-card');
59
+ const imagePath = join(tmpDir, 'card.png');
60
+ await renderImage(imagePath);
61
+ const command = Ffmpeg()
62
+ .input(imagePath)
63
+ .inputOptions(['-loop', '1', '-framerate', String(config.fps)])
64
+ .input(audio.filePath);
65
+ if (postAudioPauseSeconds > 0) {
66
+ command.complexFilter([
67
+ { filter: 'apad', inputs: '1:a', outputs: 'apadded' },
68
+ ]);
69
+ command.outputOptions(['-map', '0:v', '-map', '[apadded]', '-t', String(duration), '-pix_fmt', 'yuv420p']);
70
+ }
71
+ else {
72
+ command.outputOptions(['-t', String(duration), '-shortest', '-pix_fmt', 'yuv420p']);
73
+ }
74
+ command
75
+ .output(outputPath)
76
+ .format('matroska')
77
+ .videoCodec('libx264')
78
+ .outputOptions(['-crf', '0', '-preset', 'ultrafast'])
79
+ .audioCodec('aac');
80
+ await ffmpegPromise(command);
81
+ }
82
+ async function createTitleCard(scenarioName, featureName, titleAudio, outputPath, width, height, overlayImagePath, templates, postAudioPauseSeconds = 0) {
83
+ const t = resolveTemplates(templates);
84
+ const audioDuration = await getMediaDuration(titleAudio.filePath);
85
+ const duration = Math.max(audioDuration + 1, 3) + postAudioPauseSeconds;
86
+ const tmpDir = await createTempDir('title-card');
87
+ const titleImagePath = join(tmpDir, 'title.png');
88
+ const html = t.titleCardHtml(scenarioName, featureName, width, height);
89
+ await renderHtmlToImage(html, titleImagePath, width, height);
90
+ const command = Ffmpeg()
91
+ .input(titleImagePath)
92
+ .inputOptions(['-loop', '1', '-framerate', String(getConfiguration().fps)])
93
+ .input(titleAudio.filePath);
94
+ if (overlayImagePath) {
95
+ command.input(overlayImagePath);
96
+ const overlayFilters = [
97
+ { filter: 'overlay', options: { x: 0, y: 0 }, inputs: ['0:v', '2:v'], outputs: 'vout' },
98
+ { filter: 'format', options: { pix_fmts: 'yuv420p' }, inputs: 'vout', outputs: 'vfinal' },
99
+ ];
100
+ if (postAudioPauseSeconds > 0) {
101
+ overlayFilters.push({ filter: 'apad', inputs: '1:a', outputs: 'apadded' });
102
+ command.complexFilter(overlayFilters);
103
+ command.map('[vfinal]');
104
+ command.outputOptions(['-map', '[apadded]', '-t', String(duration)]);
105
+ }
106
+ else {
107
+ command.complexFilter(overlayFilters);
108
+ command.map('[vfinal]');
109
+ command.outputOptions(['-map', '1:a', '-t', String(duration), '-shortest']);
110
+ }
111
+ }
112
+ else if (postAudioPauseSeconds > 0) {
113
+ command.complexFilter([
114
+ { filter: 'apad', inputs: '1:a', outputs: 'apadded' },
115
+ ]);
116
+ command.outputOptions(['-map', '0:v', '-map', '[apadded]', '-t', String(duration), '-pix_fmt', 'yuv420p']);
117
+ }
118
+ else {
119
+ command.outputOptions(['-t', String(duration), '-shortest', '-pix_fmt', 'yuv420p']);
120
+ }
121
+ command
122
+ .output(outputPath)
123
+ .format('matroska')
124
+ .videoCodec('libx264')
125
+ .outputOptions(['-crf', '0', '-preset', 'ultrafast'])
126
+ .audioCodec('aac');
127
+ await ffmpegPromise(command);
128
+ }
129
+ async function createAnnotatedScenarioVideo(recording, stepAudios, narration, outputPath, width, height, overlayImagePath, templates) {
130
+ const t = resolveTemplates(templates);
131
+ const dpr = getConfiguration().deviceScaleFactor;
132
+ const tmpDir = await createTempDir('subtitles');
133
+ const subtitleImages = await Promise.all(recording.stepTimings.map(async (timing, i) => {
134
+ const narrationText = narration.steps[i]?.narration ?? timing.stepText;
135
+ const imgPath = join(tmpDir, `sub-${i}.png`);
136
+ const html = t.subtitleHtml(narrationText, width, height);
137
+ await renderHtmlToImage(html, imgPath, width, height);
138
+ return imgPath;
139
+ }));
140
+ const adjustedTimings = [];
141
+ let earliestNextStart = 0;
142
+ for (let i = 0; i < stepAudios.length && i < recording.stepTimings.length; i++) {
143
+ const audioDuration = await getMediaDuration(stepAudios[i].filePath);
144
+ const stepStartMs = recording.stepTimings[i].startTime * 1000;
145
+ const delayMs = Math.round(Math.max(stepStartMs - audioDuration * 1000, earliestNextStart, 0));
146
+ earliestNextStart = delayMs + audioDuration * 1000;
147
+ adjustedTimings.push({ delayMs, audioDuration });
148
+ }
149
+ const command = Ffmpeg().input(recording.videoPath);
150
+ for (let i = 0; i < stepAudios.length; i++) {
151
+ command.input(stepAudios[i].filePath);
152
+ }
153
+ const popupVideos = recording.popupVideos ?? [];
154
+ for (const popup of popupVideos) {
155
+ command.input(popup.videoPath).inputOptions(['-itsoffset', String(popup.startTime)]);
156
+ }
157
+ const popupShadowImages = [];
158
+ for (let i = 0; i < popupVideos.length; i++) {
159
+ const popup = popupVideos[i];
160
+ const maxW = Math.round(width * 0.8);
161
+ const maxH = Math.round(height * 0.8);
162
+ let pipW = popup.width;
163
+ let pipH = popup.height;
164
+ if (pipW > maxW || pipH > maxH) {
165
+ const scale = Math.min(maxW / pipW, maxH / pipH);
166
+ pipW = Math.round(pipW * scale);
167
+ pipH = Math.round(pipH * scale);
168
+ }
169
+ const shadowPath = join(tmpDir, `popup-shadow-${i}.png`);
170
+ const shadowHtml = t.popupShadowHtml(pipW, pipH, width, height);
171
+ await renderHtmlToImage(shadowHtml, shadowPath, width, height);
172
+ popupShadowImages.push(shadowPath);
173
+ command.input(shadowPath);
174
+ }
175
+ for (const imgPath of subtitleImages) {
176
+ command.input(imgPath);
177
+ }
178
+ if (overlayImagePath) {
179
+ command.input(overlayImagePath);
180
+ }
181
+ const audioInputOffset = 1;
182
+ const popupInputOffset = audioInputOffset + stepAudios.length;
183
+ const popupShadowInputOffset = popupInputOffset + popupVideos.length;
184
+ const imageInputOffset = popupShadowInputOffset + popupShadowImages.length;
185
+ const overlayInputIdx = imageInputOffset + subtitleImages.length;
186
+ const filters = [];
187
+ let lastVideoLabel = '0:v';
188
+ for (let i = 0; i < popupVideos.length; i++) {
189
+ const popup = popupVideos[i];
190
+ const pipInput = `${popupInputOffset + i}:v`;
191
+ const croppedLabel = `pcrop${i}`;
192
+ filters.push({
193
+ filter: 'crop',
194
+ options: { w: popup.width * dpr, h: popup.height * dpr, x: 0, y: 0 },
195
+ inputs: pipInput,
196
+ outputs: croppedLabel,
197
+ });
198
+ const maxW = Math.round(width * dpr * 0.8);
199
+ const maxH = Math.round(height * dpr * 0.8);
200
+ let pipW = popup.width * dpr;
201
+ let pipH = popup.height * dpr;
202
+ let pipLabel = croppedLabel;
203
+ if (pipW > maxW || pipH > maxH) {
204
+ const scale = Math.min(maxW / pipW, maxH / pipH);
205
+ pipW = Math.round(pipW * scale);
206
+ pipH = Math.round(pipH * scale);
207
+ const scaledLabel = `pscaled${i}`;
208
+ filters.push({
209
+ filter: 'scale',
210
+ options: { w: pipW, h: pipH },
211
+ inputs: croppedLabel,
212
+ outputs: scaledLabel,
213
+ });
214
+ pipLabel = scaledLabel;
215
+ }
216
+ const pipX = Math.round((width * dpr - pipW) / 2);
217
+ const pipY = Math.round((height * dpr - pipH) / 2);
218
+ const enableExpr = `between(t,${popup.startTime},${popup.endTime})`;
219
+ const shadowLabel = `pshadow${i}`;
220
+ filters.push({
221
+ filter: 'overlay',
222
+ options: { x: 0, y: 0, enable: enableExpr },
223
+ inputs: [lastVideoLabel, `${popupShadowInputOffset + i}:v`],
224
+ outputs: shadowLabel,
225
+ });
226
+ const outLabel = `pip${i}`;
227
+ filters.push({
228
+ filter: 'overlay',
229
+ options: { x: pipX, y: pipY, enable: enableExpr },
230
+ inputs: [shadowLabel, pipLabel],
231
+ outputs: outLabel,
232
+ });
233
+ lastVideoLabel = outLabel;
234
+ }
235
+ const SUBTITLE_FADE_SECONDS = 0.3;
236
+ for (let i = 0; i < subtitleImages.length; i++) {
237
+ const imgInput = `${imageInputOffset + i}:v`;
238
+ const outLabel = `sub${i}`;
239
+ const subtitleStart = i < adjustedTimings.length
240
+ ? adjustedTimings[i].delayMs / 1000
241
+ : recording.stepTimings[i].startTime;
242
+ const subtitleEnd = i < adjustedTimings.length
243
+ ? (adjustedTimings[i].delayMs / 1000) + adjustedTimings[i].audioDuration + 1
244
+ : recording.stepTimings[i].endTime + 1;
245
+ const fadeOutStart = Math.max(subtitleEnd - SUBTITLE_FADE_SECONDS, subtitleStart);
246
+ const fadedLabel = `subfade${i}`;
247
+ filters.push({
248
+ filter: 'fade',
249
+ options: { t: 'in', st: subtitleStart, d: SUBTITLE_FADE_SECONDS, alpha: 1 },
250
+ inputs: imgInput,
251
+ outputs: `subfadein${i}`,
252
+ });
253
+ filters.push({
254
+ filter: 'fade',
255
+ options: { t: 'out', st: fadeOutStart, d: SUBTITLE_FADE_SECONDS, alpha: 1 },
256
+ inputs: `subfadein${i}`,
257
+ outputs: fadedLabel,
258
+ });
259
+ filters.push({
260
+ filter: 'overlay',
261
+ options: {
262
+ x: 0,
263
+ y: 0,
264
+ enable: `between(t,${subtitleStart},${subtitleEnd})`,
265
+ },
266
+ inputs: [lastVideoLabel, fadedLabel],
267
+ outputs: outLabel,
268
+ });
269
+ lastVideoLabel = outLabel;
270
+ }
271
+ if (overlayImagePath) {
272
+ const outLabel = 'withoverlay';
273
+ filters.push({
274
+ filter: 'overlay',
275
+ options: { x: 0, y: 0 },
276
+ inputs: [lastVideoLabel, `${overlayInputIdx}:v`],
277
+ outputs: outLabel,
278
+ });
279
+ lastVideoLabel = outLabel;
280
+ }
281
+ const mixInputs = [];
282
+ for (let i = 0; i < adjustedTimings.length; i++) {
283
+ const { delayMs } = adjustedTimings[i];
284
+ const delayedLabel = `adelay${i}`;
285
+ filters.push({
286
+ filter: 'adelay',
287
+ options: { delays: `${delayMs}|${delayMs}`, all: 1 },
288
+ inputs: `${audioInputOffset + i}:a`,
289
+ outputs: delayedLabel,
290
+ });
291
+ mixInputs.push(delayedLabel);
292
+ }
293
+ if (mixInputs.length > 0) {
294
+ filters.push({
295
+ filter: 'amix',
296
+ options: { inputs: mixInputs.length, duration: 'longest', dropout_transition: 0, normalize: 0 },
297
+ inputs: mixInputs,
298
+ outputs: 'amixed',
299
+ });
300
+ filters.push({
301
+ filter: 'apad',
302
+ inputs: 'amixed',
303
+ outputs: 'apadded',
304
+ });
305
+ }
306
+ if (filters.length > 0) {
307
+ command.complexFilter(filters);
308
+ command.map(`[${lastVideoLabel}]`);
309
+ if (mixInputs.length > 0) {
310
+ command.outputOptions(['-map', '[apadded]']);
311
+ }
312
+ }
313
+ command
314
+ .output(outputPath)
315
+ .outputOptions(['-shortest', '-pix_fmt', 'yuv420p'])
316
+ .format('matroska')
317
+ .videoCodec('libx264')
318
+ .outputOptions(['-crf', '0', '-preset', 'ultrafast'])
319
+ .audioCodec('aac');
320
+ await ffmpegPromise(command);
321
+ }
322
+ async function concatenateAndEncode(videoPaths, outputPath, music) {
323
+ const tmpDir = await createTempDir('concat');
324
+ const config = getConfiguration();
325
+ const cf = config.crossfadeDurationSeconds;
326
+ const useCrossfade = videoPaths.length > 1 && cf > 0;
327
+ // Fast path: simple concat straight to output (no music, no crossfade)
328
+ if (!music && !useCrossfade) {
329
+ const listFile = join(tmpDir, 'concat.txt');
330
+ const listContent = videoPaths.map((p) => `file '${p}'`).join('\n');
331
+ await writeFile(listFile, listContent);
332
+ const command = Ffmpeg()
333
+ .input(listFile)
334
+ .inputOptions(['-f', 'concat', '-safe', '0'])
335
+ .output(outputPath)
336
+ .format('mp4')
337
+ .videoCodec('libx264')
338
+ .outputOptions(['-preset', 'medium', '-crf', '18', '-r', String(config.fps), '-pix_fmt', 'yuv420p'])
339
+ .audioCodec('aac');
340
+ await ffmpegPromise(command);
341
+ return;
342
+ }
343
+ // Build intermediate: either via xfade crossfade or simple concat
344
+ const intermediatePath = join(tmpDir, 'intermediate.mkv');
345
+ if (useCrossfade) {
346
+ const durations = await Promise.all(videoPaths.map(getMediaDuration));
347
+ const command = Ffmpeg();
348
+ for (const p of videoPaths) {
349
+ command.input(p);
350
+ }
351
+ const filters = [];
352
+ // Normalize all inputs to the target fps before crossfading
353
+ for (let i = 0; i < videoPaths.length; i++) {
354
+ filters.push({
355
+ filter: 'fps',
356
+ options: { fps: config.fps },
357
+ inputs: `${i}:v`,
358
+ outputs: `vfps${i}`,
359
+ });
360
+ }
361
+ let lastV = 'vfps0';
362
+ let lastA = '0:a';
363
+ for (let i = 0; i < videoPaths.length - 1; i++) {
364
+ const offset = durations.slice(0, i + 1).reduce((a, b) => a + b, 0) - (i + 1) * cf;
365
+ const vOut = `vxf${i}`;
366
+ const aOut = `axf${i}`;
367
+ filters.push({
368
+ filter: 'xfade',
369
+ options: { transition: 'fade', duration: cf, offset: Math.max(offset, 0) },
370
+ inputs: [lastV, `vfps${i + 1}`],
371
+ outputs: vOut,
372
+ });
373
+ filters.push({
374
+ filter: 'acrossfade',
375
+ options: { d: cf },
376
+ inputs: [lastA, `${i + 1}:a`],
377
+ outputs: aOut,
378
+ });
379
+ lastV = vOut;
380
+ lastA = aOut;
381
+ }
382
+ command.complexFilter(filters);
383
+ if (!music) {
384
+ // Crossfade without music: output directly to MP4
385
+ command
386
+ .outputOptions(['-map', `[${lastV}]`, '-map', `[${lastA}]`])
387
+ .output(outputPath)
388
+ .format('mp4')
389
+ .videoCodec('libx264')
390
+ .outputOptions(['-preset', 'medium', '-crf', '18', '-r', String(config.fps), '-pix_fmt', 'yuv420p'])
391
+ .audioCodec('aac');
392
+ await ffmpegPromise(command);
393
+ return;
394
+ }
395
+ // Crossfade to lossless intermediate for music mixing
396
+ command
397
+ .outputOptions(['-map', `[${lastV}]`, '-map', `[${lastA}]`])
398
+ .output(intermediatePath)
399
+ .format('matroska')
400
+ .videoCodec('libx264')
401
+ .outputOptions(['-crf', '0', '-preset', 'ultrafast'])
402
+ .audioCodec('aac');
403
+ await ffmpegPromise(command);
404
+ }
405
+ else {
406
+ // Simple concat to intermediate for music mixing
407
+ const listFile = join(tmpDir, 'concat.txt');
408
+ const listContent = videoPaths.map((p) => `file '${p}'`).join('\n');
409
+ await writeFile(listFile, listContent);
410
+ const concatCommand = Ffmpeg()
411
+ .input(listFile)
412
+ .inputOptions(['-f', 'concat', '-safe', '0'])
413
+ .output(intermediatePath)
414
+ .format('matroska')
415
+ .videoCodec('copy')
416
+ .audioCodec('copy');
417
+ await ffmpegPromise(concatCommand);
418
+ }
419
+ // Mix in background music
420
+ const totalDuration = await getMediaDuration(intermediatePath);
421
+ const fadeOutStart = Math.max(totalDuration - music.fadeSeconds, 0);
422
+ const mixCommand = Ffmpeg()
423
+ .input(intermediatePath)
424
+ .input(music.filePath)
425
+ .inputOptions(['-stream_loop', '-1']);
426
+ mixCommand.complexFilter([
427
+ {
428
+ filter: 'volume',
429
+ options: { volume: String(music.volume) },
430
+ inputs: '1:a',
431
+ outputs: 'mvol',
432
+ },
433
+ {
434
+ filter: 'afade',
435
+ options: { t: 'in', st: '0', d: String(music.fadeSeconds) },
436
+ inputs: 'mvol',
437
+ outputs: 'mfadein',
438
+ },
439
+ {
440
+ filter: 'afade',
441
+ options: { t: 'out', st: String(fadeOutStart), d: String(music.fadeSeconds) },
442
+ inputs: 'mfadein',
443
+ outputs: 'mfaded',
444
+ },
445
+ {
446
+ filter: 'asplit',
447
+ options: { outputs: 2 },
448
+ inputs: '0:a',
449
+ outputs: ['narration', 'sidechain'],
450
+ },
451
+ {
452
+ filter: 'sidechaincompress',
453
+ options: { threshold: '0.05', ratio: '3', attack: '200', release: '1000' },
454
+ inputs: ['mfaded', 'sidechain'],
455
+ outputs: 'ducked',
456
+ },
457
+ {
458
+ filter: 'amix',
459
+ options: { inputs: '2', duration: 'first', dropout_transition: '0', normalize: '0' },
460
+ inputs: ['narration', 'ducked'],
461
+ outputs: 'final',
462
+ },
463
+ ]);
464
+ mixCommand
465
+ .outputOptions(['-map', '0:v', '-map', '[final]'])
466
+ .output(outputPath)
467
+ .format('mp4')
468
+ .videoCodec('libx264')
469
+ .outputOptions(['-preset', 'medium', '-crf', '18', '-r', String(config.fps), '-pix_fmt', 'yuv420p'])
470
+ .audioCodec('aac');
471
+ await ffmpegPromise(mixCommand);
472
+ }
473
+ export async function composeFeatureVideo(inputs, featureName, featureDescription, introAudio, conclusionAudio, outputDir, width, height, music, templates) {
474
+ const t = resolveTemplates(templates);
475
+ const config = getConfiguration();
476
+ const tmpDir = await createTempDir('compose');
477
+ const scenarioVideos = [];
478
+ const scenarioNames = inputs.map((inp) => inp.recording.scenarioName);
479
+ const introPath = join(tmpDir, 'intro.mkv');
480
+ await createBookendCard(async (outputPath) => {
481
+ const html = t.introCardHtml(featureName, featureDescription, config.introLabel, width, height);
482
+ await renderHtmlToImage(html, outputPath, width, height);
483
+ }, introAudio, introPath, config.scenarioEndPauseMs / 1000);
484
+ scenarioVideos.push(introPath);
485
+ const overlayImages = await renderOverlayImages(featureName, scenarioNames, width, height, renderHtmlToImage, templates?.overlayHtml);
486
+ for (let i = 0; i < inputs.length; i++) {
487
+ const { recording, narration, titleAudio, stepAudios } = inputs[i];
488
+ const titlePath = join(tmpDir, `title-${i}.mkv`);
489
+ await createTitleCard(recording.scenarioName, featureName, titleAudio, titlePath, width, height, overlayImages[i], templates, config.scenarioEndPauseMs / 1000);
490
+ const annotatedPath = join(tmpDir, `scenario-${i}.mkv`);
491
+ await createAnnotatedScenarioVideo(recording, stepAudios, narration, annotatedPath, width, height, overlayImages[i], templates);
492
+ scenarioVideos.push(titlePath, annotatedPath);
493
+ }
494
+ const conclusionPath = join(tmpDir, 'conclusion.mkv');
495
+ await createBookendCard(async (outputPath) => {
496
+ const html = t.conclusionCardHtml(featureName, width, height);
497
+ await renderHtmlToImage(html, outputPath, width, height);
498
+ }, conclusionAudio, conclusionPath);
499
+ scenarioVideos.push(conclusionPath);
500
+ const featureSlug = featureName.toLowerCase().replace(/[^a-z0-9]+/g, '-');
501
+ const featureOutputDir = join(outputDir, featureSlug);
502
+ await mkdir(featureOutputDir, { recursive: true });
503
+ const outputPath = join(featureOutputDir, `${featureSlug}.mp4`);
504
+ await concatenateAndEncode(scenarioVideos, outputPath, music);
505
+ if (renderBrowser) {
506
+ await renderBrowser.close();
507
+ renderBrowser = undefined;
508
+ }
509
+ return outputPath;
510
+ }
511
+ //# sourceMappingURL=composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer.js","sourceRoot":"","sources":["../src/composer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { z } from 'zod';
2
+ declare const demoJsonSchema: z.ZodObject<{
3
+ width: z.ZodOptional<z.ZodNumber>;
4
+ height: z.ZodOptional<z.ZodNumber>;
5
+ outputDir: z.ZodOptional<z.ZodString>;
6
+ featuresGlob: z.ZodOptional<z.ZodString>;
7
+ musicFile: z.ZodOptional<z.ZodString>;
8
+ musicVolume: z.ZodOptional<z.ZodNumber>;
9
+ musicFadeSeconds: z.ZodOptional<z.ZodNumber>;
10
+ stepDelayMs: z.ZodOptional<z.ZodNumber>;
11
+ stepSettleMs: z.ZodOptional<z.ZodNumber>;
12
+ scenarioEndPauseMs: z.ZodOptional<z.ZodNumber>;
13
+ ttsModel: z.ZodOptional<z.ZodString>;
14
+ ttsVoice: z.ZodOptional<z.ZodString>;
15
+ ttsStylePreamble: z.ZodOptional<z.ZodString>;
16
+ introLabel: z.ZodOptional<z.ZodString>;
17
+ deviceScaleFactor: z.ZodOptional<z.ZodNumber>;
18
+ fps: z.ZodOptional<z.ZodNumber>;
19
+ crossfadeDurationSeconds: z.ZodOptional<z.ZodNumber>;
20
+ }, "strict", z.ZodTypeAny, {
21
+ width?: number | undefined;
22
+ height?: number | undefined;
23
+ outputDir?: string | undefined;
24
+ featuresGlob?: string | undefined;
25
+ musicFile?: string | undefined;
26
+ musicVolume?: number | undefined;
27
+ musicFadeSeconds?: number | undefined;
28
+ stepDelayMs?: number | undefined;
29
+ stepSettleMs?: number | undefined;
30
+ scenarioEndPauseMs?: number | undefined;
31
+ ttsModel?: string | undefined;
32
+ ttsVoice?: string | undefined;
33
+ ttsStylePreamble?: string | undefined;
34
+ introLabel?: string | undefined;
35
+ deviceScaleFactor?: number | undefined;
36
+ fps?: number | undefined;
37
+ crossfadeDurationSeconds?: number | undefined;
38
+ }, {
39
+ width?: number | undefined;
40
+ height?: number | undefined;
41
+ outputDir?: string | undefined;
42
+ featuresGlob?: string | undefined;
43
+ musicFile?: string | undefined;
44
+ musicVolume?: number | undefined;
45
+ musicFadeSeconds?: number | undefined;
46
+ stepDelayMs?: number | undefined;
47
+ stepSettleMs?: number | undefined;
48
+ scenarioEndPauseMs?: number | undefined;
49
+ ttsModel?: string | undefined;
50
+ ttsVoice?: string | undefined;
51
+ ttsStylePreamble?: string | undefined;
52
+ introLabel?: string | undefined;
53
+ deviceScaleFactor?: number | undefined;
54
+ fps?: number | undefined;
55
+ crossfadeDurationSeconds?: number | undefined;
56
+ }>;
57
+ export type DemoJson = z.infer<typeof demoJsonSchema>;
58
+ interface ResolvedConfig {
59
+ appBaseUrl: string;
60
+ width: number;
61
+ height: number;
62
+ outputDir: string;
63
+ featuresGlob: string;
64
+ musicFile: string;
65
+ musicVolume: number;
66
+ musicFadeSeconds: number;
67
+ stepDelayMs: number;
68
+ stepSettleMs: number;
69
+ scenarioEndPauseMs: number;
70
+ ttsModel: string;
71
+ ttsVoice: string;
72
+ ttsStylePreamble: string;
73
+ introLabel: string;
74
+ deviceScaleFactor: number;
75
+ fps: number;
76
+ crossfadeDurationSeconds: number;
77
+ googleCloudProject: string;
78
+ googleCloudRegion: string;
79
+ narrationTimingFile: string;
80
+ manifestDir: string;
81
+ browserHeadless: boolean;
82
+ }
83
+ export type DemoConfiguration = Readonly<ResolvedConfig>;
84
+ export declare function loadConfiguration(cwd?: string): DemoConfiguration;
85
+ export declare function initConfiguration(cwd: string): DemoConfiguration;
86
+ export declare function getConfiguration(): DemoConfiguration;
87
+ export declare function resetConfiguration(): void;
88
+ export declare function createTempDir(prefix: string): Promise<string>;
89
+ export {};