@argo-video/cli 0.12.3 → 0.14.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.
Files changed (52) hide show
  1. package/README.md +102 -2
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +108 -7
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +24 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/dashboard.d.ts +22 -0
  9. package/dist/dashboard.d.ts.map +1 -0
  10. package/dist/dashboard.js +186 -0
  11. package/dist/dashboard.js.map +1 -0
  12. package/dist/export.d.ts +13 -2
  13. package/dist/export.d.ts.map +1 -1
  14. package/dist/export.js +136 -16
  15. package/dist/export.js.map +1 -1
  16. package/dist/index.d.ts +6 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +10 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/media.d.ts +2 -0
  21. package/dist/media.d.ts.map +1 -0
  22. package/dist/media.js +18 -0
  23. package/dist/media.js.map +1 -0
  24. package/dist/pipeline.d.ts +8 -0
  25. package/dist/pipeline.d.ts.map +1 -1
  26. package/dist/pipeline.js +62 -53
  27. package/dist/pipeline.js.map +1 -1
  28. package/dist/preview.d.ts +13 -0
  29. package/dist/preview.d.ts.map +1 -1
  30. package/dist/preview.js +27 -10
  31. package/dist/preview.js.map +1 -1
  32. package/dist/progress.d.ts +8 -0
  33. package/dist/progress.d.ts.map +1 -0
  34. package/dist/progress.js +67 -0
  35. package/dist/progress.js.map +1 -0
  36. package/dist/record.d.ts +3 -0
  37. package/dist/record.d.ts.map +1 -1
  38. package/dist/record.js +13 -1
  39. package/dist/record.js.map +1 -1
  40. package/dist/speed-ramp.d.ts +39 -0
  41. package/dist/speed-ramp.d.ts.map +1 -0
  42. package/dist/speed-ramp.js +184 -0
  43. package/dist/speed-ramp.js.map +1 -0
  44. package/dist/timeline.d.ts +19 -0
  45. package/dist/timeline.d.ts.map +1 -0
  46. package/dist/timeline.js +82 -0
  47. package/dist/timeline.js.map +1 -0
  48. package/dist/transitions.d.ts +15 -0
  49. package/dist/transitions.d.ts.map +1 -0
  50. package/dist/transitions.js +124 -0
  51. package/dist/transitions.js.map +1 -0
  52. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
