@argo-video/cli 0.22.0 → 0.23.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/dist/media.js CHANGED
@@ -1,4 +1,4 @@
1
- import { execFileSync } from 'node:child_process';
1
+ import { execFileSync, spawnSync } from 'node:child_process';
2
2
  export function getVideoDurationMs(videoPath) {
3
3
  let raw;
4
4
  try {
@@ -35,4 +35,93 @@ export function getVideoFrameRate(videoPath) {
35
35
  }
36
36
  return fps;
37
37
  }
38
+ /**
39
+ * Compute average luminance of a single video frame at the given timestamp.
40
+ * Returns a value 0–255 or null on failure.
41
+ */
42
+ function frameLuminance(videoPath, timestampMs) {
43
+ try {
44
+ const ss = (timestampMs / 1000).toFixed(3);
45
+ const result = spawnSync('ffmpeg', [
46
+ '-ss', ss,
47
+ '-i', videoPath,
48
+ '-frames:v', '1',
49
+ '-vf', 'scale=64:36',
50
+ '-f', 'rawvideo',
51
+ '-pix_fmt', 'rgb24',
52
+ 'pipe:1',
53
+ ], { stdio: ['pipe', 'pipe', 'pipe'], maxBuffer: 64 * 36 * 3 + 1024 });
54
+ // ffmpeg may return non-zero even when stdout has valid frame data (e.g., codec warnings)
55
+ if (!result.stdout || result.stdout.length < 3) {
56
+ return null;
57
+ }
58
+ const pixels = result.stdout;
59
+ let totalLuminance = 0;
60
+ const pixelCount = Math.floor(pixels.length / 3);
61
+ for (let i = 0; i < pixelCount; i++) {
62
+ const r = pixels[i * 3];
63
+ const g = pixels[i * 3 + 1];
64
+ const b = pixels[i * 3 + 2];
65
+ totalLuminance += 0.299 * r + 0.587 * g + 0.114 * b;
66
+ }
67
+ return totalLuminance / pixelCount;
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ /**
74
+ * Detect whether a video region is predominantly dark or light.
75
+ * Samples multiple frames across the given time range for robustness
76
+ * (a single frame might be a transition or black screen).
77
+ *
78
+ * Returns the *overlay* theme for contrast: dark video → 'light' overlay,
79
+ * light video → 'dark' overlay. Falls back to 'dark' on error.
80
+ */
81
+ export function detectVideoTheme(videoPath, startMs = 0, endMs) {
82
+ // Sample up to 5 frames spread across the range; if no endMs, sample around startMs
83
+ const sampleCount = 5;
84
+ const timestamps = [];
85
+ if (endMs !== undefined && endMs > startMs) {
86
+ const step = (endMs - startMs) / (sampleCount + 1);
87
+ for (let i = 1; i <= sampleCount; i++) {
88
+ timestamps.push(Math.round(startMs + step * i));
89
+ }
90
+ }
91
+ else {
92
+ // Single point — sample at start plus small offsets
93
+ timestamps.push(startMs);
94
+ if (startMs > 500)
95
+ timestamps.push(startMs - 500);
96
+ timestamps.push(startMs + 500);
97
+ }
98
+ const luminances = [];
99
+ for (const ts of timestamps) {
100
+ const lum = frameLuminance(videoPath, Math.max(0, ts));
101
+ if (lum !== null)
102
+ luminances.push(lum);
103
+ }
104
+ if (luminances.length === 0)
105
+ return 'dark';
106
+ const avgLuminance = luminances.reduce((a, b) => a + b, 0) / luminances.length;
107
+ return avgLuminance < 128 ? 'light' : 'dark';
108
+ }
109
+ /**
110
+ * Probe video dimensions (width × height) using ffprobe.
111
+ * Returns { width, height } or null on failure.
112
+ */
113
+ export function getVideoDimensions(videoPath) {
114
+ try {
115
+ const raw = execFileSync('ffprobe', ['-v', 'error', '-select_streams', 'v:0',
116
+ '-show_entries', 'stream=width,height',
117
+ '-of', 'csv=p=0:s=x', videoPath], { encoding: 'utf-8' }).trim();
118
+ const match = raw.match(/^(\d+)x(\d+)$/);
119
+ if (!match)
120
+ return null;
121
+ return { width: Number(match[1]), height: Number(match[2]) };
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
38
127
  //# sourceMappingURL=media.js.map
package/dist/media.js.map CHANGED
@@ -1 +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;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAChB,SAAS,EACT,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAChH,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC,IAAI,EAAE,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,uCAAuC,SAAS,IAAI;YACpD,8DAA8D;YAC9D,mBAAoB,GAAa,CAAC,OAAO,EAAE,CAC5C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,SAAS,SAAS,GAAG,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,SAAS,SAAS,GAAG,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Render overlay cues to transparent PNGs using Playwright.
3
+ *
4
+ * For imported videos (no Playwright recording step), overlays defined in
5
+ * .scenes.json are never burned into the video. This module renders each
6
+ * overlay as a transparent PNG at the video's resolution so they can be
7
+ * composited via ffmpeg's overlay filter with `enable` timeline.
8
+ */
9
+ import type { OverlayCue, Zone } from './types.js';
10
+ import type { BackgroundTheme } from './zones.js';
11
+ import type { Placement } from '../tts/align.js';
12
+ export interface OverlayPngInput {
13
+ scene: string;
14
+ overlay: OverlayCue;
15
+ startMs: number;
16
+ endMs: number;
17
+ }
18
+ export interface RenderedOverlayPng {
19
+ scene: string;
20
+ pngPath: string;
21
+ zone: Zone;
22
+ startMs: number;
23
+ endMs: number;
24
+ }
25
+ /**
26
+ * Render overlay cues to transparent PNGs.
27
+ *
28
+ * Launches a headless Chromium browser, renders each overlay as a
29
+ * full-page screenshot with transparent background, and saves them
30
+ * to `outputDir`. PNGs are content-addressed cached — only regenerated
31
+ * when the overlay definition or video dimensions change.
32
+ *
33
+ * @param overlays - Array of overlay cues with timing information
34
+ * @param outputDir - Directory to save PNGs (e.g. `.argo/<demo>/overlay-pngs/`)
35
+ * @param videoWidth - Width of the target video in pixels
36
+ * @param videoHeight - Height of the target video in pixels
37
+ * @param theme - Background theme for overlay styling, or per-overlay map keyed by scene name
38
+ * @returns Array of rendered overlay PNGs with timing and position info
39
+ */
40
+ export declare function renderOverlaysToPng(overlays: OverlayPngInput[], outputDir: string, videoWidth: number, videoHeight: number, theme?: BackgroundTheme | Record<string, BackgroundTheme>): Promise<RenderedOverlayPng[]>;
41
+ /**
42
+ * Build ffmpeg filter_complex fragments to composite overlay PNGs onto a video.
43
+ *
44
+ * Each PNG is added as an input with `-loop 1` and overlaid using the
45
+ * `enable='between(t,start,end)'` timeline filter.
46
+ *
47
+ * @param pngs - Rendered overlay PNGs with timing
48
+ * @param baseInputCount - Number of ffmpeg inputs before overlay PNGs
49
+ * @returns Object with additional ffmpeg args, filter parts, and updated input count
50
+ */
51
+ export declare function buildOverlayPngFilters(pngs: RenderedOverlayPng[], baseInputCount: number, videoSourceLabel: string): {
52
+ inputArgs: string[];
53
+ filterParts: string[];
54
+ videoSource: string;
55
+ nextInput: number;
56
+ };
57
+ /**
58
+ * Check if a demo is an imported video (has `.imported` marker).
59
+ * For variants (e.g. `demo-mobile`), also checks the base demo name.
60
+ */
61
+ export declare function isImportedVideo(argoDir: string, demoName: string): boolean;
62
+ /**
63
+ * Build overlay PNGs for an imported video if overlays are defined.
64
+ *
65
+ * Shared across all export paths (CLI, pipeline, preview) to ensure parity.
66
+ * Detects adaptive theme per-overlay from the video frame at each overlay's
67
+ * time range — a dark section gets light overlays and vice versa.
68
+ *
69
+ * @returns Rendered overlay PNGs or undefined if not applicable
70
+ */
71
+ export declare function buildOverlayPngsForImport(options: {
72
+ argoDir: string;
73
+ demoName: string;
74
+ manifestPath: string;
75
+ placements: Placement[];
76
+ videoWidth: number;
77
+ videoHeight: number;
78
+ deviceScaleFactor?: number;
79
+ }): Promise<RenderedOverlayPng[] | undefined>;
80
+ //# sourceMappingURL=render-to-png.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-to-png.d.ts","sourceRoot":"","sources":["../../src/overlays/render-to-png.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAoFD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAU,GAChE,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAqE/B;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,MAAM,GACvB;IACD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CA+BA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAS1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,kBAAkB,EAAE,GAAG,SAAS,CAAC,CAuD5C"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Render overlay cues to transparent PNGs using Playwright.
3
+ *
4
+ * For imported videos (no Playwright recording step), overlays defined in
5
+ * .scenes.json are never burned into the video. This module renders each
6
+ * overlay as a transparent PNG at the video's resolution so they can be
7
+ * composited via ffmpeg's overlay filter with `enable` timeline.
8
+ */
9
+ import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { createHash } from 'node:crypto';
12
+ import { renderTemplate } from './templates.js';
13
+ /**
14
+ * CSS positioning rules that match the live preview / recording zones.
15
+ * Uses fixed positioning within a viewport-sized container.
16
+ */
17
+ const ZONE_CSS = {
18
+ 'bottom-center': 'position:fixed;bottom:60px;left:50%;transform:translateX(-50%);',
19
+ 'top-left': 'position:fixed;top:40px;left:40px;',
20
+ 'top-right': 'position:fixed;top:40px;right:40px;',
21
+ 'bottom-left': 'position:fixed;bottom:60px;left:40px;',
22
+ 'bottom-right': 'position:fixed;bottom:60px;right:40px;',
23
+ 'center': 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);',
24
+ };
25
+ /**
26
+ * Map zone positions to ffmpeg overlay x/y expressions.
27
+ * W, H = base video dimensions; w, h = overlay dimensions.
28
+ */
29
+ const ZONE_FFMPEG_POS = {
30
+ 'top-left': 'x=40:y=40',
31
+ 'top-right': 'x=W-w-40:y=40',
32
+ 'bottom-left': 'x=40:y=H-h-60',
33
+ 'bottom-right': 'x=W-w-40:y=H-h-60',
34
+ 'bottom-center': 'x=(W-w)/2:y=H-h-60',
35
+ 'center': 'x=(W-w)/2:y=(H-h)/2',
36
+ };
37
+ /**
38
+ * Build a full-page HTML document that renders a single overlay at the
39
+ * correct zone position on a transparent background.
40
+ */
41
+ function buildOverlayHtml(templateResult, zone, width, height) {
42
+ const styleEntries = Object.entries(templateResult.styles)
43
+ .map(([k, v]) => {
44
+ // Convert camelCase to kebab-case for CSS
45
+ const prop = k.replace(/([A-Z])/g, '-$1').toLowerCase();
46
+ return `${prop}: ${v};`;
47
+ })
48
+ .join(' ');
49
+ const zoneCss = ZONE_CSS[zone];
50
+ return `<!DOCTYPE html>
51
+ <html>
52
+ <head>
53
+ <meta charset="utf-8">
54
+ <style>
55
+ * { margin: 0; padding: 0; box-sizing: border-box; }
56
+ html, body {
57
+ width: ${width}px;
58
+ height: ${height}px;
59
+ overflow: hidden;
60
+ background: transparent;
61
+ }
62
+ .overlay {
63
+ ${zoneCss}
64
+ z-index: 999999;
65
+ pointer-events: none;
66
+ font-family: system-ui, -apple-system, sans-serif;
67
+ ${styleEntries}
68
+ }
69
+ </style>
70
+ </head>
71
+ <body>
72
+ <div class="overlay">${templateResult.contentHtml}</div>
73
+ </body>
74
+ </html>`;
75
+ }
76
+ /**
77
+ * Compute a content hash for cache invalidation.
78
+ * Changes to the overlay cue or video dimensions invalidate the cache.
79
+ */
80
+ function computeHash(overlay, width, height, theme = 'dark') {
81
+ const data = JSON.stringify({ overlay, width, height, theme });
82
+ return createHash('sha256').update(data).digest('hex').slice(0, 16);
83
+ }
84
+ /**
85
+ * Render overlay cues to transparent PNGs.
86
+ *
87
+ * Launches a headless Chromium browser, renders each overlay as a
88
+ * full-page screenshot with transparent background, and saves them
89
+ * to `outputDir`. PNGs are content-addressed cached — only regenerated
90
+ * when the overlay definition or video dimensions change.
91
+ *
92
+ * @param overlays - Array of overlay cues with timing information
93
+ * @param outputDir - Directory to save PNGs (e.g. `.argo/<demo>/overlay-pngs/`)
94
+ * @param videoWidth - Width of the target video in pixels
95
+ * @param videoHeight - Height of the target video in pixels
96
+ * @param theme - Background theme for overlay styling, or per-overlay map keyed by scene name
97
+ * @returns Array of rendered overlay PNGs with timing and position info
98
+ */
99
+ export async function renderOverlaysToPng(overlays, outputDir, videoWidth, videoHeight, theme = 'dark') {
100
+ if (overlays.length === 0)
101
+ return [];
102
+ mkdirSync(outputDir, { recursive: true });
103
+ const resolveTheme = (scene) => typeof theme === 'string' ? theme : (theme[scene] ?? 'dark');
104
+ // Check which overlays need rendering (cache check)
105
+ const toRender = [];
106
+ const results = [];
107
+ const validPngPaths = new Set();
108
+ for (const input of overlays) {
109
+ const zone = input.overlay.placement ?? 'bottom-center';
110
+ const overlayTheme = resolveTheme(input.scene);
111
+ const hash = computeHash(input.overlay, videoWidth, videoHeight, overlayTheme);
112
+ const pngPath = join(outputDir, `${input.scene}-overlay-${hash}.png`);
113
+ validPngPaths.add(`${input.scene}-overlay-${hash}.png`);
114
+ if (existsSync(pngPath)) {
115
+ results.push({ scene: input.scene, pngPath, zone, startMs: input.startMs, endMs: input.endMs });
116
+ }
117
+ else {
118
+ toRender.push({ input, pngPath, hash, theme: overlayTheme });
119
+ results.push({ scene: input.scene, pngPath, zone, startMs: input.startMs, endMs: input.endMs });
120
+ }
121
+ }
122
+ // Clean up stale PNGs whose content hash no longer matches any current overlay
123
+ try {
124
+ for (const file of readdirSync(outputDir)) {
125
+ if (file.endsWith('.png') && !validPngPaths.has(file)) {
126
+ try {
127
+ unlinkSync(join(outputDir, file));
128
+ }
129
+ catch { /* ignore */ }
130
+ }
131
+ }
132
+ }
133
+ catch { /* dir may not exist yet */ }
134
+ if (toRender.length === 0)
135
+ return results;
136
+ // Lazy-load Playwright to avoid import cost when all PNGs are cached
137
+ const { chromium } = await import('playwright');
138
+ const browser = await chromium.launch({ headless: true });
139
+ try {
140
+ const context = await browser.newContext({
141
+ viewport: { width: videoWidth, height: videoHeight },
142
+ deviceScaleFactor: 1,
143
+ });
144
+ const page = await context.newPage();
145
+ for (const { input, pngPath, theme: overlayTheme } of toRender) {
146
+ const zone = input.overlay.placement ?? 'bottom-center';
147
+ const templateResult = renderTemplate(input.overlay, overlayTheme);
148
+ const html = buildOverlayHtml(templateResult, zone, videoWidth, videoHeight);
149
+ await page.setContent(html, { waitUntil: 'load' });
150
+ await page.screenshot({
151
+ path: pngPath,
152
+ omitBackground: true,
153
+ fullPage: false,
154
+ });
155
+ }
156
+ await context.close();
157
+ }
158
+ finally {
159
+ await browser.close();
160
+ }
161
+ return results;
162
+ }
163
+ /**
164
+ * Build ffmpeg filter_complex fragments to composite overlay PNGs onto a video.
165
+ *
166
+ * Each PNG is added as an input with `-loop 1` and overlaid using the
167
+ * `enable='between(t,start,end)'` timeline filter.
168
+ *
169
+ * @param pngs - Rendered overlay PNGs with timing
170
+ * @param baseInputCount - Number of ffmpeg inputs before overlay PNGs
171
+ * @returns Object with additional ffmpeg args, filter parts, and updated input count
172
+ */
173
+ export function buildOverlayPngFilters(pngs, baseInputCount, videoSourceLabel) {
174
+ if (pngs.length === 0) {
175
+ return { inputArgs: [], filterParts: [], videoSource: videoSourceLabel, nextInput: baseInputCount };
176
+ }
177
+ const inputArgs = [];
178
+ const filterParts = [];
179
+ let currentVideo = videoSourceLabel;
180
+ let nextInput = baseInputCount;
181
+ for (let i = 0; i < pngs.length; i++) {
182
+ const png = pngs[i];
183
+ const pngInputIdx = nextInput++;
184
+ // Add PNG as looped input with explicit duration to prevent ffmpeg hanging.
185
+ // Without -t, -loop 1 creates an infinite stream that never terminates.
186
+ const durSec = ((png.endMs + 1000) / 1000).toFixed(3);
187
+ inputArgs.push('-loop', '1', '-t', durSec, '-i', png.pngPath);
188
+ const startSec = (png.startMs / 1000).toFixed(3);
189
+ const endSec = (png.endMs / 1000).toFixed(3);
190
+ const posExpr = ZONE_FFMPEG_POS[png.zone];
191
+ const outputLabel = `ovlpng${i}`;
192
+ filterParts.push(`[${currentVideo}][${pngInputIdx}:v]overlay=${posExpr}:enable='between(t\\,${startSec}\\,${endSec})':format=auto:eof_action=pass[${outputLabel}]`);
193
+ currentVideo = outputLabel;
194
+ }
195
+ return { inputArgs, filterParts, videoSource: currentVideo, nextInput };
196
+ }
197
+ /**
198
+ * Check if a demo is an imported video (has `.imported` marker).
199
+ * For variants (e.g. `demo-mobile`), also checks the base demo name.
200
+ */
201
+ export function isImportedVideo(argoDir, demoName) {
202
+ if (existsSync(join(argoDir, demoName, '.imported')))
203
+ return true;
204
+ // Variant subdirs like `demo-mobile` — check the base demo
205
+ const dashIdx = demoName.lastIndexOf('-');
206
+ if (dashIdx > 0) {
207
+ const baseName = demoName.slice(0, dashIdx);
208
+ if (existsSync(join(argoDir, baseName, '.imported')))
209
+ return true;
210
+ }
211
+ return false;
212
+ }
213
+ /**
214
+ * Build overlay PNGs for an imported video if overlays are defined.
215
+ *
216
+ * Shared across all export paths (CLI, pipeline, preview) to ensure parity.
217
+ * Detects adaptive theme per-overlay from the video frame at each overlay's
218
+ * time range — a dark section gets light overlays and vice versa.
219
+ *
220
+ * @returns Rendered overlay PNGs or undefined if not applicable
221
+ */
222
+ export async function buildOverlayPngsForImport(options) {
223
+ const { argoDir, demoName, manifestPath, placements, videoWidth, videoHeight, deviceScaleFactor = 1 } = options;
224
+ if (!isImportedVideo(argoDir, demoName))
225
+ return undefined;
226
+ if (placements.length === 0)
227
+ return undefined;
228
+ let scenes;
229
+ try {
230
+ scenes = JSON.parse(readFileSync(manifestPath, 'utf-8'));
231
+ }
232
+ catch {
233
+ return undefined;
234
+ }
235
+ const hasOverlays = scenes.some((s) => s.overlay);
236
+ if (!hasOverlays)
237
+ return undefined;
238
+ const overlayInputs = [];
239
+ for (const entry of scenes) {
240
+ if (!entry.overlay || !entry.scene)
241
+ continue;
242
+ const placement = placements.find((p) => p.scene === entry.scene);
243
+ if (!placement)
244
+ continue;
245
+ overlayInputs.push({
246
+ scene: entry.scene,
247
+ overlay: entry.overlay,
248
+ startMs: placement.startMs,
249
+ endMs: placement.endMs,
250
+ });
251
+ }
252
+ if (overlayInputs.length === 0)
253
+ return undefined;
254
+ // Detect theme per-overlay from the video at each overlay's time range
255
+ // Try the original-extension video first (imported videos), fall back to .webm
256
+ const { detectVideoTheme } = await import('../media.js');
257
+ const demoDir = join(argoDir, demoName);
258
+ const videoExts = ['.mp4', '.mov', '.mkv', '.avi', '.webm'];
259
+ let videoPath = join(demoDir, 'video.webm');
260
+ for (const ext of videoExts) {
261
+ const candidate = join(demoDir, `video${ext}`);
262
+ if (existsSync(candidate)) {
263
+ videoPath = candidate;
264
+ break;
265
+ }
266
+ }
267
+ const themeMap = {};
268
+ for (const input of overlayInputs) {
269
+ themeMap[input.scene] = detectVideoTheme(videoPath, input.startMs, input.endMs);
270
+ }
271
+ const uniqueThemes = [...new Set(Object.values(themeMap))];
272
+ const themeLabel = uniqueThemes.length === 1 ? uniqueThemes[0] : `mixed (${uniqueThemes.join('/')})`;
273
+ const pngDir = join(argoDir, demoName, 'overlay-pngs');
274
+ const renderW = videoWidth * deviceScaleFactor;
275
+ const renderH = videoHeight * deviceScaleFactor;
276
+ const pngs = await renderOverlaysToPng(overlayInputs, pngDir, renderW, renderH, themeMap);
277
+ console.log(` Rendered ${pngs.length} overlay PNG(s) for compositing (theme: ${themeLabel})`);
278
+ return pngs;
279
+ }
280
+ //# sourceMappingURL=render-to-png.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-to-png.js","sourceRoot":"","sources":["../../src/overlays/render-to-png.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["../../src/overlays/zones.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAuB9C;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,CAwC5F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE"}
1
+ {"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["../../src/overlays/zones.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAuB9C;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,CA2E5F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE"}
@@ -99,7 +99,42 @@ export async function detectBackgroundTheme(page, zone) {
99
99
  }
100
100
  }
101
101
  }
102
- // Fall back to system theme
102
+ // Fall back: resolve CSS custom properties used for backgrounds.
103
+ // getComputedStyle(body).backgroundColor returns transparent when
104
+ // the background is set via CSS variables (e.g., background: var(--bg)).
105
+ // We resolve the variable value and parse the hex/rgb color.
106
+ const rootStyle = getComputedStyle(document.documentElement);
107
+ const bgVarNames = ['--bg', '--background', '--bg-color', '--background-color'];
108
+ for (const varName of bgVarNames) {
109
+ const varVal = rootStyle.getPropertyValue(varName).trim();
110
+ if (!varVal)
111
+ continue;
112
+ // Try hex color
113
+ const hexMatch = varVal.match(/^#([0-9a-f]{3,8})$/i);
114
+ if (hexMatch) {
115
+ let hex = hexMatch[1];
116
+ if (hex.length === 3)
117
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
118
+ const r = parseInt(hex.slice(0, 2), 16);
119
+ const g = parseInt(hex.slice(2, 4), 16);
120
+ const b = parseInt(hex.slice(4, 6), 16);
121
+ const lum = 0.299 * r + 0.587 * g + 0.114 * b;
122
+ return lum < 128 ? 'light' : 'dark';
123
+ }
124
+ // Try rgb/rgba
125
+ const rgbMatch = varVal.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
126
+ if (rgbMatch) {
127
+ const lum = 0.299 * Number(rgbMatch[1]) + 0.587 * Number(rgbMatch[2]) + 0.114 * Number(rgbMatch[3]);
128
+ return lum < 128 ? 'light' : 'dark';
129
+ }
130
+ }
131
+ // Check if html/body has a class indicating dark mode
132
+ const htmlClasses = document.documentElement.className;
133
+ const bodyClasses = document.body.className;
134
+ if (/\bdark\b/i.test(htmlClasses) || /\bdark\b/i.test(bodyClasses)) {
135
+ return 'light';
136
+ }
137
+ // Last resort: system theme
103
138
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
104
139
  return prefersDark ? 'light' : 'dark';
105
140
  }, pos);
@@ -1 +1 @@
1
- {"version":3,"file":"zones.js","sourceRoot":"","sources":["../../src/overlays/zones.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zones.js","sourceRoot":"","sources":["../../src/overlays/zones.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAY9C,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,CAiZjB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAa9C,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,CAyajB"}
package/dist/pipeline.js CHANGED
@@ -12,6 +12,7 @@ import { applySpeedRampToTimeline } from './speed-ramp.js';
12
12
  import { shiftCameraMoves, scaleCameraMoves } from './camera-move.js';
13
13
  import { resolveFreezes, adjustPlacementsForFreezes, totalFreezeDurationMs, } from './freeze.js';
14
14
  import { getVideoDurationMs } from './media.js';
15
+ import { buildOverlayPngsForImport } from './overlays/render-to-png.js';
15
16
  // Note: MusicGen (AI music generation) is a preview-only feature — runs in browser via WebGPU.
16
17
  // Pipeline uses saved WAV files via audio.music config path.
17
18
  import { buildPlacementsFromTimingAndDurations, buildSceneTexts, computeHeadTrimMs, readScenesManifest, shiftPlacements, } from './timeline.js';
@@ -209,6 +210,16 @@ export async function runPipeline(demoName, config, pipelineOpts) {
209
210
  const chapterMetadataPath = join(argoDir, 'chapters.txt');
210
211
  const chapterMetadata = generateChapterMetadata(finalPlacements, finalDurationMs);
211
212
  writeFileSync(chapterMetadataPath, chapterMetadata, 'utf-8');
213
+ // Render overlay PNGs for imported videos (no Playwright recording step)
214
+ const overlayPngs = await buildOverlayPngsForImport({
215
+ argoDir: '.argo',
216
+ demoName,
217
+ manifestPath,
218
+ placements: finalPlacements,
219
+ videoWidth: config.video.width,
220
+ videoHeight: config.video.height,
221
+ deviceScaleFactor: config.video.deviceScaleFactor,
222
+ });
212
223
  // Step 4: Export final video
213
224
  console.log('🎞️ Cutting the final take...');
214
225
  const exportOptions = {
@@ -232,6 +243,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
232
243
  musicPath: config.export.audio?.music,
233
244
  musicVolume: config.export.audio?.musicVolume,
234
245
  watermark: config.export.watermark,
246
+ overlayPngs,
235
247
  };
236
248
  if (resolvedFreezes.length > 0) {
237
249
  exportOptions.freezeSpecs = resolvedFreezes;
@@ -382,6 +394,16 @@ export async function runPipeline(demoName, config, pipelineOpts) {
382
394
  variantCameraMoves = shiftCameraMoves(variantCameraMoves, variantHeadTrimMs);
383
395
  variantCameraMoves = scaleCameraMoves(variantCameraMoves, config.video.deviceScaleFactor ?? 1);
384
396
  }
397
+ // Render overlay PNGs for imported video variants
398
+ const variantOverlayPngs = await buildOverlayPngsForImport({
399
+ argoDir: '.argo',
400
+ demoName: variantSubdir,
401
+ manifestPath,
402
+ placements: variantPlacements,
403
+ videoWidth: variant.video.width,
404
+ videoHeight: variant.video.height,
405
+ deviceScaleFactor: config.video.deviceScaleFactor,
406
+ });
385
407
  const variantOutputPath = await exportVideo({
386
408
  demoName: variantSubdir,
387
409
  argoDir: '.argo',
@@ -402,6 +424,7 @@ export async function runPipeline(demoName, config, pipelineOpts) {
402
424
  cameraMoves: variantCameraMoves.length > 0 ? variantCameraMoves : undefined,
403
425
  watermark: config.export.watermark,
404
426
  freezeSpecs: variantResolvedFreezes.length > 0 ? variantResolvedFreezes : undefined,
427
+ overlayPngs: variantOverlayPngs,
405
428
  });
406
429
  console.log(`🚀 Variant saved to: ${variantOutputPath}`);
407
430
  }