@argo-video/cli 0.13.0 → 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 (48) hide show
  1. package/README.md +102 -2
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +105 -7
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +18 -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 +59 -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/speed-ramp.d.ts +39 -0
  37. package/dist/speed-ramp.d.ts.map +1 -0
  38. package/dist/speed-ramp.js +184 -0
  39. package/dist/speed-ramp.js.map +1 -0
  40. package/dist/timeline.d.ts +19 -0
  41. package/dist/timeline.d.ts.map +1 -0
  42. package/dist/timeline.js +82 -0
  43. package/dist/timeline.js.map +1 -0
  44. package/dist/transitions.d.ts +15 -0
  45. package/dist/transitions.d.ts.map +1 -0
  46. package/dist/transitions.js +124 -0
  47. package/dist/transitions.js.map +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,82 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { schedulePlacements } from './tts/align.js';
3
+ import { ClipCache } from './tts/cache.js';
4
+ import { parseWavHeader } from './tts/engine.js';
5
+ export function readScenesManifest(manifestPath) {
6
+ const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));
7
+ if (!Array.isArray(raw)) {
8
+ throw new Error(`Manifest ${manifestPath} must contain a JSON array`);
9
+ }
10
+ return raw.map((entry) => {
11
+ if (!entry || typeof entry !== 'object' || typeof entry.scene !== 'string') {
12
+ throw new Error(`Manifest ${manifestPath} contains an entry without a valid scene name`);
13
+ }
14
+ return entry;
15
+ });
16
+ }
17
+ export function buildSceneTexts(entries) {
18
+ const sceneTexts = {};
19
+ for (const entry of entries) {
20
+ if (typeof entry.text === 'string' && entry.text.trim().length > 0) {
21
+ sceneTexts[entry.scene] = entry.text;
22
+ }
23
+ }
24
+ return sceneTexts;
25
+ }
26
+ export function buildSceneDurationsFromCache(demoName, entries, defaults, projectRoot = '.') {
27
+ const cache = new ClipCache(projectRoot);
28
+ const sceneDurations = {};
29
+ for (const entry of entries) {
30
+ if (typeof entry.text !== 'string' || entry.text.trim().length === 0)
31
+ continue;
32
+ const cacheEntry = {
33
+ scene: entry.scene,
34
+ text: entry.text,
35
+ voice: entry.voice ?? defaults.voice,
36
+ speed: entry.speed ?? defaults.speed,
37
+ lang: entry.lang,
38
+ };
39
+ const clipPath = cache.getClipPath(demoName, cacheEntry);
40
+ if (!existsSync(clipPath))
41
+ continue;
42
+ const wavBuf = readFileSync(clipPath);
43
+ sceneDurations[entry.scene] = parseWavHeader(wavBuf).durationMs;
44
+ }
45
+ return sceneDurations;
46
+ }
47
+ export function computeHeadTrimMs(timing, leadInMs = 200, minTrimMs = 500) {
48
+ const markTimes = Object.values(timing);
49
+ if (markTimes.length === 0)
50
+ return 0;
51
+ const firstMarkMs = Math.min(...markTimes);
52
+ const headTrimMs = Math.max(0, firstMarkMs - leadInMs);
53
+ return headTrimMs <= minTrimMs ? 0 : headTrimMs;
54
+ }
55
+ export function buildPlacementsFromTimingAndDurations(timing, sceneDurations, totalDurationMs) {
56
+ const voicedPlacements = schedulePlacements(Object.entries(timing)
57
+ .filter(([scene]) => (sceneDurations[scene] ?? 0) > 0)
58
+ .map(([scene, startMs]) => ({
59
+ scene,
60
+ startMs,
61
+ durationMs: sceneDurations[scene],
62
+ })));
63
+ const voicedScenes = new Set(voicedPlacements.map((p) => p.scene));
64
+ const sortedMarks = Object.entries(timing).sort((a, b) => a[1] - b[1]);
65
+ const silentPlacements = sortedMarks.flatMap(([scene, startMs], index) => {
66
+ if (voicedScenes.has(scene))
67
+ return [];
68
+ const endMs = index + 1 < sortedMarks.length ? sortedMarks[index + 1][1] : totalDurationMs;
69
+ return [{ scene, startMs, endMs }];
70
+ });
71
+ return [...voicedPlacements, ...silentPlacements].sort((a, b) => a.startMs - b.startMs);
72
+ }
73
+ export function shiftPlacements(placements, offsetMs) {
74
+ if (offsetMs <= 0)
75
+ return placements;
76
+ return placements.map((placement) => ({
77
+ ...placement,
78
+ startMs: Math.max(0, placement.startMs - offsetMs),
79
+ endMs: Math.max(0, placement.endMs - offsetMs),
80
+ }));
81
+ }
82
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAoC,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,SAAS,EAAsB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAWjD,MAAM,UAAU,kBAAkB,CAAC,YAAoB;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,YAAY,YAAY,4BAA4B,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACvB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAA6B,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACpG,MAAM,IAAI,KAAK,CAAC,YAAY,YAAY,+CAA+C,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,KAA2B,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAA6B;IAC3D,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,QAAgB,EAChB,OAA6B,EAC7B,QAA4C,EAC5C,WAAW,GAAG,GAAG;IAEjB,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,cAAc,GAA2B,EAAE,CAAC;IAElD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAE/E,MAAM,UAAU,GAAkB;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;YACpC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC;QACF,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEpC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACtC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC;IAClE,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAmB,EACnB,QAAQ,GAAG,GAAG,EACd,SAAS,GAAG,GAAG;IAEf,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAErC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;IACvD,OAAO,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,MAAmB,EACnB,cAAsC,EACtC,eAAuB;IAEvB,MAAM,gBAAgB,GAAG,kBAAkB,CACzC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;SACrD,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,KAAK;QACL,OAAO;QACP,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC;KAClC,CAAC,CAAC,CACN,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE;QACvE,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QAC3F,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,gBAAgB,EAAE,GAAG,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAuB,EAAE,QAAgB;IACvE,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IACrC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACpC,GAAG,SAAS;QACZ,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,OAAO,GAAG,QAAQ,CAAC;QAClD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,GAAG,QAAQ,CAAC;KAC/C,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Placement } from './tts/align.js';
2
+ import type { TransitionConfig } from './config.js';
3
+ /**
4
+ * Generate ffmpeg transition filters for scene boundaries.
5
+ *
6
+ * Returns either:
7
+ * - Simple string[] for -vf (wipe transitions only)
8
+ * - A filterComplex object for filter_complex (fade/dissolve — uses split+trim+fade+concat)
9
+ */
10
+ export declare function buildTransitionFilters(placements: Placement[], transition: TransitionConfig, hasAudio?: boolean, fps?: number): string[] | {
11
+ filterComplex: string;
12
+ videoOutput: string;
13
+ audioOutput: string | null;
14
+ };
15
+ //# sourceMappingURL=transitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.d.ts","sourceRoot":"","sources":["../src/transitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA4HpD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,CAAC,EAAE,OAAO,EAClB,GAAG,GAAE,MAAW,GACf,MAAM,EAAE,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAkCvF"}
@@ -0,0 +1,124 @@
1
+ function buildDirectionalWipe(direction, boundarySec, halfDur) {
2
+ const coverStart = boundarySec - halfDur;
3
+ const revealEnd = boundarySec + halfDur;
4
+ const coverDur = halfDur.toFixed(3);
5
+ const revealDur = halfDur.toFixed(3);
6
+ if (direction === 'left') {
7
+ return [
8
+ `drawbox=x='iw-if(between(t\\,${coverStart.toFixed(3)}\\,${boundarySec.toFixed(3)})\\,(t-${coverStart.toFixed(3)})/${coverDur}*iw\\,0)':y=0:w='if(between(t\\,${coverStart.toFixed(3)}\\,${boundarySec.toFixed(3)})\\,(t-${coverStart.toFixed(3)})/${coverDur}*iw\\,0)':h=ih:color=black:t=fill`,
9
+ `drawbox=x=0:y=0:w='if(between(t\\,${boundarySec.toFixed(3)}\\,${revealEnd.toFixed(3)})\\,(1-(t-${boundarySec.toFixed(3)})/${revealDur})*iw\\,0)':h=ih:color=black:t=fill`,
10
+ ];
11
+ }
12
+ return [
13
+ `drawbox=x=0:y=0:w='if(between(t\\,${coverStart.toFixed(3)}\\,${boundarySec.toFixed(3)})\\,(t-${coverStart.toFixed(3)})/${coverDur}*iw\\,0)':h=ih:color=black:t=fill`,
14
+ `drawbox=x='iw-if(between(t\\,${boundarySec.toFixed(3)}\\,${revealEnd.toFixed(3)})\\,(1-(t-${boundarySec.toFixed(3)})/${revealDur})*iw\\,0)':y=0:w='if(between(t\\,${boundarySec.toFixed(3)}\\,${revealEnd.toFixed(3)})\\,(1-(t-${boundarySec.toFixed(3)})/${revealDur})*iw\\,0)':h=ih:color=black:t=fill`,
15
+ ];
16
+ }
17
+ /**
18
+ * Build a filter_complex string for fade transitions using split+trim+fade+concat.
19
+ *
20
+ * This is the only reliable way to apply multiple fade transitions in ffmpeg —
21
+ * the fade filter only supports one fade-out per stream instance, so we split
22
+ * the video at each scene boundary, apply fades independently, then concatenate.
23
+ *
24
+ * Both fade-through-black and dissolve use dip-to-black. The difference is
25
+ * duration: dissolve uses a quicker dip (60% of half-duration) for a subtler
26
+ * effect. A true crossfade/dissolve with overlapping blend would require
27
+ * ffmpeg's xfade filter which needs re-encoded segment pairs — not practical
28
+ * for continuous recordings.
29
+ */
30
+ function buildFadeFilterComplex(placements, halfDur, isDissolveDip, videoInputLabel, audioInputLabel, fps) {
31
+ // Build boundary times from placements (scene starts after the first)
32
+ const boundaries = [];
33
+ for (let i = 1; i < placements.length; i++) {
34
+ boundaries.push(placements[i].startMs / 1000);
35
+ }
36
+ // For dissolve, use shorter fade duration for a dip effect
37
+ const fadeDur = isDissolveDip ? halfDur * 0.6 : halfDur;
38
+ const numSegments = boundaries.length + 1;
39
+ const parts = [];
40
+ const frameSec = 1 / fps;
41
+ // Split video into N segments
42
+ parts.push(`${videoInputLabel}split=${numSegments}${Array.from({ length: numSegments }, (_, i) => `[vs${i}]`).join('')}`);
43
+ // Split audio if present
44
+ if (audioInputLabel) {
45
+ parts.push(`${audioInputLabel}asplit=${numSegments}${Array.from({ length: numSegments }, (_, i) => `[as${i}]`).join('')}`);
46
+ }
47
+ // Trim and fade each segment
48
+ const segLabels = [];
49
+ const aSegLabels = [];
50
+ for (let i = 0; i < numSegments; i++) {
51
+ const start = i === 0 ? 0 : boundaries[i - 1];
52
+ const end = i < boundaries.length ? boundaries[i] : '';
53
+ const trimEnd = end !== '' ? `:${end.toFixed(4)}` : '';
54
+ const label = `v${i}`;
55
+ let chain = `[vs${i}]trim=${start.toFixed(4)}${trimEnd},setpts=PTS-STARTPTS`;
56
+ // Fade out at end of segment (except last).
57
+ // End the fade one frame before the cut so the final visible frame of the
58
+ // outgoing segment is already black and cannot "peek" through at the join.
59
+ if (i < boundaries.length) {
60
+ const segDuration = end - start;
61
+ const fadeEnd = Math.max(0, segDuration - frameSec);
62
+ const effectiveFadeDur = Math.min(fadeDur, fadeEnd);
63
+ if (effectiveFadeDur > 0) {
64
+ const fadeStart = Math.max(0, fadeEnd - effectiveFadeDur);
65
+ chain += `,fade=t=out:st=${fadeStart.toFixed(4)}:d=${effectiveFadeDur.toFixed(4)}`;
66
+ }
67
+ }
68
+ // Fade in at start of segment (except first). The first visible frame of
69
+ // the incoming segment starts black, matching the outgoing black frame.
70
+ if (i > 0) {
71
+ chain += `,fade=t=in:st=0:d=${fadeDur.toFixed(4)}`;
72
+ }
73
+ chain += `[${label}]`;
74
+ parts.push(chain);
75
+ segLabels.push(`[${label}]`);
76
+ // Audio: trim to match video segment, no fading
77
+ if (audioInputLabel) {
78
+ const aLabel = `a${i}`;
79
+ parts.push(`[as${i}]atrim=${start.toFixed(4)}${trimEnd},asetpts=PTS-STARTPTS[${aLabel}]`);
80
+ aSegLabels.push(`[${aLabel}]`);
81
+ }
82
+ }
83
+ // Concat all segments
84
+ const totalConcatSegments = segLabels.length;
85
+ const videoOutput = 'vfaded';
86
+ if (audioInputLabel) {
87
+ const audioOutput = 'afaded';
88
+ const interleaved = segLabels.map((v, i) => `${v}${aSegLabels[i]}`).join('');
89
+ parts.push(`${interleaved}concat=n=${totalConcatSegments}:v=1:a=1[${videoOutput}][${audioOutput}]`);
90
+ return { filterComplex: parts.join(';\n'), videoOutput: `[${videoOutput}]`, audioOutput: `[${audioOutput}]` };
91
+ }
92
+ else {
93
+ parts.push(`${segLabels.join('')}concat=n=${totalConcatSegments}:v=1:a=0[${videoOutput}]`);
94
+ return { filterComplex: parts.join(';\n'), videoOutput: `[${videoOutput}]`, audioOutput: null };
95
+ }
96
+ }
97
+ /**
98
+ * Generate ffmpeg transition filters for scene boundaries.
99
+ *
100
+ * Returns either:
101
+ * - Simple string[] for -vf (wipe transitions only)
102
+ * - A filterComplex object for filter_complex (fade/dissolve — uses split+trim+fade+concat)
103
+ */
104
+ export function buildTransitionFilters(placements, transition, hasAudio, fps = 30) {
105
+ if (placements.length < 2)
106
+ return [];
107
+ const durMs = transition.durationMs ?? 500;
108
+ const durSec = durMs / 1000;
109
+ const halfDur = durSec / 2;
110
+ if (transition.type === 'wipe-left' || transition.type === 'wipe-right') {
111
+ const parts = [];
112
+ for (let i = 1; i < placements.length; i++) {
113
+ const boundarySec = placements[i].startMs / 1000;
114
+ parts.push(...buildDirectionalWipe(transition.type === 'wipe-left' ? 'left' : 'right', boundarySec, halfDur));
115
+ }
116
+ return parts;
117
+ }
118
+ // Fade-through-black and dissolve use filter_complex with split+trim+fade+concat.
119
+ // This is the only approach that reliably applies multiple fade transitions —
120
+ // ffmpeg's fade filter only supports one fade-out per stream instance.
121
+ const isDissolveDip = transition.type === 'dissolve';
122
+ return buildFadeFilterComplex(placements, halfDur, isDissolveDip, '[0:v]', hasAudio ? '[1:a]' : null, fps);
123
+ }
124
+ //# sourceMappingURL=transitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../src/transitions.ts"],"names":[],"mappings":"AAGA,SAAS,oBAAoB,CAC3B,SAA2B,EAC3B,WAAmB,EACnB,OAAe;IAEf,MAAM,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IACzC,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAErC,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO;YACL,gCAAgC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,mCAAmC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,mCAAmC;YAChS,qCAAqC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,oCAAoC;SAC3K,CAAC;IACJ,CAAC;IAED,OAAO;QACL,qCAAqC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,mCAAmC;QACrK,gCAAgC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,oCAAoC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,oCAAoC;KAC3S,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,sBAAsB,CAC7B,UAAuB,EACvB,OAAe,EACf,aAAsB,EACtB,eAAuB,EACvB,eAA8B,EAC9B,GAAW;IAEX,sEAAsE;IACtE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,2DAA2D;IAC3D,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;IAExD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC;IAEzB,8BAA8B;IAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,SAAS,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAE1H,yBAAyB;IACzB,IAAI,eAAe,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,UAAU,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7H,CAAC;IAED,6BAA6B;IAC7B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAK,GAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC;QAEtB,IAAI,KAAK,GAAG,MAAM,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,sBAAsB,CAAC;QAE7E,4CAA4C;QAC5C,0EAA0E;QAC1E,2EAA2E;QAC3E,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,WAAW,GAAI,GAAc,GAAG,KAAK,CAAC;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;YACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACpD,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC,CAAC;gBAC1D,KAAK,IAAI,kBAAkB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACrF,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,wEAAwE;QACxE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,KAAK,IAAI,qBAAqB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,CAAC;QAED,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QAE7B,gDAAgD;QAChD,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,yBAAyB,MAAM,GAAG,CAAC,CAAC;YAC1F,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,mBAAmB,GAAG,SAAS,CAAC,MAAM,CAAC;IAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC;IAC7B,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC7B,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,YAAY,mBAAmB,YAAY,WAAW,KAAK,WAAW,GAAG,CAAC,CAAC;QACpG,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,WAAW,GAAG,EAAE,WAAW,EAAE,IAAI,WAAW,GAAG,EAAE,CAAC;IAChH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,mBAAmB,YAAY,WAAW,GAAG,CAAC,CAAC;QAC3F,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,WAAW,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAClG,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAuB,EACvB,UAA4B,EAC5B,QAAkB,EAClB,MAAc,EAAE;IAEhB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,IAAI,GAAG,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAC5B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,CAAC;IAE3B,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW,IAAI,UAAU,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACxE,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;YACjD,KAAK,CAAC,IAAI,CACR,GAAG,oBAAoB,CACrB,UAAU,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAClD,WAAW,EACX,OAAO,CACR,CACF,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kFAAkF;IAClF,8EAA8E;IAC9E,uEAAuE;IACvE,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC;IACrD,OAAO,sBAAsB,CAC3B,UAAU,EACV,OAAO,EACP,aAAa,EACb,OAAO,EACP,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EACzB,GAAG,CACJ,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@argo-video/cli",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Turn Playwright demo scripts into polished product demo videos with AI voiceover",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",