package/dist/export.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type { Placement } from './tts/align.js';
2
+ import type { TransitionConfig } from './config.js';
3
+ import { type Segment } from './speed-ramp.js';
1
4
  export interface ExportOptions {
2
5
  demoName: string;
3
6
  argoDir: string;
@@ -18,8 +21,16 @@ export interface ExportOptions {
18
21
  thumbnailPath?: string;
19
22
  /** Optional path to ffmpeg chapter metadata file for MP4 chapter markers. */
20
23
  chapterMetadataPath?: string;
21
- /** Additional aspect ratios to export alongside the main 16:9. */
22
- formats?: Array<'1:1' | '9:16'>;
24
+ /** Additional formats to export alongside the main 16:9. */
25
+ formats?: Array<'1:1' | '9:16' | 'gif'>;
26
+ /** Scene transition config for inter-scene transitions. */
27
+ transition?: TransitionConfig;
28
+ /** Scene placements — needed for transitions. */
29
+ placements?: Placement[];
30
+ /** Estimated total duration in ms — used for progress bar. */
31
+ totalDurationMs?: number;
32
+ /** Precomputed speed-ramp segments on the post-trim timeline. */
33
+ speedRampSegments?: Segment[];
23
34
  }
24
35
  /**
25
36
  * Check whether ffmpeg is available on the system PATH.
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;CACjC;AAMD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAYrC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAoKzE"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;IACxC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iDAAiD;IACjD,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,EAAE,CAAC;CAC/B;AAMD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAYrC;AAuDD;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAqPzE"}
package/dist/export.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { execFileSync, spawnSync } from 'node:child_process';
2
2
  import { existsSync, mkdirSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
+ import { buildTransitionFilters } from './transitions.js';
5
+ import { runFfmpegWithProgress } from './progress.js';
6
+ import { buildSpeedRampFilter } from './speed-ramp.js';
4
7
  function formatSeconds(ms) {
5
8
  return (ms / 1000).toFixed(3).replace(/\.?0+$/, '');
6
9
  }
@@ -20,11 +23,54 @@ export function checkFfmpeg() {
20
23
  ' Windows: choco install ffmpeg');
21
24
  }
22
25
  }
26
+ /**
27
+ * Export an MP4 to animated GIF with palette optimization.
28
+ */
29
+ async function exportGif(mp4Path, gifPath, fps = 10, width = 640) {
30
+ // Two-pass approach: generate palette first, then use it for high-quality GIF
31
+ const palettePath = mp4Path.replace(/\.mp4$/, '.palette.png');
32
+ const paletteArgs = [
33
+ '-i', mp4Path,
34
+ '-vf', `fps=${fps},scale=${width}:-1:flags=lanczos,palettegen=stats_mode=diff`,
35
+ '-y', palettePath,
36
+ ];
37
+ const paletteResult = spawnSync('ffmpeg', paletteArgs, { stdio: 'pipe' });
38
+ if (paletteResult.status !== 0) {
39
+ console.warn('Warning: GIF palette generation failed, using single-pass fallback');
40
+ // Single-pass fallback
41
+ const fallbackArgs = [
42
+ '-i', mp4Path,
43
+ '-vf', `fps=${fps},scale=${width}:-1:flags=lanczos`,
44
+ '-y', gifPath,
45
+ ];
46
+ const fbResult = spawnSync('ffmpeg', fallbackArgs, { stdio: 'inherit' });
47
+ if (fbResult.status !== 0) {
48
+ console.warn(`Warning: GIF export failed`);
49
+ }
50
+ return;
51
+ }
52
+ const gifArgs = [
53
+ '-i', mp4Path,
54
+ '-i', palettePath,
55
+ '-lavfi', `fps=${fps},scale=${width}:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5`,
56
+ '-y', gifPath,
57
+ ];
58
+ const gifResult = spawnSync('ffmpeg', gifArgs, { stdio: 'pipe' });
59
+ if (gifResult.status !== 0) {
60
+ console.warn(`Warning: GIF export failed`);
61
+ }
62
+ // Clean up palette
63
+ try {
64
+ const { unlinkSync } = await import('node:fs');
65
+ unlinkSync(palettePath);
66
+ }
67
+ catch { /* ignore */ }
68
+ }
23
69
  /**
24
70
  * Export a demo to MP4 by combining the screen recording with aligned narration audio.
25
71
  */
26
72
  export async function exportVideo(options) {
27
- const { demoName, argoDir, outputDir, preset = 'slow', crf = 16, fps, tailPadMs, outputWidth, outputHeight, deviceScaleFactor = 1, thumbnailPath, chapterMetadataPath, } = options;
73
+ const { demoName, argoDir, outputDir, preset = 'slow', crf = 16, fps, tailPadMs, outputWidth, outputHeight, deviceScaleFactor = 1, thumbnailPath, chapterMetadataPath, transition, placements, totalDurationMs, speedRampSegments, } = options;
28
74
  checkFfmpeg();
29
75
  const demoDir = join(argoDir, demoName);
30
76
  const videoPath = join(demoDir, 'video.webm');
@@ -67,6 +113,17 @@ export async function exportVideo(options) {
67
113
  args.push('-i', thumbnailPath);
68
114
  }
69
115
  // Build video filter chain
116
+ const filterParts = [];
117
+ let videoSource = '0:v';
118
+ let audioSource = hasAudio ? '1:a' : undefined;
119
+ const speedRampFilter = speedRampSegments && speedRampSegments.length > 0
120
+ ? buildSpeedRampFilter(speedRampSegments, { video: '0:v', audio: hasAudio ? '1:a' : undefined })
121
+ : null;
122
+ if (speedRampFilter) {
123
+ filterParts.push(speedRampFilter.filterComplex);
124
+ videoSource = speedRampFilter.outputLabels.video;
125
+ audioSource = speedRampFilter.outputLabels.audio;
126
+ }
70
127
  const vFilters = [];
71
128
  if (tailPadMs && tailPadMs > 0) {
72
129
  vFilters.push(`tpad=stop_mode=clone:stop_duration=${formatSeconds(tailPadMs)}`);
@@ -74,8 +131,51 @@ export async function exportVideo(options) {
74
131
  if (deviceScaleFactor > 1 && outputWidth && outputHeight) {
75
132
  vFilters.push(`scale=${outputWidth}:${outputHeight}:flags=lanczos`);
76
133
  }
77
- if (vFilters.length > 0) {
78
- args.push('-vf', vFilters.join(','));
134
+ // Scene transitions
135
+ let transitionComplex = null;
136
+ if (transition && placements && placements.length > 1) {
137
+ const transitionResult = buildTransitionFilters(placements, transition, hasAudio, fps ?? 30);
138
+ if (Array.isArray(transitionResult)) {
139
+ // Simple -vf filters (wipe)
140
+ vFilters.push(...transitionResult);
141
+ }
142
+ else if (transitionResult.filterComplex) {
143
+ // Complex filter graph (fade/dissolve — split+trim+fade+concat)
144
+ transitionComplex = transitionResult;
145
+ }
146
+ }
147
+ if (transitionComplex) {
148
+ // Fade transitions use filter_complex with split+concat.
149
+ // Apply any vFilters (scale, tpad) before the transition.
150
+ let fc = transitionComplex.filterComplex;
151
+ if (speedRampFilter) {
152
+ fc = fc.replace('[0:v]', `[${videoSource}]`);
153
+ if (audioSource && transitionComplex.audioOutput) {
154
+ fc = fc.replace('[1:a]', `[${audioSource}]`);
155
+ }
156
+ }
157
+ if (vFilters.length > 0) {
158
+ // Prepend vFilters to the video input before split
159
+ const inputRef = speedRampFilter ? `[${videoSource}]` : '[0:v]';
160
+ fc = fc.replace(inputRef + 'split=', `${inputRef}${vFilters.join(',')},split=`);
161
+ }
162
+ filterParts.push(fc);
163
+ videoSource = transitionComplex.videoOutput.replace(/[\[\]]/g, '');
164
+ if (hasAudio && transitionComplex.audioOutput) {
165
+ audioSource = transitionComplex.audioOutput.replace(/[\[\]]/g, '');
166
+ }
167
+ }
168
+ else if (vFilters.length > 0) {
169
+ if (speedRampFilter || filterParts.length > 0) {
170
+ filterParts.push(`[${videoSource}]${vFilters.join(',')}[outvfinal]`);
171
+ videoSource = 'outvfinal';
172
+ }
173
+ else {
174
+ args.push('-vf', vFilters.join(','));
175
+ }
176
+ }
177
+ if (filterParts.length > 0) {
178
+ args.push('-filter_complex', filterParts.join(';\n'));
79
179
  }
80
180
  args.push('-c:v', 'libx264', '-preset', preset, '-crf', String(crf));
81
181
  if (hasAudio) {
@@ -87,11 +187,19 @@ export async function exportVideo(options) {
87
187
  if (hasChapters) {
88
188
  args.push('-map_metadata', String(chapterInputIdx));
89
189
  }
190
+ const usesExplicitMaps = hasThumbnail || filterParts.length > 0;
191
+ const mapRef = (label) => (label.includes(':') ? label : `[${label}]`);
192
+ if (usesExplicitMaps) {
193
+ args.push('-map', mapRef(videoSource));
194
+ if (hasAudio && audioSource)
195
+ args.push('-map', mapRef(audioSource));
196
+ }
90
197
  if (hasThumbnail) {
91
- // Map video, audio (if present), and thumbnail streams explicitly
92
- args.push('-map', '0:v');
93
- if (hasAudio)
94
- args.push('-map', '1:a');
198
+ if (!usesExplicitMaps) {
199
+ args.push('-map', '0:v');
200
+ if (hasAudio)
201
+ args.push('-map', '1:a');
202
+ }
95
203
  args.push('-map', `${thumbInputIdx}:v`);
96
204
  // Encode thumbnail stream as PNG attached picture
97
205
  args.push('-c:v:1', 'png', '-disposition:v:1', 'attached_pic');
@@ -101,19 +209,31 @@ export async function exportVideo(options) {
101
209
  args.push('-shortest');
102
210
  }
103
211
  args.push('-y', outputPath);
104
- const result = spawnSync('ffmpeg', args, { stdio: 'inherit' });
105
- if (result.error) {
106
- throw new Error(`Failed to launch ffmpeg: ${result.error.message}`);
212
+ // Use progress bar when we know the total duration
213
+ if (totalDurationMs && totalDurationMs > 0) {
214
+ await runFfmpegWithProgress(args, totalDurationMs);
107
215
  }
108
- if (result.signal) {
109
- throw new Error(`ffmpeg was killed by signal ${result.signal}`);
110
- }
111
- if (result.status !== 0) {
112
- throw new Error(`ffmpeg failed with exit code ${result.status}`);
216
+ else {
217
+ const result = spawnSync('ffmpeg', args, { stdio: 'inherit' });
218
+ if (result.error) {
219
+ throw new Error(`Failed to launch ffmpeg: ${result.error.message}`);
220
+ }
221
+ if (result.signal) {
222
+ throw new Error(`ffmpeg was killed by signal ${result.signal}`);
223
+ }
224
+ if (result.status !== 0) {
225
+ throw new Error(`ffmpeg failed with exit code ${result.status}`);
226
+ }
113
227
  }
114
- // Export additional aspect ratios by cropping from the main 16:9 output
228
+ // Export additional formats
115
229
  const formats = options.formats ?? [];
116
230
  for (const format of formats) {
231
+ if (format === 'gif') {
232
+ const gifPath = outputPath.replace(/\.mp4$/, '.gif');
233
+ console.log(` Exporting GIF → ${gifPath}`);
234
+ await exportGif(outputPath, gifPath, 10, outputWidth ?? 640);
235
+ continue;
236
+ }
117
237
  const suffix = format.replace(':', 'x');
118
238
  const formatPath = outputPath.replace(/\.mp4$/, `.${suffix}.mp4`);
119
239
  // Compute crop dimensions from 16:9 source
@@ -1 +1 @@
1
- {"version":3,"file":"export.js","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { defineConfig, loadConfig, demosProject, type ArgoConfig, type UserConfig, type TTSConfig, type TTSEngine, type VideoConfig, type ExportConfig, } from './config.js';
1
+ export { defineConfig, loadConfig, demosProject, type ArgoConfig, type UserConfig, type TTSConfig, type TTSEngine, type VideoConfig, type ExportConfig, type TransitionType, type TransitionConfig, type SpeedRampConfig, } from './config.js';
2
2
  export { test, expect, demoType } from './fixtures.js';
3
3
  export { NarrationTimeline, type SceneDurationOptions } from './narration.js';
4
4
  export { showCaption, hideCaption, withCaption } from './captions.js';
@@ -13,5 +13,10 @@ export { generateChapterMetadata } from './chapters.js';
13
13
  export { buildSceneReport, formatSceneReport, type SceneReport } from './report.js';
14
14
  export { validateDemo, type ValidateOptions, type ValidateResult } from './validate.js';
15
15
  export { runDoctor, formatDoctorResults } from './doctor.js';
16
+ export { runPipeline, runBatchPipeline, discoverDemos, type PipelineOptions } from './pipeline.js';
17
+ export { buildTransitionFilters } from './transitions.js';
18
+ export { computeSegments, applySpeedRamp } from './speed-ramp.js';
19
+ export { runFfmpegWithProgress } from './progress.js';
20
+ export { startDashboardServer } from './dashboard.js';
16
21
  export { init } from './init.js';
17
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGtE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,KAAK,UAAU,EACf,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAGlE,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,eAAe,EACf,WAAW,EACX,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAGpF,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGtE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,KAAK,UAAU,EACf,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAGlE,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,eAAe,EACf,WAAW,EACX,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAGpF,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAGnG,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -26,6 +26,16 @@ export { buildSceneReport, formatSceneReport } from './report.js';
26
26
  export { validateDemo } from './validate.js';
27
27
  // Doctor
28
28
  export { runDoctor, formatDoctorResults } from './doctor.js';
29
+ // Pipeline
30
+ export { runPipeline, runBatchPipeline, discoverDemos } from './pipeline.js';
31
+ // Transitions
32
+ export { buildTransitionFilters } from './transitions.js';
33
+ // Speed Ramp
34
+ export { computeSegments, applySpeedRamp } from './speed-ramp.js';
35
+ // Progress
36
+ export { runFfmpegWithProgress } from './progress.js';
37
+ // Dashboard
38
+ export { startDashboardServer } from './dashboard.js';
29
39
  // Init
30
40
  export { init } from './init.js';
31
41
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,SAAS;AACT,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,GAOb,MAAM,aAAa,CAAC;AAErB,WAAW;AACX,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,YAAY;AACZ,OAAO,EAAE,iBAAiB,EAA6B,MAAM,gBAAgB,CAAC;AAE9E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEtE,WAAW;AACX,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,GAMZ,MAAM,qBAAqB,CAAC;AAE7B,UAAU;AACV,OAAO,EAAE,YAAY,EAAwB,MAAM,cAAc,CAAC;AAElE,SAAS;AACT,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,WAAW,GAKZ,MAAM,aAAa,CAAC;AAErB,SAAS;AACT,OAAO,EACL,eAAe,EACf,WAAW,GAEZ,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE1D,WAAW;AACX,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAEpF,WAAW;AACX,OAAO,EAAE,YAAY,EAA6C,MAAM,eAAe,CAAC;AAExF,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO;AACP,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,SAAS;AACT,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,GAUb,MAAM,aAAa,CAAC;AAErB,WAAW;AACX,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,YAAY;AACZ,OAAO,EAAE,iBAAiB,EAA6B,MAAM,gBAAgB,CAAC;AAE9E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEtE,WAAW;AACX,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,GAMZ,MAAM,qBAAqB,CAAC;AAE7B,UAAU;AACV,OAAO,EAAE,YAAY,EAAwB,MAAM,cAAc,CAAC;AAElE,SAAS;AACT,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,WAAW,GAKZ,MAAM,aAAa,CAAC;AAErB,SAAS;AACT,OAAO,EACL,eAAe,EACf,WAAW,GAEZ,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE1D,WAAW;AACX,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAEpF,WAAW;AACX,OAAO,EAAE,YAAY,EAA6C,MAAM,eAAe,CAAC;AAExF,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7D,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAwB,MAAM,eAAe,CAAC;AAEnG,cAAc;AACd,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,aAAa;AACb,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAElE,WAAW;AACX,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,YAAY;AACZ,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO;AACP,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getVideoDurationMs(videoPath: string): number;
2
+ //# sourceMappingURL=media.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAwB5D"}
package/dist/media.js ADDED
@@ -0,0 +1,18 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ export function getVideoDurationMs(videoPath) {
3
+ let raw;
4
+ try {
5
+ raw = execFileSync('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', videoPath], { encoding: 'utf-8' }).trim();
6
+ }
7
+ catch (err) {
8
+ throw new Error(`Failed to get video duration from ${videoPath}. ` +
9
+ `Ensure ffprobe is installed (it usually comes with ffmpeg). ` +
10
+ `Original error: ${err.message}`);
11
+ }
12
+ const durationMs = Math.round(parseFloat(raw) * 1000);
13
+ if (isNaN(durationMs) || durationMs <= 0) {
14
+ throw new Error(`ffprobe returned invalid duration "${raw}" for ${videoPath}. The video file may be corrupt.`);
15
+ }
16
+ return durationMs;
17
+ }
18
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAChB,SAAS,EACT,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAChF,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC,IAAI,EAAE,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,qCAAqC,SAAS,IAAI;YAClD,8DAA8D;YAC9D,mBAAoB,GAAa,CAAC,OAAO,EAAE,CAC5C,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACb,sCAAsC,GAAG,SAAS,SAAS,kCAAkC,CAC9F,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -2,5 +2,13 @@ import type { ArgoConfig } from './config.js';
2
2
  export interface PipelineOptions {
3
3
  headed?: boolean;
4
4
  }
5
+ /**
6
+ * Discover all demo names in the demos directory by looking for `.scenes.json` files.
7
+ */
8
+ export declare function discoverDemos(demosDir: string): string[];
9
+ /**
10
+ * Run the pipeline for all demos in the demosDir.
11
+ */
12
+ export declare function runBatchPipeline(config: Pick<ArgoConfig, 'baseURL' | 'demosDir' | 'outputDir' | 'tts' | 'video' | 'export' | 'overlays'>, pipelineOpts?: PipelineOptions): Promise<string[]>;
5
13
  export declare function runPipeline(demoName: string, config: Pick<ArgoConfig, 'baseURL' | 'demosDir' | 'outputDir' | 'tts' | 'video' | 'export' | 'overlays'>, pipelineOpts?: PipelineOptions): Promise<string>;
6
14
  //# sourceMappingURL=pipeline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA0B9C,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC,EACxG,YAAY,CAAC,EAAE,eAAe,GAC7B,OAAO,CAAC,MAAM,CAAC,CAuNjB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CASxD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC,EACxG,YAAY,CAAC,EAAE,eAAe,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBnB;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC,EACxG,YAAY,CAAC,EAAE,eAAe,GAC7B,OAAO,CAAC,MAAM,CAAC,CA8MjB"}
package/dist/pipeline.js CHANGED
@@ -1,6 +1,5 @@
1
- import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
- import { execFileSync } from 'node:child_process';
3
- import { join } from 'node:path';
1
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
2
+ import { join, basename } from 'node:path';
4
3
  import { generateClips } from './tts/generate.js';
5
4
  import { record } from './record.js';
6
5
  import { alignClips } from './tts/align.js';
@@ -9,21 +8,49 @@ import { exportVideo, checkFfmpeg } from './export.js';
9
8
  import { generateSrt, generateVtt } from './subtitles.js';
10
9
  import { generateChapterMetadata } from './chapters.js';
11
10
  import { buildSceneReport, formatSceneReport } from './report.js';
12
- function getVideoDurationMs(videoPath) {
13
- let raw;
11
+ import { applySpeedRampToTimeline } from './speed-ramp.js';
12
+ import { getVideoDurationMs } from './media.js';
13
+ import { buildPlacementsFromTimingAndDurations, buildSceneTexts, computeHeadTrimMs, readScenesManifest, shiftPlacements, } from './timeline.js';
14
+ /**
15
+ * Discover all demo names in the demos directory by looking for `.scenes.json` files.
16
+ */
17
+ export function discoverDemos(demosDir) {
14
18
  try {
15
- raw = execFileSync('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', videoPath], { encoding: 'utf-8' }).trim();
19
+ return readdirSync(demosDir)
20
+ .filter((f) => f.endsWith('.scenes.json'))
21
+ .map((f) => basename(f).replace(/\.scenes\.json$/, ''))
22
+ .sort();
16
23
  }
17
- catch (err) {
18
- throw new Error(`Failed to get video duration from ${videoPath}. ` +
19
- `Ensure ffprobe is installed (it usually comes with ffmpeg). ` +
20
- `Original error: ${err.message}`);
24
+ catch {
25
+ return [];
21
26
  }
22
- const durationMs = Math.round(parseFloat(raw) * 1000);
23
- if (isNaN(durationMs) || durationMs <= 0) {
24
- throw new Error(`ffprobe returned invalid duration "${raw}" for ${videoPath}. The video file may be corrupt.`);
27
+ }
28
+ /**
29
+ * Run the pipeline for all demos in the demosDir.
30
+ */
31
+ export async function runBatchPipeline(config, pipelineOpts) {
32
+ const demos = discoverDemos(config.demosDir);
33
+ if (demos.length === 0) {
34
+ throw new Error(`No demos found in ${config.demosDir}/ (no .scenes.json files)`);
25
35
  }
26
- return durationMs;
36
+ console.log(`Found ${demos.length} demo(s): ${demos.join(', ')}\n`);
37
+ const results = [];
38
+ for (const demo of demos) {
39
+ console.log(`\n${'═'.repeat(60)}`);
40
+ console.log(` Pipeline: ${demo}`);
41
+ console.log(`${'═'.repeat(60)}\n`);
42
+ try {
43
+ const output = await runPipeline(demo, config, pipelineOpts);
44
+ results.push(output);
45
+ }
46
+ catch (err) {
47
+ console.error(`\n✗ Pipeline failed for ${demo}: ${err.message}`);
48
+ }
49
+ }
50
+ console.log(`\n${'═'.repeat(60)}`);
51
+ console.log(` Batch complete: ${results.length}/${demos.length} succeeded`);
52
+ console.log(`${'═'.repeat(60)}\n`);
53
+ return results;
27
54
  }
28
55
  export async function runPipeline(demoName, config, pipelineOpts) {
29
56
  if (!config.baseURL) {
@@ -34,6 +61,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
34
61
  }
35
62
  checkFfmpeg();
36
63
  const argoDir = join('.argo', demoName);
64
+ mkdirSync(argoDir, { recursive: true });
37
65
  // Step 1: Generate TTS clips
38
66
  console.log('★ Brewing voiceover clips...');
39
67
  const clipResults = await generateClips({
@@ -59,6 +87,9 @@ export async function runPipeline(demoName, config, pipelineOpts) {
59
87
  video: { width: config.video.width, height: config.video.height },
60
88
  browser: config.video.browser,
61
89
  deviceScaleFactor: config.video.deviceScaleFactor,
90
+ isMobile: config.video.isMobile,
91
+ hasTouch: config.video.hasTouch,
92
+ contextOptions: config.video.contextOptions,
62
93
  autoBackground: config.overlays.autoBackground,
63
94
  defaultPlacement: config.overlays.defaultPlacement,
64
95
  headed: pipelineOpts?.headed,
@@ -80,14 +111,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
80
111
  let shiftedPlacements = [];
81
112
  let shiftedDurationMs = totalDurationMs;
82
113
  // Auto-trim: skip setup before first scene mark (with 200ms lead-in)
83
- const markTimes = Object.values(timing);
84
- let headTrimMs = 0;
85
- if (markTimes.length > 0) {
86
- const firstMarkMs = Math.min(...markTimes);
87
- headTrimMs = Math.max(0, firstMarkMs - 200);
88
- if (headTrimMs <= 500)
89
- headTrimMs = 0;
90
- }
114
+ const headTrimMs = computeHeadTrimMs(timing);
91
115
  if (!isSilent) {
92
116
  console.log('★ Mixing the soundtrack...');
93
117
  // Load WAV clips into memory
@@ -110,46 +134,27 @@ export async function runPipeline(demoName, config, pipelineOpts) {
110
134
  console.warn(`Aligned narration runs ${aligned.overflowMs}ms past the recording. ` +
111
135
  `Padding the final video frame to preserve the full audio.`);
112
136
  }
113
- // Merge voiced placements with silent scenes (scenes that have timing marks but no TTS clips)
114
- const voicedScenes = new Set(aligned.placements.map(p => p.scene));
115
- const sortedMarks = Object.entries(timing).sort((a, b) => a[1] - b[1]);
116
- const silentPlacements = sortedMarks
117
- .filter(([scene]) => !voicedScenes.has(scene))
118
- .map(([scene, startMs], _i, arr) => {
119
- const idx = sortedMarks.findIndex(([s]) => s === scene);
120
- const endMs = idx + 1 < sortedMarks.length ? sortedMarks[idx + 1][1] : totalDurationMs;
121
- return { scene, startMs, endMs };
122
- });
123
- const allPlacements = [...aligned.placements, ...silentPlacements].sort((a, b) => a.startMs - b.startMs);
124
- shiftedPlacements = headTrimMs > 0
125
- ? allPlacements.map(p => ({ ...p, startMs: p.startMs - headTrimMs, endMs: p.endMs - headTrimMs }))
126
- : allPlacements;
137
+ const allPlacements = buildPlacementsFromTimingAndDurations(timing, sceneDurations, totalDurationMs);
138
+ shiftedPlacements = shiftPlacements(allPlacements, headTrimMs);
127
139
  shiftedDurationMs = Math.max(totalDurationMs, aligned.requiredDurationMs) - headTrimMs;
128
140
  }
129
141
  else {
130
142
  console.log('★ Silent mode — no voiceover clips');
131
143
  shiftedDurationMs = totalDurationMs - headTrimMs;
132
- // Build placements from timing marks for chapters (each scene runs until the next mark)
133
- const sortedMarks = Object.entries(timing).sort((a, b) => a[1] - b[1]);
134
- shiftedPlacements = sortedMarks.map(([scene, startMs], i) => {
135
- const endMs = i + 1 < sortedMarks.length ? sortedMarks[i + 1][1] : totalDurationMs;
136
- return { scene, startMs: startMs - headTrimMs, endMs: endMs - headTrimMs };
137
- });
144
+ shiftedPlacements = shiftPlacements(buildPlacementsFromTimingAndDurations(timing, sceneDurations, totalDurationMs), headTrimMs);
138
145
  }
146
+ const speedRampPlan = applySpeedRampToTimeline(shiftedPlacements, shiftedDurationMs, config.export.speedRamp);
147
+ const finalPlacements = speedRampPlan.placements;
148
+ const finalDurationMs = speedRampPlan.totalDurationMs;
139
149
  // Ensure output directory exists before writing subtitles
140
150
  mkdirSync(config.outputDir, { recursive: true });
141
151
  // Build scene text map for subtitles
142
152
  const manifestPath = `${config.demosDir}/${demoName}.scenes.json`;
143
- const sceneTexts = {};
144
153
  try {
145
- const manifestContent = JSON.parse(readFileSync(manifestPath, 'utf-8'));
146
- for (const entry of manifestContent) {
147
- if (entry.scene && entry.text)
148
- sceneTexts[entry.scene] = entry.text;
149
- }
150
- // Generate subtitles (shifted if head-trimming)
151
- const srt = generateSrt(shiftedPlacements, sceneTexts);
152
- const vtt = generateVtt(shiftedPlacements, sceneTexts);
154
+ const sceneTexts = buildSceneTexts(readScenesManifest(manifestPath));
155
+ // Generate subtitles on the final export timeline.
156
+ const srt = generateSrt(finalPlacements, sceneTexts);
157
+ const vtt = generateVtt(finalPlacements, sceneTexts);
153
158
  writeFileSync(join(config.outputDir, `${demoName}.srt`), srt, 'utf-8');
154
159
  writeFileSync(join(config.outputDir, `${demoName}.vtt`), vtt, 'utf-8');
155
160
  }
@@ -158,7 +163,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
158
163
  }
159
164
  // Generate chapter metadata for ffmpeg
160
165
  const chapterMetadataPath = join(argoDir, 'chapters.txt');
161
- const chapterMetadata = generateChapterMetadata(shiftedPlacements, shiftedDurationMs);
166
+ const chapterMetadata = generateChapterMetadata(finalPlacements, finalDurationMs);
162
167
  writeFileSync(chapterMetadataPath, chapterMetadata, 'utf-8');
163
168
  // Step 4: Export final video
164
169
  console.log('★ Cutting the final take...');
@@ -175,6 +180,10 @@ export async function runPipeline(demoName, config, pipelineOpts) {
175
180
  thumbnailPath: config.export.thumbnailPath,
176
181
  chapterMetadataPath,
177
182
  formats: config.export.formats,
183
+ transition: config.export.transition,
184
+ placements: finalPlacements,
185
+ totalDurationMs: finalDurationMs,
186
+ speedRampSegments: speedRampPlan.segments,
178
187
  };
179
188
  if (tailPadMs !== undefined)
180
189
  exportOptions.tailPadMs = tailPadMs;
@@ -182,7 +191,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
182
191
  exportOptions.headTrimMs = headTrimMs;
183
192
  const outputPath = await exportVideo(exportOptions);
184
193
  // Scene report
185
- const report = buildSceneReport(demoName, shiftedPlacements, overflowMs, shiftedDurationMs, outputPath);
194
+ const report = buildSceneReport(demoName, finalPlacements, overflowMs, finalDurationMs, outputPath);
186
195
  writeFileSync(join(argoDir, 'scene-report.json'), JSON.stringify(report, null, 2), 'utf-8');
187
196
  console.log(formatSceneReport(report));
188
197
  // Pipeline metadata — provenance tracking for voices, settings, resolution