hyperframes 0.7.26 → 0.7.27
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/cli.js +574 -227
- package/dist/hyperframes-slideshow.global.js +20 -20
- package/dist/studio/assets/{index-D3eh3pRK.js → index-C07SnkBi.js} +1 -1
- package/dist/studio/assets/{index-BPya4QRs.js → index-CoIF_vfx.js} +1 -1
- package/dist/studio/assets/{index-BZqvc9Ns.js → index-DueKwqDv.js} +3 -3
- package/dist/studio/index.html +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ var VERSION;
|
|
|
50
50
|
var init_version = __esm({
|
|
51
51
|
"src/version.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
VERSION = true ? "0.7.
|
|
53
|
+
VERSION = true ? "0.7.27" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -60925,7 +60925,7 @@ function formatHttpErrorDiagnostic(input2) {
|
|
|
60925
60925
|
return `[Browser:HTTP${input2.status}] ${input2.method} ${sanitizeDiagnosticUrl(input2.url)} resource=${input2.resourceType}${statusText}`;
|
|
60926
60926
|
}
|
|
60927
60927
|
async function driveWarmupTicks(options, state) {
|
|
60928
|
-
const
|
|
60928
|
+
const sleep5 = options.sleep ?? realSleep;
|
|
60929
60929
|
while (true) {
|
|
60930
60930
|
if (options.lockWarmupTicks) {
|
|
60931
60931
|
if (state.ticks >= LOCKED_WARMUP_TICKS) return;
|
|
@@ -60937,7 +60937,7 @@ async function driveWarmupTicks(options, state) {
|
|
|
60937
60937
|
state.ticks += 1;
|
|
60938
60938
|
} catch {
|
|
60939
60939
|
}
|
|
60940
|
-
await
|
|
60940
|
+
await sleep5(options.intervalMs);
|
|
60941
60941
|
}
|
|
60942
60942
|
}
|
|
60943
60943
|
function resolveCaptureSessionOptions(options, browserVersion, platform10 = process.platform) {
|
|
@@ -62729,7 +62729,7 @@ import { join as join6, dirname as dirname4, extname as extname2 } from "path";
|
|
|
62729
62729
|
function appendEncodeTimeoutMessage(error, timedOut, timeoutMs) {
|
|
62730
62730
|
if (!timedOut) return error;
|
|
62731
62731
|
return `${error}
|
|
62732
|
-
FFmpeg killed after exceeding ffmpegEncodeTimeout (${timeoutMs} ms)
|
|
62732
|
+
FFmpeg killed after exceeding ffmpegEncodeTimeout (${timeoutMs} ms). Long or high-frame-count renders may need more time: set FFMPEG_ENCODE_TIMEOUT_MS to a higher value (ms), or set PRODUCER_ENABLE_CHUNKED_ENCODE=true to encode in smaller chunks instead of one long-running ffmpeg process.`;
|
|
62733
62733
|
}
|
|
62734
62734
|
function isAacSidecar(audioPath) {
|
|
62735
62735
|
return extname2(audioPath).toLowerCase() === ".aac";
|
|
@@ -66304,8 +66304,15 @@ function findRootTag(source) {
|
|
|
66304
66304
|
const bodyEnd = bodyOpenMatch && bodyCloseMatch && bodyCloseMatch.index > bodyStart ? bodyCloseMatch.index : source.length;
|
|
66305
66305
|
const bodyContent = bodyOpenMatch ? source.slice(bodyStart, bodyEnd) : source;
|
|
66306
66306
|
const bodyTags = extractOpenTags(bodyContent);
|
|
66307
|
+
let skipBefore = -1;
|
|
66307
66308
|
for (const tag of bodyTags) {
|
|
66309
|
+
if (tag.index < skipBefore) continue;
|
|
66308
66310
|
if (["script", "style", "meta", "link", "title"].includes(tag.name)) continue;
|
|
66311
|
+
if (tag.name === "svg" && !readAttr(tag.raw, "data-composition-id") && !readAttr(tag.raw, "data-width") && !readAttr(tag.raw, "data-height")) {
|
|
66312
|
+
const closeMatch = /<\/svg\s*>/i.exec(bodyContent.slice(tag.index));
|
|
66313
|
+
skipBefore = closeMatch ? tag.index + closeMatch.index + closeMatch[0].length : Infinity;
|
|
66314
|
+
continue;
|
|
66315
|
+
}
|
|
66309
66316
|
return { ...tag, index: tag.index + bodyStart };
|
|
66310
66317
|
}
|
|
66311
66318
|
return null;
|
|
@@ -67974,7 +67981,7 @@ var init_dist4 = __esm({
|
|
|
67974
67981
|
TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
|
|
67975
67982
|
TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN = /window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
|
67976
67983
|
TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines(?:\[[^\]]+\]|\.[A-Za-z_$][\w$]*)\s*=/i;
|
|
67977
|
-
WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
|
67984
|
+
WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines(?:\[\s*(?:["']([^"']+)["']|[A-Za-z_$][\w$.]*)\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
|
67978
67985
|
INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
|
|
67979
67986
|
TIMELINE_REGISTRY_KEY_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=/g;
|
|
67980
67987
|
TIMELINE_REGISTRY_OBJECT_BODY_PATTERN = /window\.__timelines\s*=\s*\{([\s\S]*?)\}/i;
|
|
@@ -68708,12 +68715,14 @@ ${right.raw}`)
|
|
|
68708
68715
|
(candidate) => isHardKillSet(candidate, win.targetSelector, boundary)
|
|
68709
68716
|
);
|
|
68710
68717
|
if (hasHardKill) continue;
|
|
68718
|
+
const exitClipInfo = clipIds.get(win.targetSelector) || clipClasses.get(win.targetSelector);
|
|
68719
|
+
const fixHint = exitClipInfo ? `"${win.targetSelector}" is a clip element \u2014 the framework already manages its visibility. Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill (\`tl.set("<inner-selector>", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\`) onto that wrapper instead.` : `Add \`tl.set("${win.targetSelector}", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\` after the exit tween.`;
|
|
68711
68720
|
findings.push({
|
|
68712
68721
|
code: "gsap_exit_missing_hard_kill",
|
|
68713
68722
|
severity: "error",
|
|
68714
68723
|
message: `GSAP exit on "${win.targetSelector}" ends at the ${boundary.toFixed(2)}s clip start boundary without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.`,
|
|
68715
68724
|
selector: win.targetSelector,
|
|
68716
|
-
fixHint
|
|
68725
|
+
fixHint,
|
|
68717
68726
|
snippet: truncateSnippet(win.raw)
|
|
68718
68727
|
});
|
|
68719
68728
|
}
|
|
@@ -68983,12 +68992,15 @@ ${right.raw}`)
|
|
|
68983
68992
|
const killPattern = new RegExp(`["']#${id}["'][^)]*visibility\\s*:\\s*["']hidden["']`);
|
|
68984
68993
|
const hasKill = killPattern.test(content);
|
|
68985
68994
|
if (!hasKill) {
|
|
68995
|
+
const classes = (readAttr(tag.raw, "class") || "").split(/\s+/).filter(Boolean);
|
|
68996
|
+
const isClip = classes.includes("clip");
|
|
68997
|
+
const fixHint = isClip ? `"#${id}" is a clip element \u2014 the framework already manages its visibility. Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill (\`tl.set("<inner-selector>", { visibility: "hidden" }, <exit-end-time>)\`) onto that wrapper instead.` : `Add \`tl.set("#${id}", { visibility: "hidden" }, <exit-end-time>)\` after the scene's exit tweens.`;
|
|
68986
68998
|
findings.push({
|
|
68987
68999
|
code: "scene_layer_missing_visibility_kill",
|
|
68988
69000
|
severity: "error",
|
|
68989
69001
|
elementId: id,
|
|
68990
69002
|
message: `Scene layer "#${id}" exits via opacity tween but has no visibility: hidden hard kill. When scrubbing or when tweens conflict, the scene may remain partially visible and overlap the next scene.`,
|
|
68991
|
-
fixHint
|
|
69003
|
+
fixHint
|
|
68992
69004
|
});
|
|
68993
69005
|
}
|
|
68994
69006
|
}
|
|
@@ -70089,7 +70101,7 @@ ${allInlineStyles}`.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
|
70089
70101
|
code: "font_family_without_font_face",
|
|
70090
70102
|
severity: "error",
|
|
70091
70103
|
message: `Font ${undeclared.length === 1 ? "family" : "families"} used without @font-face declaration: ${undeclared.join(", ")}. These are not in the auto-resolved font list, so the renderer cannot supply them automatically. Text will fall back to a generic font, producing incorrect typography in the video.`,
|
|
70092
|
-
fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files."
|
|
70104
|
+
fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files. For an OS-bundled system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, use src: local('Exact Font Name') instead \u2014 the declaration alone satisfies this check without needing a font file."
|
|
70093
70105
|
});
|
|
70094
70106
|
return findings;
|
|
70095
70107
|
}
|
|
@@ -95031,10 +95043,11 @@ __export(manager_exports2, {
|
|
|
95031
95043
|
clearBrowser: () => clearBrowser,
|
|
95032
95044
|
ensureBrowser: () => ensureBrowser,
|
|
95033
95045
|
findBrowser: () => findBrowser,
|
|
95034
|
-
isLinuxArm: () => isLinuxArm
|
|
95046
|
+
isLinuxArm: () => isLinuxArm,
|
|
95047
|
+
withInstallLock: () => withInstallLock
|
|
95035
95048
|
});
|
|
95036
95049
|
import { execSync as execSync5, spawnSync as spawnSync2 } from "child_process";
|
|
95037
|
-
import { existsSync as existsSync31, readdirSync as readdirSync13, rmSync as rmSync6 } from "fs";
|
|
95050
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync15, readdirSync as readdirSync13, rmSync as rmSync6, statSync as statSync9 } from "fs";
|
|
95038
95051
|
import { basename as basename4 } from "path";
|
|
95039
95052
|
import { homedir as homedir9 } from "os";
|
|
95040
95053
|
import { join as join27 } from "path";
|
|
@@ -95049,6 +95062,59 @@ Fix: run \`npm install\` or \`bun install\` to restore missing packages, then re
|
|
|
95049
95062
|
);
|
|
95050
95063
|
}
|
|
95051
95064
|
}
|
|
95065
|
+
function isErrno(err, code) {
|
|
95066
|
+
return err.code === code;
|
|
95067
|
+
}
|
|
95068
|
+
function sleep(ms) {
|
|
95069
|
+
return new Promise((resolve62) => setTimeout(resolve62, ms));
|
|
95070
|
+
}
|
|
95071
|
+
function tryAcquireDirLock(lockDir) {
|
|
95072
|
+
try {
|
|
95073
|
+
mkdirSync15(lockDir, { recursive: false });
|
|
95074
|
+
return true;
|
|
95075
|
+
} catch (err) {
|
|
95076
|
+
if (!isErrno(err, "EEXIST")) throw err;
|
|
95077
|
+
return false;
|
|
95078
|
+
}
|
|
95079
|
+
}
|
|
95080
|
+
function reclaimStaleInstallLock(timeoutMs) {
|
|
95081
|
+
if (!tryAcquireDirLock(INSTALL_RECLAIM_LOCK_DIR)) return;
|
|
95082
|
+
try {
|
|
95083
|
+
const mtimeMs = statSync9(INSTALL_LOCK_DIR).mtimeMs;
|
|
95084
|
+
if (Date.now() - mtimeMs > timeoutMs) {
|
|
95085
|
+
rmSync6(INSTALL_LOCK_DIR, { recursive: true, force: true });
|
|
95086
|
+
}
|
|
95087
|
+
} catch (err) {
|
|
95088
|
+
if (!isErrno(err, "ENOENT")) throw err;
|
|
95089
|
+
} finally {
|
|
95090
|
+
rmSync6(INSTALL_RECLAIM_LOCK_DIR, { recursive: true, force: true });
|
|
95091
|
+
}
|
|
95092
|
+
}
|
|
95093
|
+
async function withInstallLock(fn, timeoutMs = INSTALL_LOCK_TIMEOUT_MS, pollMs = INSTALL_LOCK_POLL_MS) {
|
|
95094
|
+
if (!existsSync31(CACHE_DIR2)) mkdirSync15(CACHE_DIR2, { recursive: true });
|
|
95095
|
+
let deadline = Date.now() + timeoutMs;
|
|
95096
|
+
for (; ; ) {
|
|
95097
|
+
if (existsSync31(INSTALL_RECLAIM_LOCK_DIR)) {
|
|
95098
|
+
await sleep(pollMs);
|
|
95099
|
+
continue;
|
|
95100
|
+
}
|
|
95101
|
+
if (tryAcquireDirLock(INSTALL_LOCK_DIR)) {
|
|
95102
|
+
rmSync6(INSTALL_RECLAIM_LOCK_DIR, { recursive: true, force: true });
|
|
95103
|
+
break;
|
|
95104
|
+
}
|
|
95105
|
+
if (Date.now() > deadline) {
|
|
95106
|
+
reclaimStaleInstallLock(timeoutMs);
|
|
95107
|
+
deadline = Date.now() + timeoutMs;
|
|
95108
|
+
continue;
|
|
95109
|
+
}
|
|
95110
|
+
await sleep(pollMs);
|
|
95111
|
+
}
|
|
95112
|
+
try {
|
|
95113
|
+
return await fn();
|
|
95114
|
+
} finally {
|
|
95115
|
+
rmSync6(INSTALL_LOCK_DIR, { recursive: true, force: true });
|
|
95116
|
+
}
|
|
95117
|
+
}
|
|
95052
95118
|
function whichBinary2(name) {
|
|
95053
95119
|
try {
|
|
95054
95120
|
const cmd = process.platform === "win32" ? `where ${name}` : `which ${name}`;
|
|
@@ -95199,7 +95265,7 @@ async function findBrowser() {
|
|
|
95199
95265
|
`[browser] Cached binary missing at ${fromCache.staleHyperframesCachePath} \u2014 re-downloading...`
|
|
95200
95266
|
);
|
|
95201
95267
|
try {
|
|
95202
|
-
return await downloadBrowser();
|
|
95268
|
+
return await withInstallLock(() => downloadBrowser());
|
|
95203
95269
|
} catch (err) {
|
|
95204
95270
|
const cause = normalizeErrorMessage(err);
|
|
95205
95271
|
throw new Error(
|
|
@@ -95262,14 +95328,18 @@ async function ensureBrowser(options) {
|
|
|
95262
95328
|
console.warn(
|
|
95263
95329
|
`[browser] Cached binary missing at ${fromCache.staleHyperframesCachePath} \u2014 re-downloading...`
|
|
95264
95330
|
);
|
|
95265
|
-
return downloadBrowser(options);
|
|
95331
|
+
return withInstallLock(() => downloadBrowser(options));
|
|
95266
95332
|
}
|
|
95267
95333
|
const fromSystem = findFromSystem2();
|
|
95268
95334
|
if (fromSystem) {
|
|
95269
95335
|
warnSystemFallbackOnce(fromSystem.executablePath);
|
|
95270
95336
|
return fromSystem;
|
|
95271
95337
|
}
|
|
95272
|
-
return
|
|
95338
|
+
return withInstallLock(async () => {
|
|
95339
|
+
const afterLock = await findFromCache();
|
|
95340
|
+
if (afterLock.result) return afterLock.result;
|
|
95341
|
+
return downloadBrowser(options);
|
|
95342
|
+
});
|
|
95273
95343
|
}
|
|
95274
95344
|
async function downloadBrowser(options) {
|
|
95275
95345
|
if (isLinuxArm()) {
|
|
@@ -95299,7 +95369,7 @@ function clearBrowser() {
|
|
|
95299
95369
|
function isLinuxArm() {
|
|
95300
95370
|
return process.platform === "linux" && process.arch === "arm64";
|
|
95301
95371
|
}
|
|
95302
|
-
var CHROME_VERSION, CACHE_DIR2, PUPPETEER_CACHE_DIR, SYSTEM_CHROME_PATHS, _warnedSystemFallback;
|
|
95372
|
+
var CHROME_VERSION, CACHE_DIR2, PUPPETEER_CACHE_DIR, INSTALL_LOCK_DIR, INSTALL_RECLAIM_LOCK_DIR, INSTALL_LOCK_TIMEOUT_MS, INSTALL_LOCK_POLL_MS, SYSTEM_CHROME_PATHS, _warnedSystemFallback;
|
|
95303
95373
|
var init_manager2 = __esm({
|
|
95304
95374
|
"src/browser/manager.ts"() {
|
|
95305
95375
|
"use strict";
|
|
@@ -95307,6 +95377,10 @@ var init_manager2 = __esm({
|
|
|
95307
95377
|
CHROME_VERSION = "131.0.6778.85";
|
|
95308
95378
|
CACHE_DIR2 = join27(homedir9(), ".cache", "hyperframes", "chrome");
|
|
95309
95379
|
PUPPETEER_CACHE_DIR = join27(homedir9(), ".cache", "puppeteer", "chrome-headless-shell");
|
|
95380
|
+
INSTALL_LOCK_DIR = join27(CACHE_DIR2, ".install.lock");
|
|
95381
|
+
INSTALL_RECLAIM_LOCK_DIR = join27(CACHE_DIR2, ".install.reclaim.lock");
|
|
95382
|
+
INSTALL_LOCK_TIMEOUT_MS = 12e4;
|
|
95383
|
+
INSTALL_LOCK_POLL_MS = 200;
|
|
95310
95384
|
SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : [
|
|
95311
95385
|
"/usr/bin/google-chrome",
|
|
95312
95386
|
"/usr/bin/google-chrome-stable",
|
|
@@ -98587,7 +98661,7 @@ __export(deterministicFonts_exports, {
|
|
|
98587
98661
|
resolveFontFamilyDeclarationFamilies: () => resolveFontFamilyDeclarationFamilies
|
|
98588
98662
|
});
|
|
98589
98663
|
import { createHash as createHash6 } from "crypto";
|
|
98590
|
-
import { existsSync as existsSync33, mkdirSync as
|
|
98664
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync16, readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "fs";
|
|
98591
98665
|
import { homedir as homedir10, tmpdir as tmpdir3 } from "os";
|
|
98592
98666
|
import { join as join28 } from "path";
|
|
98593
98667
|
import postcss4 from "postcss";
|
|
@@ -98914,7 +98988,7 @@ function fontSlug(familyName) {
|
|
|
98914
98988
|
function fontCacheDir(slug) {
|
|
98915
98989
|
const dir = join28(GOOGLE_FONTS_CACHE_DIR, slug);
|
|
98916
98990
|
if (!existsSync33(dir)) {
|
|
98917
|
-
|
|
98991
|
+
mkdirSync16(dir, { recursive: true });
|
|
98918
98992
|
}
|
|
98919
98993
|
return dir;
|
|
98920
98994
|
}
|
|
@@ -99201,11 +99275,11 @@ import { spawn as spawn10 } from "child_process";
|
|
|
99201
99275
|
import {
|
|
99202
99276
|
copyFileSync as copyFileSync2,
|
|
99203
99277
|
existsSync as existsSync34,
|
|
99204
|
-
mkdirSync as
|
|
99278
|
+
mkdirSync as mkdirSync17,
|
|
99205
99279
|
readFileSync as readFileSync21,
|
|
99206
99280
|
renameSync as renameSync4,
|
|
99207
99281
|
rmSync as rmSync7,
|
|
99208
|
-
statSync as
|
|
99282
|
+
statSync as statSync10
|
|
99209
99283
|
} from "fs";
|
|
99210
99284
|
import { dirname as dirname13, isAbsolute as isAbsolute10, join as join29, resolve as resolve20 } from "path";
|
|
99211
99285
|
function splitUrlSuffix2(src) {
|
|
@@ -99251,7 +99325,7 @@ function resolveGifSourcePath(src, options) {
|
|
|
99251
99325
|
}
|
|
99252
99326
|
function isUsableFile(path2) {
|
|
99253
99327
|
try {
|
|
99254
|
-
const stat3 =
|
|
99328
|
+
const stat3 = statSync10(path2);
|
|
99255
99329
|
return stat3.isFile() && stat3.size > 0;
|
|
99256
99330
|
} catch {
|
|
99257
99331
|
return false;
|
|
@@ -99368,10 +99442,10 @@ async function runAnimatedGifTranscode(request) {
|
|
|
99368
99442
|
}
|
|
99369
99443
|
async function ensurePreparedWebm(input2) {
|
|
99370
99444
|
if (!existsSync34(dirname13(input2.cachePath))) {
|
|
99371
|
-
|
|
99445
|
+
mkdirSync17(dirname13(input2.cachePath), { recursive: true });
|
|
99372
99446
|
}
|
|
99373
99447
|
if (!existsSync34(dirname13(input2.outputPath))) {
|
|
99374
|
-
|
|
99448
|
+
mkdirSync17(dirname13(input2.outputPath), { recursive: true });
|
|
99375
99449
|
}
|
|
99376
99450
|
if (!isUsableFile(input2.cachePath)) {
|
|
99377
99451
|
const tmpPath = `${input2.cachePath}.tmp-${process.pid}-${Date.now()}`;
|
|
@@ -99617,7 +99691,7 @@ var init_hf_early_stub_inline = __esm({
|
|
|
99617
99691
|
// ../producer/src/services/fileServer.ts
|
|
99618
99692
|
import { Hono as Hono3 } from "hono";
|
|
99619
99693
|
import { serve as serve2 } from "@hono/node-server";
|
|
99620
|
-
import { existsSync as existsSync36, realpathSync as realpathSync4, statSync as
|
|
99694
|
+
import { existsSync as existsSync36, realpathSync as realpathSync4, statSync as statSync11, createReadStream } from "fs";
|
|
99621
99695
|
import { readFile as readFile2 } from "fs/promises";
|
|
99622
99696
|
import { Readable as Readable2 } from "stream";
|
|
99623
99697
|
import { join as join30, extname as extname9, resolve as resolve23, sep as sep5 } from "path";
|
|
@@ -99965,13 +100039,13 @@ function createFileServer2(options) {
|
|
|
99965
100039
|
let filePath = null;
|
|
99966
100040
|
if (compiledDir) {
|
|
99967
100041
|
const candidate = join30(compiledDir, relativePath);
|
|
99968
|
-
if (existsSync36(candidate) && isPathInside2(candidate, compiledDir) &&
|
|
100042
|
+
if (existsSync36(candidate) && isPathInside2(candidate, compiledDir) && statSync11(candidate).isFile()) {
|
|
99969
100043
|
filePath = candidate;
|
|
99970
100044
|
}
|
|
99971
100045
|
}
|
|
99972
100046
|
if (!filePath) {
|
|
99973
100047
|
const candidate = join30(projectDir, relativePath);
|
|
99974
|
-
if (existsSync36(candidate) && isPathInside2(candidate, projectDir) &&
|
|
100048
|
+
if (existsSync36(candidate) && isPathInside2(candidate, projectDir) && statSync11(candidate).isFile()) {
|
|
99975
100049
|
filePath = candidate;
|
|
99976
100050
|
}
|
|
99977
100051
|
}
|
|
@@ -99993,7 +100067,7 @@ function createFileServer2(options) {
|
|
|
99993
100067
|
html = isIndex ? injectScriptsIntoHtml(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
|
|
99994
100068
|
return c3.text(html, 200, { "Content-Type": contentType });
|
|
99995
100069
|
}
|
|
99996
|
-
const stat3 =
|
|
100070
|
+
const stat3 = statSync11(filePath);
|
|
99997
100071
|
const totalSize2 = stat3.size;
|
|
99998
100072
|
const rangeHeader = c3.req.header("range");
|
|
99999
100073
|
const rangeRequest = parseRangeHeader(rangeHeader, totalSize2);
|
|
@@ -100245,7 +100319,7 @@ var init_paths = __esm({
|
|
|
100245
100319
|
});
|
|
100246
100320
|
|
|
100247
100321
|
// ../producer/src/services/render/shared.ts
|
|
100248
|
-
import { copyFileSync as copyFileSync3, cpSync as cpSync2, existsSync as existsSync37, mkdirSync as
|
|
100322
|
+
import { copyFileSync as copyFileSync3, cpSync as cpSync2, existsSync as existsSync37, mkdirSync as mkdirSync18, symlinkSync as symlinkSync2, writeFileSync as writeFileSync12 } from "fs";
|
|
100249
100323
|
import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute11, join as join33, relative as relative8, resolve as resolve24 } from "path";
|
|
100250
100324
|
function writeFileExclusiveSync(path2, data2) {
|
|
100251
100325
|
try {
|
|
@@ -100275,11 +100349,11 @@ function resolveDeviceScaleFactor(input2) {
|
|
|
100275
100349
|
}
|
|
100276
100350
|
function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
100277
100351
|
const compileDir = join33(workDir, "compiled");
|
|
100278
|
-
|
|
100352
|
+
mkdirSync18(compileDir, { recursive: true });
|
|
100279
100353
|
writeFileSync12(join33(compileDir, "index.html"), compiled.html, "utf-8");
|
|
100280
100354
|
for (const [srcPath, html] of compiled.subCompositions) {
|
|
100281
100355
|
const outPath = join33(compileDir, srcPath);
|
|
100282
|
-
|
|
100356
|
+
mkdirSync18(dirname15(outPath), { recursive: true });
|
|
100283
100357
|
writeFileSync12(outPath, html, "utf-8");
|
|
100284
100358
|
}
|
|
100285
100359
|
for (const [relativePath, absolutePath] of compiled.externalAssets) {
|
|
@@ -100288,7 +100362,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
100288
100362
|
console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
|
|
100289
100363
|
continue;
|
|
100290
100364
|
}
|
|
100291
|
-
|
|
100365
|
+
mkdirSync18(dirname15(outPath), { recursive: true });
|
|
100292
100366
|
copyFileSync3(absolutePath, outPath);
|
|
100293
100367
|
}
|
|
100294
100368
|
if (includeSummary) {
|
|
@@ -100413,7 +100487,7 @@ var init_shared = __esm({
|
|
|
100413
100487
|
};
|
|
100414
100488
|
materializeFileSystem = {
|
|
100415
100489
|
existsSync: existsSync37,
|
|
100416
|
-
mkdirSync:
|
|
100490
|
+
mkdirSync: mkdirSync18,
|
|
100417
100491
|
symlinkSync: symlinkSync2,
|
|
100418
100492
|
cpSync: cpSync2
|
|
100419
100493
|
};
|
|
@@ -101605,7 +101679,7 @@ var init_manualEditsRenderScript = __esm({
|
|
|
101605
101679
|
});
|
|
101606
101680
|
|
|
101607
101681
|
// ../producer/src/services/htmlCompiler.ts
|
|
101608
|
-
import { readFileSync as readFileSync24, existsSync as existsSync38, mkdirSync as
|
|
101682
|
+
import { readFileSync as readFileSync24, existsSync as existsSync38, mkdirSync as mkdirSync19 } from "fs";
|
|
101609
101683
|
import { join as join35, dirname as dirname16, resolve as resolve25, basename as basename7 } from "path";
|
|
101610
101684
|
function parseSubCompHtmlForValidity(html) {
|
|
101611
101685
|
return parseHTML(html).document;
|
|
@@ -101715,7 +101789,7 @@ function detectShaderTransitionUsage(html) {
|
|
|
101715
101789
|
async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
|
|
101716
101790
|
let filePath = src;
|
|
101717
101791
|
if (isHttpUrl(src)) {
|
|
101718
|
-
if (!existsSync38(downloadDir))
|
|
101792
|
+
if (!existsSync38(downloadDir)) mkdirSync19(downloadDir, { recursive: true });
|
|
101719
101793
|
try {
|
|
101720
101794
|
filePath = await downloadToTemp(src, downloadDir);
|
|
101721
101795
|
} catch {
|
|
@@ -102202,7 +102276,7 @@ function collectExternalAssets(html, projectDir) {
|
|
|
102202
102276
|
}
|
|
102203
102277
|
async function downloadAndRewriteUrls(urlSet, html, remoteDir, warnLabel, logLabel, extraRewrite) {
|
|
102204
102278
|
if (urlSet.size === 0) return { html, remoteMediaAssets: /* @__PURE__ */ new Map() };
|
|
102205
|
-
if (!existsSync38(remoteDir))
|
|
102279
|
+
if (!existsSync38(remoteDir)) mkdirSync19(remoteDir, { recursive: true });
|
|
102206
102280
|
const urlToLocal = /* @__PURE__ */ new Map();
|
|
102207
102281
|
await Promise.all(
|
|
102208
102282
|
[...urlSet].map(async (url) => {
|
|
@@ -103465,6 +103539,7 @@ async function runAudioStage(input2) {
|
|
|
103465
103539
|
const stage3Start = Date.now();
|
|
103466
103540
|
const audioOutputPath = join39(workDir, "audio.aac");
|
|
103467
103541
|
let hasAudio = false;
|
|
103542
|
+
let audioError;
|
|
103468
103543
|
if (audios.length > 0) {
|
|
103469
103544
|
const audioResult = await processCompositionAudio(
|
|
103470
103545
|
audios,
|
|
@@ -103478,9 +103553,10 @@ async function runAudioStage(input2) {
|
|
|
103478
103553
|
);
|
|
103479
103554
|
assertNotAborted();
|
|
103480
103555
|
hasAudio = audioResult.success;
|
|
103556
|
+
if (!hasAudio) audioError = audioResult.error ?? "audio mix failed for an unknown reason";
|
|
103481
103557
|
}
|
|
103482
103558
|
const audioProcessMs = Date.now() - stage3Start;
|
|
103483
|
-
return { audioOutputPath, hasAudio, audioProcessMs };
|
|
103559
|
+
return { audioOutputPath, hasAudio, audioProcessMs, audioError };
|
|
103484
103560
|
}
|
|
103485
103561
|
var init_audioStage = __esm({
|
|
103486
103562
|
"../producer/src/services/render/stages/audioStage.ts"() {
|
|
@@ -104551,7 +104627,7 @@ import {
|
|
|
104551
104627
|
closeSync as closeSync3,
|
|
104552
104628
|
constants as constants2,
|
|
104553
104629
|
fstatSync as fstatSync2,
|
|
104554
|
-
mkdirSync as
|
|
104630
|
+
mkdirSync as mkdirSync20,
|
|
104555
104631
|
mkdtempSync as mkdtempSync2,
|
|
104556
104632
|
openSync as openSync2,
|
|
104557
104633
|
readFileSync as readFileSync25
|
|
@@ -104643,7 +104719,7 @@ async function extractHdrVideoFrames(args) {
|
|
|
104643
104719
|
for (const [videoId, srcPath] of prep.hdrVideoSrcPaths) {
|
|
104644
104720
|
const video = composition.videos.find((v2) => v2.id === videoId);
|
|
104645
104721
|
if (!video) continue;
|
|
104646
|
-
|
|
104722
|
+
mkdirSync20(framesDir, { recursive: true });
|
|
104647
104723
|
const frameDir = mkdtempSync2(join41(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
|
|
104648
104724
|
const duration = video.end - video.start;
|
|
104649
104725
|
const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
|
|
@@ -105362,7 +105438,7 @@ var init_captureHdrHybridLoop = __esm({
|
|
|
105362
105438
|
});
|
|
105363
105439
|
|
|
105364
105440
|
// ../producer/src/services/render/stages/captureHdrStage.ts
|
|
105365
|
-
import { existsSync as existsSync41, mkdirSync as
|
|
105441
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync21 } from "fs";
|
|
105366
105442
|
import { join as join46 } from "path";
|
|
105367
105443
|
async function runCaptureHdrStage(input2) {
|
|
105368
105444
|
const {
|
|
@@ -105524,7 +105600,7 @@ async function runCaptureHdrStage(input2) {
|
|
|
105524
105600
|
const debugDumpEnabled = process.env.KEEP_TEMP === "1";
|
|
105525
105601
|
const debugDumpDir = debugDumpEnabled ? join46(framesDir, "debug-composite") : null;
|
|
105526
105602
|
if (debugDumpDir && !existsSync41(debugDumpDir)) {
|
|
105527
|
-
|
|
105603
|
+
mkdirSync21(debugDumpDir, { recursive: true });
|
|
105528
105604
|
}
|
|
105529
105605
|
const compositeTransfer = resolveCompositeTransfer(hasHdrContent, effectiveHdr);
|
|
105530
105606
|
const hdrTargetTransfer = compositeTransfer === "srgb" ? void 0 : compositeTransfer;
|
|
@@ -105725,7 +105801,7 @@ var init_gifEncodeArgs = __esm({
|
|
|
105725
105801
|
});
|
|
105726
105802
|
|
|
105727
105803
|
// ../producer/src/services/render/stages/encodeStage.ts
|
|
105728
|
-
import { copyFileSync as copyFileSync4, existsSync as existsSync43, mkdirSync as
|
|
105804
|
+
import { copyFileSync as copyFileSync4, existsSync as existsSync43, mkdirSync as mkdirSync23, readdirSync as readdirSync14, rmSync as rmSync10, statSync as statSync12 } from "fs";
|
|
105729
105805
|
import { dirname as dirname18, join as join48 } from "path";
|
|
105730
105806
|
function resolveGifLoop(loop) {
|
|
105731
105807
|
const resolved = loop ?? 0;
|
|
@@ -105785,7 +105861,7 @@ async function encodeGifFromDir(framesDir, framePattern, outputPath, input2) {
|
|
|
105785
105861
|
error: formatFfmpegError(gifResult.exitCode, gifResult.stderr)
|
|
105786
105862
|
};
|
|
105787
105863
|
}
|
|
105788
|
-
const fileSize = existsSync43(outputPath) ?
|
|
105864
|
+
const fileSize = existsSync43(outputPath) ? statSync12(outputPath).size : 0;
|
|
105789
105865
|
return {
|
|
105790
105866
|
success: true,
|
|
105791
105867
|
outputPath,
|
|
@@ -105823,7 +105899,7 @@ async function runEncodeStage(input2) {
|
|
|
105823
105899
|
const stage5Start = Date.now();
|
|
105824
105900
|
if (isPngSequence) {
|
|
105825
105901
|
updateJobStatus(job, "encoding", "Writing PNG sequence", 75, onProgress);
|
|
105826
|
-
if (!existsSync43(outputPath))
|
|
105902
|
+
if (!existsSync43(outputPath)) mkdirSync23(outputPath, { recursive: true });
|
|
105827
105903
|
const captured = readdirSync14(framesDir).filter((name) => name.endsWith(".png")).sort();
|
|
105828
105904
|
if (captured.length === 0) {
|
|
105829
105905
|
throw new Error(
|
|
@@ -105967,12 +106043,12 @@ var init_assembleStage = __esm({
|
|
|
105967
106043
|
// ../producer/src/services/renderOrchestrator.ts
|
|
105968
106044
|
import {
|
|
105969
106045
|
existsSync as existsSync44,
|
|
105970
|
-
mkdirSync as
|
|
106046
|
+
mkdirSync as mkdirSync24,
|
|
105971
106047
|
mkdtempSync as mkdtempSync3,
|
|
105972
106048
|
readFileSync as readFileSync26,
|
|
105973
106049
|
readdirSync as readdirSync15,
|
|
105974
106050
|
rmSync as rmSync11,
|
|
105975
|
-
statSync as
|
|
106051
|
+
statSync as statSync13,
|
|
105976
106052
|
writeFileSync as writeFileSync13,
|
|
105977
106053
|
copyFileSync as copyFileSync5,
|
|
105978
106054
|
appendFileSync
|
|
@@ -105995,7 +106071,7 @@ function sampleDirectoryBytes(dir) {
|
|
|
105995
106071
|
for (const name of entries2) {
|
|
105996
106072
|
const full2 = join49(current2, name);
|
|
105997
106073
|
try {
|
|
105998
|
-
const st3 =
|
|
106074
|
+
const st3 = statSync13(full2);
|
|
105999
106075
|
if (st3.isDirectory()) {
|
|
106000
106076
|
stack.push(full2);
|
|
106001
106077
|
} else if (st3.isFile()) {
|
|
@@ -106350,7 +106426,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
106350
106426
|
const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve26(process.env.PRODUCER_RENDERS_DIR, "..") : resolve26(moduleDir, "../..");
|
|
106351
106427
|
const debugDir = join49(producerRoot, ".debug");
|
|
106352
106428
|
const outputDir = dirname19(outputPath);
|
|
106353
|
-
if (!existsSync44(outputDir))
|
|
106429
|
+
if (!existsSync44(outputDir)) mkdirSync24(outputDir, { recursive: true });
|
|
106354
106430
|
const workDir = job.config.debug ? join49(debugDir, job.id) : mkdtempSync3(join49(outputDir, `work-${job.id}-`));
|
|
106355
106431
|
const pipelineStart = Date.now();
|
|
106356
106432
|
const log2 = job.config.logger ?? defaultLogger;
|
|
@@ -106412,7 +106488,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
106412
106488
|
job.startedAt = /* @__PURE__ */ new Date();
|
|
106413
106489
|
assertNotAborted();
|
|
106414
106490
|
assertConfiguredFfmpegBinariesExist();
|
|
106415
|
-
if (!existsSync44(workDir))
|
|
106491
|
+
if (!existsSync44(workDir)) mkdirSync24(workDir, { recursive: true });
|
|
106416
106492
|
if (job.config.debug) {
|
|
106417
106493
|
const logPath = join49(workDir, "render.log");
|
|
106418
106494
|
restoreLogger = installDebugLogger(logPath, log2);
|
|
@@ -106648,6 +106724,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
106648
106724
|
);
|
|
106649
106725
|
const { audioOutputPath, hasAudio } = audioResult;
|
|
106650
106726
|
perfStages.audioProcessMs = audioResult.audioProcessMs;
|
|
106727
|
+
if (audioResult.audioError) {
|
|
106728
|
+
log2.warn(`[Render] Audio mix failed \u2014 output will be video-only: ${audioResult.audioError}`);
|
|
106729
|
+
}
|
|
106651
106730
|
const stage4Start = Date.now();
|
|
106652
106731
|
updateJobStatus(job, "rendering", "Starting frame capture", 25, onProgress);
|
|
106653
106732
|
if (!fileServer) {
|
|
@@ -106674,7 +106753,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
106674
106753
|
throw new Error("File server failed to initialize before frame capture");
|
|
106675
106754
|
}
|
|
106676
106755
|
const framesDir = join49(workDir, "captured-frames");
|
|
106677
|
-
if (!existsSync44(framesDir))
|
|
106756
|
+
if (!existsSync44(framesDir)) mkdirSync24(framesDir, { recursive: true });
|
|
106678
106757
|
const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
|
|
106679
106758
|
chromePath: resolveHeadlessShellPath(cfg),
|
|
106680
106759
|
browserTimeout: cfg.browserTimeout
|
|
@@ -107264,7 +107343,7 @@ var init_config3 = __esm({
|
|
|
107264
107343
|
});
|
|
107265
107344
|
|
|
107266
107345
|
// ../producer/src/services/hyperframeLint.ts
|
|
107267
|
-
import { existsSync as existsSync45, readFileSync as readFileSync27, statSync as
|
|
107346
|
+
import { existsSync as existsSync45, readFileSync as readFileSync27, statSync as statSync14 } from "fs";
|
|
107268
107347
|
import { resolve as resolve27, join as join50 } from "path";
|
|
107269
107348
|
function isStringRecord2(value) {
|
|
107270
107349
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -107293,7 +107372,7 @@ function pickEntryFile(files, preferredEntryFile) {
|
|
|
107293
107372
|
}
|
|
107294
107373
|
function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
107295
107374
|
const absProjectDir = resolve27(projectDir);
|
|
107296
|
-
if (!existsSync45(absProjectDir) || !
|
|
107375
|
+
if (!existsSync45(absProjectDir) || !statSync14(absProjectDir).isDirectory()) {
|
|
107297
107376
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
107298
107377
|
}
|
|
107299
107378
|
const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
|
|
@@ -107304,7 +107383,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
|
107304
107383
|
if (!absoluteEntryPath.startsWith(absProjectDir)) {
|
|
107305
107384
|
return { error: `Entry file must stay inside project directory: ${entryFile}` };
|
|
107306
107385
|
}
|
|
107307
|
-
if (existsSync45(absoluteEntryPath) &&
|
|
107386
|
+
if (existsSync45(absoluteEntryPath) && statSync14(absoluteEntryPath).isFile()) {
|
|
107308
107387
|
return {
|
|
107309
107388
|
entryFile,
|
|
107310
107389
|
html: readFileSync27(absoluteEntryPath, "utf-8"),
|
|
@@ -107495,8 +107574,8 @@ var init_semaphore = __esm({
|
|
|
107495
107574
|
// ../producer/src/server.ts
|
|
107496
107575
|
import {
|
|
107497
107576
|
existsSync as existsSync47,
|
|
107498
|
-
mkdirSync as
|
|
107499
|
-
statSync as
|
|
107577
|
+
mkdirSync as mkdirSync25,
|
|
107578
|
+
statSync as statSync15,
|
|
107500
107579
|
mkdtempSync as mkdtempSync4,
|
|
107501
107580
|
writeFileSync as writeFileSync14,
|
|
107502
107581
|
rmSync as rmSync12,
|
|
@@ -107563,7 +107642,7 @@ function resolvePreparedRenderOutput(prepared, rendersDir, log2) {
|
|
|
107563
107642
|
const { input: input2, cleanupProjectDir } = prepared;
|
|
107564
107643
|
const absoluteOutputPath = resolveOutputPath(input2.projectDir, input2.outputPath, rendersDir, log2);
|
|
107565
107644
|
const outputDir = dirname21(absoluteOutputPath);
|
|
107566
|
-
if (!existsSync47(outputDir))
|
|
107645
|
+
if (!existsSync47(outputDir)) mkdirSync25(outputDir, { recursive: true });
|
|
107567
107646
|
return { input: input2, cleanupProjectDir, absoluteOutputPath };
|
|
107568
107647
|
}
|
|
107569
107648
|
function validateRenderOverrides(body) {
|
|
@@ -107593,7 +107672,7 @@ async function prepareRenderBody(body) {
|
|
|
107593
107672
|
const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
|
|
107594
107673
|
if (projectDir) {
|
|
107595
107674
|
const absProjectDir = resolve28(projectDir);
|
|
107596
|
-
if (!existsSync47(absProjectDir) || !
|
|
107675
|
+
if (!existsSync47(absProjectDir) || !statSync15(absProjectDir).isDirectory()) {
|
|
107597
107676
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
107598
107677
|
}
|
|
107599
107678
|
const entry = options.entryFile || "index.html";
|
|
@@ -107760,7 +107839,7 @@ function createRenderHandlers(options = {}) {
|
|
|
107760
107839
|
log2.info(`render progress ${pct}%`, { requestId, stage: j3.currentStage, message });
|
|
107761
107840
|
}
|
|
107762
107841
|
});
|
|
107763
|
-
const fileSize = existsSync47(absoluteOutputPath) ?
|
|
107842
|
+
const fileSize = existsSync47(absoluteOutputPath) ? statSync15(absoluteOutputPath).size : 0;
|
|
107764
107843
|
const durationMs = Date.now() - t0;
|
|
107765
107844
|
const outputToken = store.register(absoluteOutputPath);
|
|
107766
107845
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
@@ -107876,7 +107955,7 @@ function createRenderHandlers(options = {}) {
|
|
|
107876
107955
|
},
|
|
107877
107956
|
abortController.signal
|
|
107878
107957
|
);
|
|
107879
|
-
const fileSize = existsSync47(absoluteOutputPath) ?
|
|
107958
|
+
const fileSize = existsSync47(absoluteOutputPath) ? statSync15(absoluteOutputPath).size : 0;
|
|
107880
107959
|
const outputToken = store.register(absoluteOutputPath);
|
|
107881
107960
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
107882
107961
|
log2.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
|
|
@@ -107939,7 +108018,7 @@ function createRenderHandlers(options = {}) {
|
|
|
107939
108018
|
store.delete(token);
|
|
107940
108019
|
return c3.json({ success: false, error: "Output artifact file missing" }, 404);
|
|
107941
108020
|
}
|
|
107942
|
-
const stats =
|
|
108021
|
+
const stats = statSync15(artifact.path);
|
|
107943
108022
|
return new Response(createReadStream2(artifact.path), {
|
|
107944
108023
|
headers: {
|
|
107945
108024
|
"content-type": "video/mp4",
|
|
@@ -108103,7 +108182,7 @@ var init_planHash = __esm({
|
|
|
108103
108182
|
});
|
|
108104
108183
|
|
|
108105
108184
|
// ../producer/src/services/render/stages/freezePlan.ts
|
|
108106
|
-
import { existsSync as existsSync48, mkdirSync as
|
|
108185
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync26, readFileSync as readFileSync28, readdirSync as readdirSync16, writeFileSync as writeFileSync15 } from "fs";
|
|
108107
108186
|
import { join as join54, relative as relative9, resolve as resolve29 } from "path";
|
|
108108
108187
|
function stripUndefined(value) {
|
|
108109
108188
|
if (Array.isArray(value)) return value.map(stripUndefined);
|
|
@@ -108199,7 +108278,7 @@ async function freezePlan(input2) {
|
|
|
108199
108278
|
throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
|
|
108200
108279
|
}
|
|
108201
108280
|
const metaDir = join54(planDir, "meta");
|
|
108202
|
-
if (!existsSync48(metaDir))
|
|
108281
|
+
if (!existsSync48(metaDir)) mkdirSync26(metaDir, { recursive: true });
|
|
108203
108282
|
writeFileSync15(
|
|
108204
108283
|
join54(metaDir, "composition.json"),
|
|
108205
108284
|
`${JSON.stringify(composition, null, 2)}
|
|
@@ -108429,11 +108508,11 @@ var init_shared2 = __esm({
|
|
|
108429
108508
|
import {
|
|
108430
108509
|
cpSync as cpSync3,
|
|
108431
108510
|
existsSync as existsSync50,
|
|
108432
|
-
mkdirSync as
|
|
108511
|
+
mkdirSync as mkdirSync27,
|
|
108433
108512
|
readdirSync as readdirSync17,
|
|
108434
108513
|
renameSync as renameSync5,
|
|
108435
108514
|
rmSync as rmSync13,
|
|
108436
|
-
statSync as
|
|
108515
|
+
statSync as statSync16,
|
|
108437
108516
|
writeFileSync as writeFileSync16
|
|
108438
108517
|
} from "fs";
|
|
108439
108518
|
import { join as join56, relative as relative10, sep as sep6 } from "path";
|
|
@@ -108466,7 +108545,7 @@ function measurePlanDirBytes(planDir) {
|
|
|
108466
108545
|
walk(full2);
|
|
108467
108546
|
} else if (entry.isFile()) {
|
|
108468
108547
|
try {
|
|
108469
|
-
total +=
|
|
108548
|
+
total += statSync16(full2).size;
|
|
108470
108549
|
} catch {
|
|
108471
108550
|
}
|
|
108472
108551
|
}
|
|
@@ -108600,7 +108679,7 @@ async function plan(projectDir, config, planDir) {
|
|
|
108600
108679
|
useGpu: false,
|
|
108601
108680
|
browserGpuMode: "software"
|
|
108602
108681
|
});
|
|
108603
|
-
if (!existsSync50(planDir))
|
|
108682
|
+
if (!existsSync50(planDir)) mkdirSync27(planDir, { recursive: true });
|
|
108604
108683
|
const log2 = config.logger ?? defaultLogger;
|
|
108605
108684
|
const abortSignal = config.abortSignal;
|
|
108606
108685
|
const assertNotAborted = () => {
|
|
@@ -108634,9 +108713,9 @@ async function plan(projectDir, config, planDir) {
|
|
|
108634
108713
|
throw new Error(`[plan] entry file not found: ${htmlPath}`);
|
|
108635
108714
|
}
|
|
108636
108715
|
const workDir = join56(planDir, ".plan-work");
|
|
108637
|
-
if (!existsSync50(workDir))
|
|
108716
|
+
if (!existsSync50(workDir)) mkdirSync27(workDir, { recursive: true });
|
|
108638
108717
|
const compiledDir = join56(workDir, "compiled");
|
|
108639
|
-
|
|
108718
|
+
mkdirSync27(compiledDir, { recursive: true });
|
|
108640
108719
|
cpSync3(projectDir, compiledDir, {
|
|
108641
108720
|
recursive: true,
|
|
108642
108721
|
dereference: true,
|
|
@@ -108729,13 +108808,16 @@ async function plan(projectDir, config, planDir) {
|
|
|
108729
108808
|
abortSignal,
|
|
108730
108809
|
assertNotAborted
|
|
108731
108810
|
});
|
|
108811
|
+
if (audioResult.audioError) {
|
|
108812
|
+
log2.warn(`[Render] Audio mix failed \u2014 output will be video-only: ${audioResult.audioError}`);
|
|
108813
|
+
}
|
|
108732
108814
|
const stagedVideoFrames = join56(compiledDir, "__hyperframes_video_frames");
|
|
108733
108815
|
const videoFramesDst = join56(planDir, "video-frames");
|
|
108734
108816
|
if (existsSync50(videoFramesDst)) rmSync13(videoFramesDst, { recursive: true, force: true });
|
|
108735
108817
|
if (existsSync50(stagedVideoFrames)) {
|
|
108736
108818
|
renameSync5(stagedVideoFrames, videoFramesDst);
|
|
108737
108819
|
} else {
|
|
108738
|
-
|
|
108820
|
+
mkdirSync27(videoFramesDst, { recursive: true });
|
|
108739
108821
|
}
|
|
108740
108822
|
if (existsSync50(finalCompiledDir)) rmSync13(finalCompiledDir, { recursive: true, force: true });
|
|
108741
108823
|
renameSync5(compiledDir, finalCompiledDir);
|
|
@@ -108750,7 +108832,7 @@ async function plan(projectDir, config, planDir) {
|
|
|
108750
108832
|
metadata: ext.metadata
|
|
108751
108833
|
}))
|
|
108752
108834
|
};
|
|
108753
|
-
|
|
108835
|
+
mkdirSync27(join56(planDir, "meta"), { recursive: true });
|
|
108754
108836
|
writeFileSync16(
|
|
108755
108837
|
join56(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
|
|
108756
108838
|
JSON.stringify(planVideosJson, null, 2),
|
|
@@ -108900,7 +108982,7 @@ var init_plan = __esm({
|
|
|
108900
108982
|
|
|
108901
108983
|
// ../producer/src/services/distributed/renderChunk.ts
|
|
108902
108984
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
108903
|
-
import { existsSync as existsSync51, mkdirSync as
|
|
108985
|
+
import { existsSync as existsSync51, mkdirSync as mkdirSync28, readFileSync as readFileSync30, readdirSync as readdirSync18, rmSync as rmSync14, writeFileSync as writeFileSync17 } from "fs";
|
|
108904
108986
|
import { extname as extname10, join as join57 } from "path";
|
|
108905
108987
|
function rebuildExtractedFramesFromPlanDir(planDir, videos) {
|
|
108906
108988
|
const result = [];
|
|
@@ -109066,9 +109148,9 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
109066
109148
|
"software"
|
|
109067
109149
|
);
|
|
109068
109150
|
const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
|
|
109069
|
-
|
|
109151
|
+
mkdirSync28(workDir, { recursive: true });
|
|
109070
109152
|
const framesDir = join57(workDir, "captured-frames");
|
|
109071
|
-
|
|
109153
|
+
mkdirSync28(framesDir, { recursive: true });
|
|
109072
109154
|
const fileServer = await createFileServer2({
|
|
109073
109155
|
projectDir: compiledDir,
|
|
109074
109156
|
compiledDir,
|
|
@@ -109147,10 +109229,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
109147
109229
|
const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
|
|
109148
109230
|
const videoOnlyPath = outputChunkPath;
|
|
109149
109231
|
if (isPngSequence) {
|
|
109150
|
-
if (!existsSync51(outputChunkPath))
|
|
109232
|
+
if (!existsSync51(outputChunkPath)) mkdirSync28(outputChunkPath, { recursive: true });
|
|
109151
109233
|
} else {
|
|
109152
109234
|
const outDir = join57(outputChunkPath, "..");
|
|
109153
|
-
if (!existsSync51(outDir))
|
|
109235
|
+
if (!existsSync51(outDir)) mkdirSync28(outDir, { recursive: true });
|
|
109154
109236
|
}
|
|
109155
109237
|
const encodeStarted = Date.now();
|
|
109156
109238
|
await runEncodeStage({
|
|
@@ -109589,11 +109671,11 @@ var init_audioPadTrim = __esm({
|
|
|
109589
109671
|
import {
|
|
109590
109672
|
cpSync as cpSync4,
|
|
109591
109673
|
existsSync as existsSync53,
|
|
109592
|
-
mkdirSync as
|
|
109674
|
+
mkdirSync as mkdirSync29,
|
|
109593
109675
|
readFileSync as readFileSync31,
|
|
109594
109676
|
readdirSync as readdirSync19,
|
|
109595
109677
|
rmSync as rmSync16,
|
|
109596
|
-
statSync as
|
|
109678
|
+
statSync as statSync17,
|
|
109597
109679
|
writeFileSync as writeFileSync18
|
|
109598
109680
|
} from "fs";
|
|
109599
109681
|
import { dirname as dirname23, join as join58 } from "path";
|
|
@@ -109626,11 +109708,11 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
|
|
|
109626
109708
|
return mergePngFrameDirs(chunkPaths, outputPath, plan2.totalFrames, audioPath, start);
|
|
109627
109709
|
}
|
|
109628
109710
|
if (!existsSync53(dirname23(outputPath))) {
|
|
109629
|
-
|
|
109711
|
+
mkdirSync29(dirname23(outputPath), { recursive: true });
|
|
109630
109712
|
}
|
|
109631
109713
|
const workDir = `${outputPath}.assemble-work`;
|
|
109632
109714
|
if (existsSync53(workDir)) rmSync16(workDir, { recursive: true, force: true });
|
|
109633
|
-
|
|
109715
|
+
mkdirSync29(workDir, { recursive: true });
|
|
109634
109716
|
try {
|
|
109635
109717
|
const concatOutputPath = join58(workDir, `concat.${plan2.dimensions.format}`);
|
|
109636
109718
|
const fpsArg = fpsToFfmpegArg({
|
|
@@ -109775,7 +109857,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
|
|
|
109775
109857
|
});
|
|
109776
109858
|
}
|
|
109777
109859
|
}
|
|
109778
|
-
const fileSize = existsSync53(outputPath) ?
|
|
109860
|
+
const fileSize = existsSync53(outputPath) ? statSync17(outputPath).size : 0;
|
|
109779
109861
|
return {
|
|
109780
109862
|
outputPath,
|
|
109781
109863
|
durationMs: Date.now() - start,
|
|
@@ -109785,10 +109867,10 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
|
|
|
109785
109867
|
}
|
|
109786
109868
|
function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, startTimeMs) {
|
|
109787
109869
|
if (existsSync53(outputPath)) rmSync16(outputPath, { recursive: true, force: true });
|
|
109788
|
-
|
|
109870
|
+
mkdirSync29(outputPath, { recursive: true });
|
|
109789
109871
|
let globalIdx = 0;
|
|
109790
109872
|
for (const chunkDir of chunkPaths) {
|
|
109791
|
-
if (!
|
|
109873
|
+
if (!statSync17(chunkDir).isDirectory()) {
|
|
109792
109874
|
throw new Error(
|
|
109793
109875
|
`[assemble] png-sequence chunk must be a directory: ${chunkDir} (got a file)`
|
|
109794
109876
|
);
|
|
@@ -109815,7 +109897,7 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
|
|
|
109815
109897
|
let fileSize = 0;
|
|
109816
109898
|
for (const name of readdirSync19(outputPath)) {
|
|
109817
109899
|
try {
|
|
109818
|
-
fileSize +=
|
|
109900
|
+
fileSize += statSync17(join58(outputPath, name)).size;
|
|
109819
109901
|
} catch {
|
|
109820
109902
|
}
|
|
109821
109903
|
}
|
|
@@ -109929,7 +110011,7 @@ __export(studioServer_exports, {
|
|
|
109929
110011
|
});
|
|
109930
110012
|
import { Hono as Hono5 } from "hono";
|
|
109931
110013
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
109932
|
-
import { existsSync as existsSync54, readFileSync as readFileSync34, writeFileSync as writeFileSync19, statSync as
|
|
110014
|
+
import { existsSync as existsSync54, readFileSync as readFileSync34, writeFileSync as writeFileSync19, statSync as statSync18 } from "fs";
|
|
109933
110015
|
import { resolve as resolve30, join as join60, basename as basename8 } from "path";
|
|
109934
110016
|
function resolveDistDir() {
|
|
109935
110017
|
return resolveStudioBundle().dir;
|
|
@@ -110385,7 +110467,7 @@ function createStudioServer(options) {
|
|
|
110385
110467
|
});
|
|
110386
110468
|
const serveStudioStaticFile = (c3) => {
|
|
110387
110469
|
const filePath = resolve30(studioDir, c3.req.path.slice(1));
|
|
110388
|
-
if (!existsSync54(filePath) || !
|
|
110470
|
+
if (!existsSync54(filePath) || !statSync18(filePath).isFile()) return c3.text("not found", 404);
|
|
110389
110471
|
const content = readFileSync34(filePath);
|
|
110390
110472
|
return new Response(content, {
|
|
110391
110473
|
headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
|
|
@@ -110496,7 +110578,7 @@ __export(preview_exports, {
|
|
|
110496
110578
|
examples: () => examples2
|
|
110497
110579
|
});
|
|
110498
110580
|
import { spawn as spawn12 } from "child_process";
|
|
110499
|
-
import { existsSync as existsSync55, lstatSync as lstatSync3, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, readlinkSync, mkdirSync as
|
|
110581
|
+
import { existsSync as existsSync55, lstatSync as lstatSync3, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
|
|
110500
110582
|
import { resolve as resolve31, dirname as dirname24, basename as basename9, join as join61 } from "path";
|
|
110501
110583
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
110502
110584
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -110804,7 +110886,7 @@ function printStudioSummary(projectName, url, opts = {}) {
|
|
|
110804
110886
|
}
|
|
110805
110887
|
function linkProjectIntoStudioData(dir, projectsDir, projectName) {
|
|
110806
110888
|
const symlinkPath = join61(projectsDir, projectName);
|
|
110807
|
-
|
|
110889
|
+
mkdirSync30(projectsDir, { recursive: true });
|
|
110808
110890
|
let createdSymlink = false;
|
|
110809
110891
|
if (dir !== symlinkPath) {
|
|
110810
110892
|
if (existsSync55(symlinkPath)) {
|
|
@@ -111251,7 +111333,7 @@ __export(init_exports, {
|
|
|
111251
111333
|
});
|
|
111252
111334
|
import {
|
|
111253
111335
|
existsSync as existsSync56,
|
|
111254
|
-
mkdirSync as
|
|
111336
|
+
mkdirSync as mkdirSync31,
|
|
111255
111337
|
copyFileSync as copyFileSync6,
|
|
111256
111338
|
cpSync as cpSync5,
|
|
111257
111339
|
writeFileSync as writeFileSync20,
|
|
@@ -111590,7 +111672,7 @@ function applyResolutionPreset(destDir, resolution) {
|
|
|
111590
111672
|
}
|
|
111591
111673
|
}
|
|
111592
111674
|
async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
|
|
111593
|
-
|
|
111675
|
+
mkdirSync31(destDir, { recursive: true });
|
|
111594
111676
|
const templateDir = getStaticTemplateDir(templateId);
|
|
111595
111677
|
if (existsSync56(join63(templateDir, "index.html"))) {
|
|
111596
111678
|
cpSync5(templateDir, destDir, { recursive: true });
|
|
@@ -111832,7 +111914,7 @@ var init_init = __esm({
|
|
|
111832
111914
|
console.error(c.error(`Audio file not found: ${audioFlag}`));
|
|
111833
111915
|
process.exit(1);
|
|
111834
111916
|
}
|
|
111835
|
-
|
|
111917
|
+
mkdirSync31(destDir2, { recursive: true });
|
|
111836
111918
|
let localVideoName2;
|
|
111837
111919
|
let videoDuration2;
|
|
111838
111920
|
let sourceFilePath2;
|
|
@@ -111974,7 +112056,7 @@ var init_init = __esm({
|
|
|
111974
112056
|
me("Setup cancelled.");
|
|
111975
112057
|
process.exit(1);
|
|
111976
112058
|
}
|
|
111977
|
-
|
|
112059
|
+
mkdirSync31(destDir, { recursive: true });
|
|
111978
112060
|
sourceFilePath = videoPath;
|
|
111979
112061
|
const result = await handleVideoFile(videoPath, destDir, true);
|
|
111980
112062
|
localVideoName = result.localVideoName;
|
|
@@ -111986,7 +112068,7 @@ var init_init = __esm({
|
|
|
111986
112068
|
me("Setup cancelled.");
|
|
111987
112069
|
process.exit(1);
|
|
111988
112070
|
}
|
|
111989
|
-
|
|
112071
|
+
mkdirSync31(destDir, { recursive: true });
|
|
111990
112072
|
sourceFilePath = audioPath;
|
|
111991
112073
|
copyFileSync6(audioPath, resolve33(destDir, basename10(audioPath)));
|
|
111992
112074
|
R2.info(`Audio copied to ${c.accent(basename10(audioPath))}`);
|
|
@@ -112856,18 +112938,18 @@ function buildPresentPage(projectName, islandJson) {
|
|
|
112856
112938
|
<meta charset="UTF-8" />
|
|
112857
112939
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
112858
112940
|
<title>${escHtml(projectName)} \u2014 Presenter</title>
|
|
112941
|
+
<script>
|
|
112942
|
+
// Retitle the audience tab so the two tabs are distinguishable in the
|
|
112943
|
+
// browser tab strip and in Meet's "Share a tab" picker.
|
|
112944
|
+
if (new URLSearchParams(location.search).get("mode") === "audience") {
|
|
112945
|
+
document.title = ${JSON.stringify(projectName).replace(/</g, "\\u003c")} + " \u2014 Audience";
|
|
112946
|
+
}
|
|
112947
|
+
</script>
|
|
112859
112948
|
<style>
|
|
112860
112949
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
112861
112950
|
html, body { height: 100%; background: #0a0a0a; overflow: hidden; }
|
|
112862
112951
|
hyperframes-slideshow { display: block; position: relative; width: 100vw; height: 100vh; }
|
|
112863
112952
|
hyperframes-player { position: absolute; inset: 0; }
|
|
112864
|
-
#present-btn {
|
|
112865
|
-
position: fixed; top: 18px; right: 18px; z-index: 99999;
|
|
112866
|
-
font: 600 14px/1 system-ui, sans-serif; color: #0d1321;
|
|
112867
|
-
background: #f4b740; border: none; border-radius: 999px;
|
|
112868
|
-
padding: 11px 18px; cursor: pointer; box-shadow: 0 6px 20px rgba(0,0,0,.45);
|
|
112869
|
-
}
|
|
112870
|
-
#present-btn:hover { background: #ffcb5c; }
|
|
112871
112953
|
</style>
|
|
112872
112954
|
<script src="/player.js"></script>
|
|
112873
112955
|
<script src="/slideshow.js"></script>
|
|
@@ -112879,28 +112961,8 @@ function buildPresentPage(projectName, islandJson) {
|
|
|
112879
112961
|
${islandJson}
|
|
112880
112962
|
</script>
|
|
112881
112963
|
</hyperframes-slideshow>
|
|
112882
|
-
|
|
112883
|
-
|
|
112884
|
-
(function () {
|
|
112885
|
-
// The audience window loads this same page with ?mode=audience; it must not
|
|
112886
|
-
// show the Present button or it would recurse opening windows.
|
|
112887
|
-
var isAudience = new URLSearchParams(location.search).get("mode") === "audience";
|
|
112888
|
-
var btn = document.getElementById("present-btn");
|
|
112889
|
-
if (isAudience) { if (btn) btn.remove(); return; }
|
|
112890
|
-
function present() {
|
|
112891
|
-
var ss = document.querySelector("hyperframes-slideshow");
|
|
112892
|
-
if (ss && typeof ss.present === "function") {
|
|
112893
|
-
ss.present();
|
|
112894
|
-
if (btn) btn.style.display = "none";
|
|
112895
|
-
}
|
|
112896
|
-
}
|
|
112897
|
-
if (btn) btn.addEventListener("click", present);
|
|
112898
|
-
// 'P' opens presenter mode (window.open needs a user gesture, so a key/click).
|
|
112899
|
-
window.addEventListener("keydown", function (e) {
|
|
112900
|
-
if ((e.key === "p" || e.key === "P") && !e.metaKey && !e.ctrlKey) present();
|
|
112901
|
-
});
|
|
112902
|
-
})();
|
|
112903
|
-
</script>
|
|
112964
|
+
<!-- Present CTA lives in the component's nav cluster (data-hf-present, plus
|
|
112965
|
+
the P key) \u2014 no page-level button, or we'd render two Present CTAs. -->
|
|
112904
112966
|
<script>
|
|
112905
112967
|
// Sound effects play HERE, in the parent document. The composition runs in the
|
|
112906
112968
|
// player's iframe, which is autoplay-blocked without its own user gesture; the
|
|
@@ -113069,6 +113131,15 @@ var init_present = __esm({
|
|
|
113069
113131
|
return;
|
|
113070
113132
|
}
|
|
113071
113133
|
const islandJson = islandMatch[1].trim();
|
|
113134
|
+
try {
|
|
113135
|
+
JSON.parse(islandJson);
|
|
113136
|
+
} catch (err) {
|
|
113137
|
+
R2.error(
|
|
113138
|
+
`Slideshow island in ${project.indexPath} is not valid JSON: ${err.message}`
|
|
113139
|
+
);
|
|
113140
|
+
process.exitCode = 1;
|
|
113141
|
+
return;
|
|
113142
|
+
}
|
|
113072
113143
|
const { Hono: Hono6 } = await import("hono");
|
|
113073
113144
|
const { createAdaptorServer } = await import("@hono/node-server");
|
|
113074
113145
|
const { isSafePath: isSafePath2 } = await Promise.resolve().then(() => (init_studio_api(), studio_api_exports));
|
|
@@ -113110,7 +113181,15 @@ var init_present = __esm({
|
|
|
113110
113181
|
console.log(` ${c.dim("Deck")} ${c.accent(project.name)}`);
|
|
113111
113182
|
console.log(` ${c.dim("Present")} ${c.accent(url)}`);
|
|
113112
113183
|
console.log();
|
|
113113
|
-
console.log(
|
|
113184
|
+
console.log(
|
|
113185
|
+
` ${c.dim("Click the Present control (or press P) to open the audience display.")}`
|
|
113186
|
+
);
|
|
113187
|
+
console.log(
|
|
113188
|
+
` ${c.dim('Google Meet: share the AUDIENCE tab ("Share screen \u2192 A tab"), not a window or your whole screen.')}`
|
|
113189
|
+
);
|
|
113190
|
+
console.log(
|
|
113191
|
+
` ${c.dim("Zoom desktop: drag the audience tab into its own window and share that window (keep it at least partly visible).")}`
|
|
113192
|
+
);
|
|
113114
113193
|
console.log(` ${c.dim("Press Ctrl+C to stop")}`);
|
|
113115
113194
|
console.log();
|
|
113116
113195
|
if (args.open) {
|
|
@@ -113129,7 +113208,7 @@ var init_present = __esm({
|
|
|
113129
113208
|
|
|
113130
113209
|
// src/utils/publishProject.ts
|
|
113131
113210
|
import { basename as basename11, dirname as dirname27, join as join64, posix as posix4, relative as relative13, resolve as resolve39 } from "path";
|
|
113132
|
-
import { existsSync as existsSync61, readdirSync as readdirSync23, readFileSync as readFileSync38, statSync as
|
|
113211
|
+
import { existsSync as existsSync61, readdirSync as readdirSync23, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
|
|
113133
113212
|
import AdmZip from "adm-zip";
|
|
113134
113213
|
function isRecord3(value) {
|
|
113135
113214
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -113236,7 +113315,7 @@ function collectProjectFiles(rootDir, currentDir, paths) {
|
|
|
113236
113315
|
collectProjectFiles(rootDir, absolutePath, paths);
|
|
113237
113316
|
continue;
|
|
113238
113317
|
}
|
|
113239
|
-
if (!
|
|
113318
|
+
if (!statSync19(absolutePath).isFile()) continue;
|
|
113240
113319
|
paths.push(relativePath);
|
|
113241
113320
|
}
|
|
113242
113321
|
}
|
|
@@ -113263,7 +113342,7 @@ function tryResolveExternal(ctx, rawPath, referrerAbsDir) {
|
|
|
113263
113342
|
const absPath = resolve39(referrerAbsDir, rawPath);
|
|
113264
113343
|
if (isPathInside(absPath, ctx.absProjectDir)) return null;
|
|
113265
113344
|
try {
|
|
113266
|
-
if (!existsSync61(absPath) || !
|
|
113345
|
+
if (!existsSync61(absPath) || !statSync19(absPath).isFile()) return null;
|
|
113267
113346
|
} catch {
|
|
113268
113347
|
return null;
|
|
113269
113348
|
}
|
|
@@ -114292,7 +114371,7 @@ __export(batchRender_exports, {
|
|
|
114292
114371
|
resolveOutputTemplate: () => resolveOutputTemplate,
|
|
114293
114372
|
runBatchRender: () => runBatchRender
|
|
114294
114373
|
});
|
|
114295
|
-
import { mkdirSync as
|
|
114374
|
+
import { mkdirSync as mkdirSync33, readFileSync as readFileSync40, writeFileSync as writeFileSync21 } from "fs";
|
|
114296
114375
|
import { dirname as dirname28, join as join66, resolve as resolve43, sep as sep8 } from "path";
|
|
114297
114376
|
function isRecord4(value) {
|
|
114298
114377
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -114477,7 +114556,7 @@ function summarizeManifest(manifest) {
|
|
|
114477
114556
|
}
|
|
114478
114557
|
function writeManifest(manifest) {
|
|
114479
114558
|
summarizeManifest(manifest);
|
|
114480
|
-
|
|
114559
|
+
mkdirSync33(dirname28(manifest.manifestPath), { recursive: true });
|
|
114481
114560
|
writeFileSync21(manifest.manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
114482
114561
|
}
|
|
114483
114562
|
function emitJsonEvent(event, json) {
|
|
@@ -114499,7 +114578,7 @@ async function renderBatchRow(row, manifest, options) {
|
|
|
114499
114578
|
console.log(c.dim(`Batch row ${row.index}: ${row.outputPath}`));
|
|
114500
114579
|
}
|
|
114501
114580
|
try {
|
|
114502
|
-
|
|
114581
|
+
mkdirSync33(dirname28(row.outputPath), { recursive: true });
|
|
114503
114582
|
const result = await options.renderOne(row);
|
|
114504
114583
|
manifestRow.status = "completed";
|
|
114505
114584
|
manifestRow.durationMs = result.durationMs ?? null;
|
|
@@ -114640,7 +114719,7 @@ __export(render_exports, {
|
|
|
114640
114719
|
renderLocal: () => renderLocal,
|
|
114641
114720
|
resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
|
|
114642
114721
|
});
|
|
114643
|
-
import { mkdirSync as
|
|
114722
|
+
import { mkdirSync as mkdirSync34, readdirSync as readdirSync24, readFileSync as readFileSync41, statSync as statSync20, writeFileSync as writeFileSync23, rmSync as rmSync17 } from "fs";
|
|
114644
114723
|
import { cpus as cpus4, freemem as freemem5, tmpdir as tmpdir5 } from "os";
|
|
114645
114724
|
import { resolve as resolve44, dirname as dirname29, join as join67, basename as basename12 } from "path";
|
|
114646
114725
|
import { execFileSync as execFileSync9, spawn as spawn14 } from "child_process";
|
|
@@ -114706,7 +114785,7 @@ function resolveDockerfilePath() {
|
|
|
114706
114785
|
const devPath = resolve44(__dirname, "..", "src", "docker", "Dockerfile.render");
|
|
114707
114786
|
for (const p2 of [builtPath, devPath]) {
|
|
114708
114787
|
try {
|
|
114709
|
-
|
|
114788
|
+
statSync20(p2);
|
|
114710
114789
|
return p2;
|
|
114711
114790
|
} catch {
|
|
114712
114791
|
continue;
|
|
@@ -114735,7 +114814,7 @@ function ensureDockerImage(version2, platform10, quiet) {
|
|
|
114735
114814
|
if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform10})...`));
|
|
114736
114815
|
const dockerfilePath = resolveDockerfilePath();
|
|
114737
114816
|
const tmpDir = join67(tmpdir5(), `hyperframes-docker-${Date.now()}`);
|
|
114738
|
-
|
|
114817
|
+
mkdirSync34(tmpDir, { recursive: true });
|
|
114739
114818
|
writeFileSync23(join67(tmpDir, "Dockerfile"), readFileSync41(dockerfilePath));
|
|
114740
114819
|
const targetArch = platform10 === "linux/arm64" ? "arm64" : "amd64";
|
|
114741
114820
|
try {
|
|
@@ -115133,14 +115212,14 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
|
|
|
115133
115212
|
let fileSize = "unknown";
|
|
115134
115213
|
let isDirectory = false;
|
|
115135
115214
|
try {
|
|
115136
|
-
const stat3 =
|
|
115215
|
+
const stat3 = statSync20(outputPath);
|
|
115137
115216
|
isDirectory = stat3.isDirectory();
|
|
115138
115217
|
if (stat3.isDirectory()) {
|
|
115139
115218
|
let total = 0;
|
|
115140
115219
|
for (const entry of readdirSync24(outputPath, { withFileTypes: true })) {
|
|
115141
115220
|
if (!entry.isFile()) continue;
|
|
115142
115221
|
try {
|
|
115143
|
-
total +=
|
|
115222
|
+
total += statSync20(join67(outputPath, entry.name)).size;
|
|
115144
115223
|
} catch {
|
|
115145
115224
|
}
|
|
115146
115225
|
}
|
|
@@ -115560,7 +115639,7 @@ var init_render = __esm({
|
|
|
115560
115639
|
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
|
115561
115640
|
const batchOutputTemplate = args.output ? args.output : join67(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
|
|
115562
115641
|
const outputPath = args.output ? resolve44(args.output) : join67(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
|
|
115563
|
-
if (!batchPath)
|
|
115642
|
+
if (!batchPath) mkdirSync34(dirname29(outputPath), { recursive: true });
|
|
115564
115643
|
const useDocker = args.docker ?? false;
|
|
115565
115644
|
const useGpu = args.gpu ?? false;
|
|
115566
115645
|
const browserGpuArg = args["browser-gpu"];
|
|
@@ -115618,7 +115697,7 @@ var init_render = __esm({
|
|
|
115618
115697
|
console.log(c.warn(" GIF output is capped at 30fps. Use --fps 15 for smaller files."));
|
|
115619
115698
|
}
|
|
115620
115699
|
const pageNavigationTimeoutMs = resolveBrowserTimeoutMsArg(args["browser-timeout"]);
|
|
115621
|
-
const entryFile = resolveCompositionEntryArg(args.composition, project.dir,
|
|
115700
|
+
const entryFile = resolveCompositionEntryArg(args.composition, project.dir, statSync20);
|
|
115622
115701
|
let batchModule;
|
|
115623
115702
|
let preparedBatch;
|
|
115624
115703
|
if (batchPath) {
|
|
@@ -116171,7 +116250,7 @@ __export(beats_exports, {
|
|
|
116171
116250
|
default: () => beats_default,
|
|
116172
116251
|
examples: () => examples11
|
|
116173
116252
|
});
|
|
116174
|
-
import { existsSync as existsSync66, readFileSync as readFileSync44, mkdirSync as
|
|
116253
|
+
import { existsSync as existsSync66, readFileSync as readFileSync44, mkdirSync as mkdirSync35, writeFileSync as writeFileSync24 } from "fs";
|
|
116175
116254
|
import { resolve as resolve45, join as join69, dirname as dirname31 } from "path";
|
|
116176
116255
|
function fail(message) {
|
|
116177
116256
|
console.error(c.error(message));
|
|
@@ -116243,7 +116322,7 @@ var init_beats2 = __esm({
|
|
|
116243
116322
|
fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
|
|
116244
116323
|
}
|
|
116245
116324
|
const outPath = join69(project.dir, "beats", `${rel}.json`);
|
|
116246
|
-
|
|
116325
|
+
mkdirSync35(dirname31(outPath), { recursive: true });
|
|
116247
116326
|
writeFileSync24(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
|
|
116248
116327
|
report(`beats/${rel}.json`, result, Boolean(args.json));
|
|
116249
116328
|
}
|
|
@@ -116257,10 +116336,10 @@ __export(staticProjectServer_exports, {
|
|
|
116257
116336
|
serveStaticProjectHtml: () => serveStaticProjectHtml
|
|
116258
116337
|
});
|
|
116259
116338
|
import { createServer } from "http";
|
|
116260
|
-
import { createReadStream as createReadStream3, existsSync as existsSync67, statSync as
|
|
116339
|
+
import { createReadStream as createReadStream3, existsSync as existsSync67, statSync as statSync21 } from "fs";
|
|
116261
116340
|
import { isAbsolute as isAbsolute13, relative as relative14, resolve as resolve46 } from "path";
|
|
116262
116341
|
function serveFileWithRange(filePath, rangeHeader, res) {
|
|
116263
|
-
const size =
|
|
116342
|
+
const size = statSync21(filePath).size;
|
|
116264
116343
|
const headers = {
|
|
116265
116344
|
"Content-Type": getMimeType(filePath),
|
|
116266
116345
|
"Accept-Ranges": "bytes"
|
|
@@ -119459,7 +119538,7 @@ __export(keyframes_exports, {
|
|
|
119459
119538
|
examples: () => examples14,
|
|
119460
119539
|
surfaceComposition: () => surfaceComposition
|
|
119461
119540
|
});
|
|
119462
|
-
import { existsSync as existsSync70, readFileSync as readFileSync47, statSync as
|
|
119541
|
+
import { existsSync as existsSync70, readFileSync as readFileSync47, statSync as statSync23 } from "fs";
|
|
119463
119542
|
import { resolve as resolve47, dirname as dirname33, basename as basename14 } from "path";
|
|
119464
119543
|
function inlineScriptText(html) {
|
|
119465
119544
|
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
@@ -119941,7 +120020,7 @@ function resolveScope(args) {
|
|
|
119941
120020
|
let comps;
|
|
119942
120021
|
let projectName;
|
|
119943
120022
|
let projectDir;
|
|
119944
|
-
if (raw && raw.endsWith(".html") && existsSync70(raw) &&
|
|
120023
|
+
if (raw && raw.endsWith(".html") && existsSync70(raw) && statSync23(raw).isFile()) {
|
|
119945
120024
|
comps = [surfaceComposition(readFileSync47(raw, "utf-8"), basename14(raw), raw)];
|
|
119946
120025
|
projectName = basename14(raw);
|
|
119947
120026
|
projectDir = dirname33(raw);
|
|
@@ -120151,7 +120230,7 @@ __export(info_exports, {
|
|
|
120151
120230
|
examples: () => examples15,
|
|
120152
120231
|
orientation: () => orientation
|
|
120153
120232
|
});
|
|
120154
|
-
import { readFileSync as readFileSync48, readdirSync as readdirSync26, statSync as
|
|
120233
|
+
import { readFileSync as readFileSync48, readdirSync as readdirSync26, statSync as statSync24 } from "fs";
|
|
120155
120234
|
import { join as join73 } from "path";
|
|
120156
120235
|
function orientation(width, height) {
|
|
120157
120236
|
if (width > height) return "landscape";
|
|
@@ -120170,7 +120249,7 @@ function totalSize(dir) {
|
|
|
120170
120249
|
if (entry.isDirectory()) {
|
|
120171
120250
|
total += totalSize(path2);
|
|
120172
120251
|
} else {
|
|
120173
|
-
total +=
|
|
120252
|
+
total += statSync24(path2).size;
|
|
120174
120253
|
}
|
|
120175
120254
|
}
|
|
120176
120255
|
return total;
|
|
@@ -120433,7 +120512,7 @@ __export(benchmark_exports, {
|
|
|
120433
120512
|
default: () => benchmark_default,
|
|
120434
120513
|
examples: () => examples17
|
|
120435
120514
|
});
|
|
120436
|
-
import { existsSync as existsSync73, statSync as
|
|
120515
|
+
import { existsSync as existsSync73, statSync as statSync25 } from "fs";
|
|
120437
120516
|
import { resolve as resolve49, join as join74 } from "path";
|
|
120438
120517
|
var examples17, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
|
|
120439
120518
|
var init_benchmark = __esm({
|
|
@@ -120527,7 +120606,7 @@ var init_benchmark = __esm({
|
|
|
120527
120606
|
const elapsedMs = Date.now() - startTime;
|
|
120528
120607
|
let fileSize = null;
|
|
120529
120608
|
if (existsSync73(outputPath)) {
|
|
120530
|
-
const stat3 =
|
|
120609
|
+
const stat3 = statSync25(outputPath);
|
|
120531
120610
|
fileSize = stat3.size;
|
|
120532
120611
|
}
|
|
120533
120612
|
runs.push({ elapsedMs, fileSize });
|
|
@@ -120784,7 +120863,7 @@ __export(manager_exports3, {
|
|
|
120784
120863
|
modelPath: () => modelPath,
|
|
120785
120864
|
selectProviders: () => selectProviders
|
|
120786
120865
|
});
|
|
120787
|
-
import { existsSync as existsSync74, mkdirSync as
|
|
120866
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync36 } from "fs";
|
|
120788
120867
|
import { homedir as homedir11, platform as platform8, arch } from "os";
|
|
120789
120868
|
import { join as join75 } from "path";
|
|
120790
120869
|
function isDevice(value) {
|
|
@@ -120831,7 +120910,7 @@ function modelPath(model = DEFAULT_MODEL2) {
|
|
|
120831
120910
|
async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
120832
120911
|
const dest = modelPath(model);
|
|
120833
120912
|
if (existsSync74(dest)) return dest;
|
|
120834
|
-
|
|
120913
|
+
mkdirSync36(MODELS_DIR2, { recursive: true });
|
|
120835
120914
|
options?.onProgress?.(`Downloading ${model} weights (~168 MB)...`);
|
|
120836
120915
|
await downloadFile(MODEL_URLS[model], dest);
|
|
120837
120916
|
if (!existsSync74(dest)) {
|
|
@@ -121783,7 +121862,7 @@ var init_transcribe2 = __esm({
|
|
|
121783
121862
|
});
|
|
121784
121863
|
|
|
121785
121864
|
// src/tts/manager.ts
|
|
121786
|
-
import { existsSync as existsSync77, mkdirSync as
|
|
121865
|
+
import { existsSync as existsSync77, mkdirSync as mkdirSync37 } from "fs";
|
|
121787
121866
|
import { homedir as homedir12 } from "os";
|
|
121788
121867
|
import { join as join77 } from "path";
|
|
121789
121868
|
function inferLangFromVoiceId(voiceId) {
|
|
@@ -121802,7 +121881,7 @@ async function ensureModel3(model = DEFAULT_MODEL3, options) {
|
|
|
121802
121881
|
`Unknown TTS model: ${model}. Available: ${Object.keys(MODEL_URLS2).join(", ")}`
|
|
121803
121882
|
);
|
|
121804
121883
|
}
|
|
121805
|
-
|
|
121884
|
+
mkdirSync37(MODELS_DIR3, { recursive: true });
|
|
121806
121885
|
options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
|
|
121807
121886
|
await downloadFile(url, modelPath2);
|
|
121808
121887
|
if (!existsSync77(modelPath2)) {
|
|
@@ -121813,7 +121892,7 @@ async function ensureModel3(model = DEFAULT_MODEL3, options) {
|
|
|
121813
121892
|
async function ensureVoices(options) {
|
|
121814
121893
|
const voicesPath = join77(VOICES_DIR, "voices-v1.0.bin");
|
|
121815
121894
|
if (existsSync77(voicesPath)) return voicesPath;
|
|
121816
|
-
|
|
121895
|
+
mkdirSync37(VOICES_DIR, { recursive: true });
|
|
121817
121896
|
options?.onProgress?.("Downloading voice data (~27 MB)...");
|
|
121818
121897
|
await downloadFile(VOICES_URL, voicesPath);
|
|
121819
121898
|
if (!existsSync77(voicesPath)) {
|
|
@@ -121945,12 +122024,12 @@ __export(synthesize_exports, {
|
|
|
121945
122024
|
synthesize: () => synthesize
|
|
121946
122025
|
});
|
|
121947
122026
|
import { execFileSync as execFileSync11 } from "child_process";
|
|
121948
|
-
import { existsSync as existsSync78, writeFileSync as writeFileSync27, mkdirSync as
|
|
122027
|
+
import { existsSync as existsSync78, writeFileSync as writeFileSync27, mkdirSync as mkdirSync38, readdirSync as readdirSync27, unlinkSync as unlinkSync5 } from "fs";
|
|
121949
122028
|
import { join as join78, dirname as dirname36, basename as basename15 } from "path";
|
|
121950
122029
|
import { homedir as homedir13 } from "os";
|
|
121951
122030
|
function ensureSynthScript() {
|
|
121952
122031
|
if (!existsSync78(SCRIPT_PATH)) {
|
|
121953
|
-
|
|
122032
|
+
mkdirSync38(SCRIPT_DIR, { recursive: true });
|
|
121954
122033
|
writeFileSync27(SCRIPT_PATH, SYNTH_SCRIPT);
|
|
121955
122034
|
const currentName = basename15(SCRIPT_PATH);
|
|
121956
122035
|
try {
|
|
@@ -121991,7 +122070,7 @@ async function synthesize(text2, outputPath, options) {
|
|
|
121991
122070
|
ensureVoices({ onProgress: options?.onProgress })
|
|
121992
122071
|
]);
|
|
121993
122072
|
const scriptPath = ensureSynthScript();
|
|
121994
|
-
|
|
122073
|
+
mkdirSync38(dirname36(outputPath), { recursive: true });
|
|
121995
122074
|
options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
|
|
121996
122075
|
try {
|
|
121997
122076
|
const stdout2 = execFileSync11(
|
|
@@ -123211,6 +123290,7 @@ var validate_exports = {};
|
|
|
123211
123290
|
__export(validate_exports, {
|
|
123212
123291
|
default: () => validate_default,
|
|
123213
123292
|
extractCompositionErrorsFromLint: () => extractCompositionErrorsFromLint,
|
|
123293
|
+
raceMediaReady: () => raceMediaReady,
|
|
123214
123294
|
shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
|
|
123215
123295
|
});
|
|
123216
123296
|
import { existsSync as existsSync81, readFileSync as readFileSync53 } from "fs";
|
|
@@ -123247,13 +123327,49 @@ async function seekTo2(page, time) {
|
|
|
123247
123327
|
}, time);
|
|
123248
123328
|
await new Promise((r2) => setTimeout(r2, SEEK_SETTLE_MS2));
|
|
123249
123329
|
}
|
|
123250
|
-
|
|
123251
|
-
|
|
123330
|
+
function raceMediaReady(el, deadlineMs) {
|
|
123331
|
+
if (Number.isFinite(el.duration) && el.duration > 0) return Promise.resolve();
|
|
123332
|
+
return new Promise((resolve62) => {
|
|
123333
|
+
const onReady = () => {
|
|
123334
|
+
el.removeEventListener("loadedmetadata", onReady);
|
|
123335
|
+
el.removeEventListener("error", onReady);
|
|
123336
|
+
clearTimeout(timer);
|
|
123337
|
+
resolve62();
|
|
123338
|
+
};
|
|
123339
|
+
el.addEventListener("loadedmetadata", onReady, { once: true });
|
|
123340
|
+
el.addEventListener("error", onReady, { once: true });
|
|
123341
|
+
const timer = setTimeout(onReady, Math.max(0, deadlineMs - Date.now()));
|
|
123342
|
+
});
|
|
123343
|
+
}
|
|
123344
|
+
async function auditClipDurations(page, analyzeClipMediaFit2, extraWaitMs) {
|
|
123345
|
+
const clips = await page.evaluate(async (maxWaitMs) => {
|
|
123346
|
+
const nodes = Array.from(
|
|
123347
|
+
document.querySelectorAll("video[data-duration], audio[data-duration]")
|
|
123348
|
+
);
|
|
123349
|
+
const deadline = Date.now() + maxWaitMs;
|
|
123350
|
+
await Promise.all(
|
|
123351
|
+
nodes.map((el) => {
|
|
123352
|
+
if (Number.isFinite(el.duration) && el.duration > 0) return Promise.resolve();
|
|
123353
|
+
return new Promise((resolve62) => {
|
|
123354
|
+
const cleanup = () => {
|
|
123355
|
+
el.removeEventListener("loadedmetadata", onReady);
|
|
123356
|
+
el.removeEventListener("error", onReady);
|
|
123357
|
+
clearTimeout(timer);
|
|
123358
|
+
};
|
|
123359
|
+
const onReady = () => {
|
|
123360
|
+
cleanup();
|
|
123361
|
+
resolve62();
|
|
123362
|
+
};
|
|
123363
|
+
el.addEventListener("loadedmetadata", onReady, { once: true });
|
|
123364
|
+
el.addEventListener("error", onReady, { once: true });
|
|
123365
|
+
const timer = setTimeout(onReady, Math.max(0, deadline - Date.now()));
|
|
123366
|
+
});
|
|
123367
|
+
})
|
|
123368
|
+
);
|
|
123252
123369
|
const rows = [];
|
|
123253
|
-
|
|
123254
|
-
const el = node;
|
|
123370
|
+
for (const el of nodes) {
|
|
123255
123371
|
const slot = parseFloat(el.getAttribute("data-duration") ?? "");
|
|
123256
|
-
if (!(slot > 0))
|
|
123372
|
+
if (!(slot > 0)) continue;
|
|
123257
123373
|
rows.push({
|
|
123258
123374
|
id: el.id || el.getAttribute("src") || `(${el.tagName.toLowerCase()})`,
|
|
123259
123375
|
kind: el.tagName === "AUDIO" ? "Audio" : "Video",
|
|
@@ -123262,9 +123378,9 @@ async function auditClipDurations(page, analyzeClipMediaFit2) {
|
|
|
123262
123378
|
duration: el.duration,
|
|
123263
123379
|
loop: el.loop || el.getAttribute("data-loop") === "true"
|
|
123264
123380
|
});
|
|
123265
|
-
}
|
|
123381
|
+
}
|
|
123266
123382
|
return rows;
|
|
123267
|
-
});
|
|
123383
|
+
}, extraWaitMs);
|
|
123268
123384
|
const warnings = [];
|
|
123269
123385
|
const unreadable = [];
|
|
123270
123386
|
for (const clip of clips) {
|
|
@@ -123383,7 +123499,7 @@ async function validateInBrowser(project, opts) {
|
|
|
123383
123499
|
});
|
|
123384
123500
|
await page.goto(server.url, { waitUntil: "domcontentloaded", timeout: 1e4 });
|
|
123385
123501
|
await new Promise((r2) => setTimeout(r2, opts.timeout ?? 3e3));
|
|
123386
|
-
for (const w3 of await auditClipDurations(page, analyzeClipMediaFit2)) {
|
|
123502
|
+
for (const w3 of await auditClipDurations(page, analyzeClipMediaFit2, opts.timeout ?? 3e3)) {
|
|
123387
123503
|
warnings.push(w3);
|
|
123388
123504
|
}
|
|
123389
123505
|
if (opts.contrast) {
|
|
@@ -129885,7 +130001,7 @@ var require_node_domexception = __commonJS({
|
|
|
129885
130001
|
});
|
|
129886
130002
|
|
|
129887
130003
|
// ../../node_modules/.bun/fetch-blob@3.2.0/node_modules/fetch-blob/from.js
|
|
129888
|
-
import { statSync as
|
|
130004
|
+
import { statSync as statSync26, createReadStream as createReadStream4, promises as fs2 } from "fs";
|
|
129889
130005
|
import { basename as basename17 } from "path";
|
|
129890
130006
|
var import_node_domexception, stat, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
|
|
129891
130007
|
var init_from = __esm({
|
|
@@ -129895,10 +130011,10 @@ var init_from = __esm({
|
|
|
129895
130011
|
init_file();
|
|
129896
130012
|
init_fetch_blob();
|
|
129897
130013
|
({ stat } = fs2);
|
|
129898
|
-
blobFromSync = (path2, type) => fromBlob(
|
|
130014
|
+
blobFromSync = (path2, type) => fromBlob(statSync26(path2), path2, type);
|
|
129899
130015
|
blobFrom = (path2, type) => stat(path2).then((stat3) => fromBlob(stat3, path2, type));
|
|
129900
130016
|
fileFrom = (path2, type) => stat(path2).then((stat3) => fromFile(stat3, path2, type));
|
|
129901
|
-
fileFromSync = (path2, type) => fromFile(
|
|
130017
|
+
fileFromSync = (path2, type) => fromFile(statSync26(path2), path2, type);
|
|
129902
130018
|
fromBlob = (stat3, path2, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
129903
130019
|
path: path2,
|
|
129904
130020
|
size: stat3.size,
|
|
@@ -143689,7 +143805,7 @@ var require_websocket = __commonJS({
|
|
|
143689
143805
|
var http4 = __require("http");
|
|
143690
143806
|
var net2 = __require("net");
|
|
143691
143807
|
var tls = __require("tls");
|
|
143692
|
-
var { randomBytes: randomBytes4, createHash:
|
|
143808
|
+
var { randomBytes: randomBytes4, createHash: createHash15 } = __require("crypto");
|
|
143693
143809
|
var { Duplex, Readable: Readable4 } = __require("stream");
|
|
143694
143810
|
var { URL: URL2 } = __require("url");
|
|
143695
143811
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -144349,7 +144465,7 @@ var require_websocket = __commonJS({
|
|
|
144349
144465
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
144350
144466
|
return;
|
|
144351
144467
|
}
|
|
144352
|
-
const digest =
|
|
144468
|
+
const digest = createHash15("sha1").update(key2 + GUID).digest("base64");
|
|
144353
144469
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
144354
144470
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
144355
144471
|
return;
|
|
@@ -144716,7 +144832,7 @@ var require_websocket_server = __commonJS({
|
|
|
144716
144832
|
var EventEmitter = __require("events");
|
|
144717
144833
|
var http4 = __require("http");
|
|
144718
144834
|
var { Duplex } = __require("stream");
|
|
144719
|
-
var { createHash:
|
|
144835
|
+
var { createHash: createHash15 } = __require("crypto");
|
|
144720
144836
|
var extension2 = require_extension();
|
|
144721
144837
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
144722
144838
|
var subprotocol2 = require_subprotocol();
|
|
@@ -145017,7 +145133,7 @@ var require_websocket_server = __commonJS({
|
|
|
145017
145133
|
);
|
|
145018
145134
|
}
|
|
145019
145135
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
145020
|
-
const digest =
|
|
145136
|
+
const digest = createHash15("sha1").update(key2 + GUID).digest("base64");
|
|
145021
145137
|
const headers = [
|
|
145022
145138
|
"HTTP/1.1 101 Switching Protocols",
|
|
145023
145139
|
"Upgrade: websocket",
|
|
@@ -156052,7 +156168,7 @@ async function uploadBlobInternal(file, uploadUrl, apiClient, httpOptions) {
|
|
|
156052
156168
|
break;
|
|
156053
156169
|
}
|
|
156054
156170
|
retryCount++;
|
|
156055
|
-
await
|
|
156171
|
+
await sleep2(currentDelayMs);
|
|
156056
156172
|
currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;
|
|
156057
156173
|
}
|
|
156058
156174
|
offset2 += chunkSize;
|
|
@@ -156069,7 +156185,7 @@ async function getBlobStat(file) {
|
|
|
156069
156185
|
const fileStat = { size: file.size, type: file.type };
|
|
156070
156186
|
return fileStat;
|
|
156071
156187
|
}
|
|
156072
|
-
function
|
|
156188
|
+
function sleep2(ms) {
|
|
156073
156189
|
return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
|
|
156074
156190
|
}
|
|
156075
156191
|
function resolveCloudFlag(options) {
|
|
@@ -163294,7 +163410,7 @@ ${underline2}`);
|
|
|
163294
163410
|
break;
|
|
163295
163411
|
}
|
|
163296
163412
|
retryCount++;
|
|
163297
|
-
await
|
|
163413
|
+
await sleep2(currentDelayMs);
|
|
163298
163414
|
currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;
|
|
163299
163415
|
}
|
|
163300
163416
|
offset2 += bytesRead;
|
|
@@ -163465,7 +163581,7 @@ __export(snapshot_exports, {
|
|
|
163465
163581
|
tailFrameTime: () => tailFrameTime
|
|
163466
163582
|
});
|
|
163467
163583
|
import { spawn as spawn16 } from "child_process";
|
|
163468
|
-
import { existsSync as existsSync84, mkdtempSync as mkdtempSync5, readFileSync as readFileSync55, mkdirSync as
|
|
163584
|
+
import { existsSync as existsSync84, mkdtempSync as mkdtempSync5, readFileSync as readFileSync55, mkdirSync as mkdirSync39, rmSync as rmSync18, writeFileSync as writeFileSync29 } from "fs";
|
|
163469
163585
|
import { tmpdir as tmpdir6 } from "os";
|
|
163470
163586
|
import { resolve as resolve55, join as join83, relative as relative15, isAbsolute as isAbsolute14, basename as basename19 } from "path";
|
|
163471
163587
|
function orbitStageSource() {
|
|
@@ -163667,7 +163783,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
163667
163783
|
}
|
|
163668
163784
|
const cameraExpr = opts.angle && (opts.angle.yaw !== 0 || opts.angle.pitch !== 0) ? `(${orbitStageSource()})(${JSON.stringify(opts.angle)})` : null;
|
|
163669
163785
|
const snapshotDir = opts.outputDir ?? join83(projectDir, "snapshots");
|
|
163670
|
-
|
|
163786
|
+
mkdirSync39(snapshotDir, { recursive: true });
|
|
163671
163787
|
try {
|
|
163672
163788
|
const { readdirSync: readdirSync35 } = await import("fs");
|
|
163673
163789
|
for (const file of readdirSync35(snapshotDir)) {
|
|
@@ -163997,7 +164113,7 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
|
163997
164113
|
});
|
|
163998
164114
|
|
|
163999
164115
|
// src/capture/assetDownloader.ts
|
|
164000
|
-
import { writeFileSync as writeFileSync30, mkdirSync as
|
|
164116
|
+
import { writeFileSync as writeFileSync30, mkdirSync as mkdirSync40 } from "fs";
|
|
164001
164117
|
import { join as join84, extname as extname15 } from "path";
|
|
164002
164118
|
import { createHash as createHash12 } from "crypto";
|
|
164003
164119
|
function svgContentHashSlug(svgSource, isLogo) {
|
|
@@ -164006,10 +164122,10 @@ function svgContentHashSlug(svgSource, isLogo) {
|
|
|
164006
164122
|
}
|
|
164007
164123
|
async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
|
|
164008
164124
|
const assetsDir = join84(outputDir, "assets");
|
|
164009
|
-
|
|
164125
|
+
mkdirSync40(assetsDir, { recursive: true });
|
|
164010
164126
|
const assets = [];
|
|
164011
164127
|
const downloadedUrls = /* @__PURE__ */ new Set();
|
|
164012
|
-
|
|
164128
|
+
mkdirSync40(join84(outputDir, "assets", "svgs"), { recursive: true });
|
|
164013
164129
|
const usedSvgNames = /* @__PURE__ */ new Set();
|
|
164014
164130
|
for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
|
|
164015
164131
|
const svg = tokens.svgs[i2];
|
|
@@ -164140,7 +164256,7 @@ function normalizeUrl(u) {
|
|
|
164140
164256
|
}
|
|
164141
164257
|
async function downloadAndRewriteFonts(css, outputDir) {
|
|
164142
164258
|
const assetsDir = join84(outputDir, "assets", "fonts");
|
|
164143
|
-
|
|
164259
|
+
mkdirSync40(assetsDir, { recursive: true });
|
|
164144
164260
|
const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
|
|
164145
164261
|
const fontUrls = /* @__PURE__ */ new Set();
|
|
164146
164262
|
let match;
|
|
@@ -164333,7 +164449,7 @@ __export(video_exports, {
|
|
|
164333
164449
|
runVideoMode: () => runVideoMode,
|
|
164334
164450
|
safeFilename: () => safeFilename
|
|
164335
164451
|
});
|
|
164336
|
-
import { createWriteStream as createWriteStream4, existsSync as existsSync85, mkdirSync as
|
|
164452
|
+
import { createWriteStream as createWriteStream4, existsSync as existsSync85, mkdirSync as mkdirSync41, readFileSync as readFileSync56, unlinkSync as unlinkSync7 } from "fs";
|
|
164337
164453
|
import { resolve as resolve56, join as join85, basename as basename20 } from "path";
|
|
164338
164454
|
async function streamToFile(url, destPath) {
|
|
164339
164455
|
const r2 = await safeFetch(url, {
|
|
@@ -164509,7 +164625,7 @@ async function runVideoMode(args) {
|
|
|
164509
164625
|
return;
|
|
164510
164626
|
}
|
|
164511
164627
|
const outDir = isW2hLayout ? join85(projectDir, "capture", "assets", "videos") : join85(projectDir, "assets", "videos");
|
|
164512
|
-
|
|
164628
|
+
mkdirSync41(outDir, { recursive: true });
|
|
164513
164629
|
const fname = safeFilename(entry.filename || basename20(entry.url));
|
|
164514
164630
|
const outPath = join85(outDir, fname);
|
|
164515
164631
|
const relPath = isW2hLayout ? `capture/assets/videos/${fname}` : `assets/videos/${fname}`;
|
|
@@ -165280,7 +165396,8 @@ var init_designStyleExtractor = __esm({
|
|
|
165280
165396
|
function rgbToHex(color) {
|
|
165281
165397
|
if (!color) return "";
|
|
165282
165398
|
if (color.startsWith('#')) return color.toUpperCase();
|
|
165283
|
-
|
|
165399
|
+
// capture optional alpha (group 4), allowing both comma and modern slash (rgb r g b / a) syntax.
|
|
165400
|
+
var m = color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*[,/]\\s*([\\d.]+))?/);
|
|
165284
165401
|
if (!m) return color;
|
|
165285
165402
|
// fully-transparent fill (rgba(...,0)) \u2192 sentinel, NOT #000000 \u2014 otherwise a transparent
|
|
165286
165403
|
// chip/tab/stat ground reads as solid black on a light-ground site.
|
|
@@ -165292,8 +165409,15 @@ var init_designStyleExtractor = __esm({
|
|
|
165292
165409
|
return f.split(",")[0].replace(/['"]/g, "").trim();
|
|
165293
165410
|
}
|
|
165294
165411
|
|
|
165412
|
+
// keep only gradient background-images (drop url() sprites + "none"); gradients are a core
|
|
165413
|
+
// brand signal (Stripe/ElevenLabs/Snowflake mesh washes) that a flat background-color misses.
|
|
165414
|
+
function gradientOf(v) {
|
|
165415
|
+
return v && v.indexOf("gradient") >= 0 ? v.trim() : "";
|
|
165416
|
+
}
|
|
165417
|
+
|
|
165295
165418
|
function getStyles(el) {
|
|
165296
165419
|
var s = getComputedStyle(el);
|
|
165420
|
+
var bf = s.backdropFilter || s.webkitBackdropFilter || "";
|
|
165297
165421
|
return {
|
|
165298
165422
|
fontFamily: cleanFont(s.fontFamily),
|
|
165299
165423
|
fontSize: s.fontSize,
|
|
@@ -165302,6 +165426,8 @@ var init_designStyleExtractor = __esm({
|
|
|
165302
165426
|
letterSpacing: s.letterSpacing,
|
|
165303
165427
|
color: rgbToHex(s.color),
|
|
165304
165428
|
background: rgbToHex(s.backgroundColor),
|
|
165429
|
+
backgroundImage: gradientOf(s.backgroundImage),
|
|
165430
|
+
backdropFilter: bf === "none" ? "" : bf,
|
|
165305
165431
|
padding: s.padding,
|
|
165306
165432
|
borderRadius: s.borderRadius,
|
|
165307
165433
|
border: s.border,
|
|
@@ -165370,23 +165496,37 @@ var init_designStyleExtractor = __esm({
|
|
|
165370
165496
|
}
|
|
165371
165497
|
|
|
165372
165498
|
// \u2500\u2500 2. Buttons \u2500\u2500
|
|
165499
|
+
// a page's primary CTA is very often a FILLED pill in the nav/header ("Sign up", "Start for free").
|
|
165500
|
+
// Old code dropped everything under <nav>, losing that CTA; keep nav elements that carry a solid
|
|
165501
|
+
// fill (a real button), still dropping plain nav text links.
|
|
165502
|
+
var isFilledEl = (el) => {
|
|
165503
|
+
var cs = getComputedStyle(el);
|
|
165504
|
+
var bg = cs.backgroundColor;
|
|
165505
|
+
var solid = !!bg && bg !== "transparent" && !/rgba?\\([^)]*,\\s*0\\s*\\)/.test(bg);
|
|
165506
|
+
// a gradient-filled CTA (e.g. Snowflake's blue pill = background: var(--ui-background-03)) has a
|
|
165507
|
+
// transparent background-COLOR but a gradient background-IMAGE \u2014 count it as filled too.
|
|
165508
|
+
return solid || (cs.backgroundImage || "").indexOf("gradient") >= 0;
|
|
165509
|
+
};
|
|
165373
165510
|
var buttonEls = Array.from(document.querySelectorAll(
|
|
165374
165511
|
'button, a[class*="btn"], a[class*="button"], a[role="button"], ' +
|
|
165375
165512
|
'[class*="btn-"], [class*="button-"], [class*="cta"]'
|
|
165376
165513
|
)).filter(function(el) {
|
|
165377
|
-
|
|
165378
|
-
|
|
165514
|
+
if (!isVisible(el)) return false;
|
|
165515
|
+
return el.closest('nav, [role="navigation"]') ? isFilledEl(el) : true;
|
|
165516
|
+
}).slice(0, 16);
|
|
165379
165517
|
|
|
165380
165518
|
var buttonMap = {};
|
|
165381
165519
|
for (var bi = 0; bi < buttonEls.length; bi++) {
|
|
165382
165520
|
var bs = getStyles(buttonEls[bi]);
|
|
165383
|
-
// Deduplicate by visual appearance
|
|
165384
|
-
var bKey = bs.background + "|" + bs.borderRadius + "|" + bs.border;
|
|
165521
|
+
// Deduplicate by visual appearance (gradient fill kept distinct so a gradient CTA survives)
|
|
165522
|
+
var bKey = bs.background + "|" + bs.backgroundImage + "|" + bs.borderRadius + "|" + bs.border;
|
|
165385
165523
|
if (!buttonMap[bKey]) {
|
|
165386
165524
|
var btnText = (buttonEls[bi].textContent || "").trim().slice(0, 40);
|
|
165387
165525
|
buttonMap[bKey] = {
|
|
165388
165526
|
label: btnText || "button",
|
|
165389
165527
|
background: bs.background,
|
|
165528
|
+
backgroundImage: bs.backgroundImage,
|
|
165529
|
+
backdropFilter: bs.backdropFilter,
|
|
165390
165530
|
color: bs.color,
|
|
165391
165531
|
padding: bs.padding,
|
|
165392
165532
|
borderRadius: bs.borderRadius,
|
|
@@ -165398,7 +165538,7 @@ var init_designStyleExtractor = __esm({
|
|
|
165398
165538
|
};
|
|
165399
165539
|
}
|
|
165400
165540
|
}
|
|
165401
|
-
var buttons = Object.values(buttonMap).slice(0,
|
|
165541
|
+
var buttons = Object.values(buttonMap).slice(0, 6);
|
|
165402
165542
|
|
|
165403
165543
|
// \u2500\u2500 3. Cards / containers \u2500\u2500
|
|
165404
165544
|
var cardEls = Array.from(document.querySelectorAll(
|
|
@@ -165413,11 +165553,14 @@ var init_designStyleExtractor = __esm({
|
|
|
165413
165553
|
var cardMap = {};
|
|
165414
165554
|
for (var ci = 0; ci < cardEls.length; ci++) {
|
|
165415
165555
|
var cs = getStyles(cardEls[ci]);
|
|
165416
|
-
|
|
165556
|
+
// gradient fill + glass blur kept in the key so a gradient/frosted card is a distinct variant
|
|
165557
|
+
var cKey = cs.background + "|" + cs.backgroundImage + "|" + cs.backdropFilter + "|" + cs.borderRadius + "|" + cs.border;
|
|
165417
165558
|
if (!cardMap[cKey]) {
|
|
165418
165559
|
cardMap[cKey] = {
|
|
165419
165560
|
label: "card",
|
|
165420
165561
|
background: cs.background,
|
|
165562
|
+
backgroundImage: cs.backgroundImage,
|
|
165563
|
+
backdropFilter: cs.backdropFilter,
|
|
165421
165564
|
color: cs.color,
|
|
165422
165565
|
padding: cs.padding,
|
|
165423
165566
|
borderRadius: cs.borderRadius,
|
|
@@ -165439,6 +165582,8 @@ var init_designStyleExtractor = __esm({
|
|
|
165439
165582
|
nav = {
|
|
165440
165583
|
label: "navigation",
|
|
165441
165584
|
background: ns.background,
|
|
165585
|
+
backgroundImage: ns.backgroundImage,
|
|
165586
|
+
backdropFilter: ns.backdropFilter,
|
|
165442
165587
|
color: ns.color,
|
|
165443
165588
|
padding: ns.padding,
|
|
165444
165589
|
borderRadius: ns.borderRadius,
|
|
@@ -165622,6 +165767,90 @@ var init_designStyleExtractor = __esm({
|
|
|
165622
165767
|
.slice(0, 5)
|
|
165623
165768
|
.map(function(e) { return { value: e[0], count: e[1] }; });
|
|
165624
165769
|
|
|
165770
|
+
// \u2500\u2500 8. Dominant gradient / mesh backgrounds \u2500\u2500
|
|
165771
|
+
// A site's signature color wash (Stripe/ElevenLabs/Snowflake) lives in gradient background-images
|
|
165772
|
+
// on large blocks \u2014 often on a pseudo-element (::before glow orbs) rather than the block itself.
|
|
165773
|
+
// Weight each distinct gradient by the total on-screen area it covers; return the top few.
|
|
165774
|
+
var gradientArea = {};
|
|
165775
|
+
var gradSamples = Array.from(document.querySelectorAll(
|
|
165776
|
+
"body, main, section, header, div, [class*='hero'], [class*='gradient'], [class*='bg'], [class*='background']"
|
|
165777
|
+
)).slice(0, 400);
|
|
165778
|
+
|
|
165779
|
+
// max stop chroma (max\u2212min RGB) of a gradient: a vivid brand wash scores high, a neutral
|
|
165780
|
+
// white/cream scrim ~0. Used to rank washes so a small vivid gradient beats a big grey scrim.
|
|
165781
|
+
function gradientChroma(g) {
|
|
165782
|
+
var max = 0, re = /rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/g, m;
|
|
165783
|
+
while ((m = re.exec(g))) {
|
|
165784
|
+
var r = +m[1], gr = +m[2], b = +m[3];
|
|
165785
|
+
var c = Math.max(r, gr, b) - Math.min(r, gr, b);
|
|
165786
|
+
if (c > max) max = c;
|
|
165787
|
+
}
|
|
165788
|
+
return max;
|
|
165789
|
+
}
|
|
165790
|
+
|
|
165791
|
+
function addGradient(val, area) {
|
|
165792
|
+
var g = gradientOf(val);
|
|
165793
|
+
if (!g || area < 20000) return; // ignore tiny decorative gradients
|
|
165794
|
+
var norm = g.replace(/\\s+/g, " ");
|
|
165795
|
+
gradientArea[norm] = (gradientArea[norm] || 0) + area;
|
|
165796
|
+
}
|
|
165797
|
+
|
|
165798
|
+
for (var gi = 0; gi < gradSamples.length; gi++) {
|
|
165799
|
+
var gel = gradSamples[gi];
|
|
165800
|
+
if (!isVisible(gel)) continue;
|
|
165801
|
+
var grect = gel.getBoundingClientRect();
|
|
165802
|
+
var garea = grect.width * grect.height;
|
|
165803
|
+
if (garea < 20000) continue;
|
|
165804
|
+
addGradient(getComputedStyle(gel).backgroundImage, garea);
|
|
165805
|
+
addGradient(getComputedStyle(gel, "::before").backgroundImage, garea);
|
|
165806
|
+
addGradient(getComputedStyle(gel, "::after").backgroundImage, garea);
|
|
165807
|
+
}
|
|
165808
|
+
|
|
165809
|
+
// rank by chroma-weighted area so the brand's signature color wash outranks a larger neutral scrim
|
|
165810
|
+
var backgrounds = Object.entries(gradientArea)
|
|
165811
|
+
.map(function(e) { return { value: e[0], area: Math.round(e[1]), score: e[1] * (1 + 2 * gradientChroma(e[0]) / 255) }; })
|
|
165812
|
+
.sort(function(a, b) { return b.score - a.score; })
|
|
165813
|
+
.slice(0, 6)
|
|
165814
|
+
.map(function(e) { return { value: e.value, area: e.area }; });
|
|
165815
|
+
|
|
165816
|
+
// \u2500\u2500 9. Frosted-glass panels (backdrop-filter) \u2500\u2500
|
|
165817
|
+
// A defining material on modern hero UIs (HeyGen's prompt box, Stripe's floating chrome): a
|
|
165818
|
+
// translucent surface with a backdrop blur. Capture the RAW fill (rgba/gradient \u2014 alpha preserved,
|
|
165819
|
+
// unlike rgbToHex) + the blur, ranked by area. This is what lets a frame render a real frosted card.
|
|
165820
|
+
var glassSamples = Array.from(document.querySelectorAll(
|
|
165821
|
+
"div, section, header, nav, aside, [class*='card'], [class*='panel'], [class*='glass'], [class*='blur'], [class*='modal'], [class*='overlay'], [class*='input']"
|
|
165822
|
+
)).slice(0, 400);
|
|
165823
|
+
var glassByKey = {};
|
|
165824
|
+
for (var qi = 0; qi < glassSamples.length; qi++) {
|
|
165825
|
+
var qel = glassSamples[qi];
|
|
165826
|
+
if (!isVisible(qel)) continue;
|
|
165827
|
+
var qs = getComputedStyle(qel);
|
|
165828
|
+
var bf = qs.backdropFilter || qs.webkitBackdropFilter || "";
|
|
165829
|
+
if (!bf || bf === "none" || bf.indexOf("blur") < 0) continue;
|
|
165830
|
+
var qrect = qel.getBoundingClientRect();
|
|
165831
|
+
var qarea = qrect.width * qrect.height;
|
|
165832
|
+
if (qarea < 8000) continue; // ignore tiny blurred chips
|
|
165833
|
+
// raw fill with alpha intact: prefer a translucent gradient, else the rgba background-color
|
|
165834
|
+
var gi2 = qs.backgroundImage;
|
|
165835
|
+
var rawFill = gi2 && gi2.indexOf("gradient") >= 0 ? gi2.replace(/\\s+/g, " ").trim() : qs.backgroundColor;
|
|
165836
|
+
var key = bf + "|" + rawFill + "|" + qs.borderRadius;
|
|
165837
|
+
if (!glassByKey[key]) {
|
|
165838
|
+
glassByKey[key] = {
|
|
165839
|
+
backdropFilter: bf,
|
|
165840
|
+
background: rawFill,
|
|
165841
|
+
border: qs.border,
|
|
165842
|
+
borderRadius: qs.borderRadius,
|
|
165843
|
+
boxShadow: qs.boxShadow === "none" ? "" : qs.boxShadow,
|
|
165844
|
+
area: 0
|
|
165845
|
+
};
|
|
165846
|
+
}
|
|
165847
|
+
glassByKey[key].area += qarea;
|
|
165848
|
+
}
|
|
165849
|
+
var glass = Object.values(glassByKey)
|
|
165850
|
+
.sort(function(a, b) { return b.area - a.area; })
|
|
165851
|
+
.slice(0, 3)
|
|
165852
|
+
.map(function(g) { return { backdropFilter: g.backdropFilter, background: g.background, border: g.border, borderRadius: g.borderRadius, boxShadow: g.boxShadow, area: Math.round(g.area) }; });
|
|
165853
|
+
|
|
165625
165854
|
return {
|
|
165626
165855
|
typography: uniqueTypo,
|
|
165627
165856
|
spacing: { observed: observedSpacing.slice(0, 15), baseUnit: baseUnit },
|
|
@@ -165632,7 +165861,9 @@ var init_designStyleExtractor = __esm({
|
|
|
165632
165861
|
nav: nav,
|
|
165633
165862
|
chips: chips,
|
|
165634
165863
|
statCells: statCells,
|
|
165635
|
-
tabs: tabs
|
|
165864
|
+
tabs: tabs,
|
|
165865
|
+
backgrounds: backgrounds,
|
|
165866
|
+
glass: glass
|
|
165636
165867
|
};
|
|
165637
165868
|
})()`;
|
|
165638
165869
|
}
|
|
@@ -165962,7 +166193,7 @@ var init_animationCataloger = __esm({
|
|
|
165962
166193
|
});
|
|
165963
166194
|
|
|
165964
166195
|
// src/capture/mediaCapture.ts
|
|
165965
|
-
import { mkdirSync as
|
|
166196
|
+
import { mkdirSync as mkdirSync43, writeFileSync as writeFileSync33, readdirSync as readdirSync30, readFileSync as readFileSync58, statSync as statSync27 } from "fs";
|
|
165966
166197
|
import { join as join87, extname as extname16 } from "path";
|
|
165967
166198
|
async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
165968
166199
|
let savedCount = 0;
|
|
@@ -166024,7 +166255,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
166024
166255
|
async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
166025
166256
|
const manifest = [];
|
|
166026
166257
|
const previewDir = join87(lottieDir, "previews");
|
|
166027
|
-
|
|
166258
|
+
mkdirSync43(previewDir, { recursive: true });
|
|
166028
166259
|
for (const file of readdirSync30(lottieDir)) {
|
|
166029
166260
|
if (!file.endsWith(".json")) continue;
|
|
166030
166261
|
try {
|
|
@@ -166032,7 +166263,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
166032
166263
|
const fr = raw.fr || 30;
|
|
166033
166264
|
const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
|
|
166034
166265
|
const previewName = file.replace(".json", "-preview.png");
|
|
166035
|
-
const fileSize =
|
|
166266
|
+
const fileSize = statSync27(join87(lottieDir, file)).size;
|
|
166036
166267
|
if (fileSize > 2e6) continue;
|
|
166037
166268
|
let previewPage;
|
|
166038
166269
|
try {
|
|
@@ -166190,9 +166421,9 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
|
|
|
166190
166421
|
const merged = [...byKey.values()];
|
|
166191
166422
|
if (merged.length === 0) return;
|
|
166192
166423
|
const videoManifestDir = join87(outputDir, "assets", "videos");
|
|
166193
|
-
|
|
166424
|
+
mkdirSync43(videoManifestDir, { recursive: true });
|
|
166194
166425
|
const previewDir = join87(videoManifestDir, "previews");
|
|
166195
|
-
|
|
166426
|
+
mkdirSync43(previewDir, { recursive: true });
|
|
166196
166427
|
const videoManifest = [];
|
|
166197
166428
|
const dlStart = Date.now();
|
|
166198
166429
|
for (let vi = 0; vi < merged.length && vi < 20; vi++) {
|
|
@@ -166314,7 +166545,7 @@ var init_mediaCapture = __esm({
|
|
|
166314
166545
|
});
|
|
166315
166546
|
|
|
166316
166547
|
// src/capture/contentExtractor.ts
|
|
166317
|
-
import { existsSync as existsSync87, readdirSync as readdirSync31, statSync as
|
|
166548
|
+
import { existsSync as existsSync87, readdirSync as readdirSync31, statSync as statSync28, readFileSync as readFileSync59 } from "fs";
|
|
166318
166549
|
import { basename as basename21, join as join88 } from "path";
|
|
166319
166550
|
async function detectLibraries(page, capturedShaders) {
|
|
166320
166551
|
let detectedLibraries = [];
|
|
@@ -166491,7 +166722,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
166491
166722
|
const results = await Promise.allSettled(
|
|
166492
166723
|
batch.map(async (file) => {
|
|
166493
166724
|
const filePath = join88(outputDir, "assets", file);
|
|
166494
|
-
const stat3 =
|
|
166725
|
+
const stat3 = statSync28(filePath);
|
|
166495
166726
|
if (stat3.size > 4e6) return { file, caption: "" };
|
|
166496
166727
|
const buffer = readFileSync59(filePath);
|
|
166497
166728
|
const base64 = buffer.toString("base64");
|
|
@@ -166615,7 +166846,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
166615
166846
|
for (const file of readdirSync31(assetsPath)) {
|
|
166616
166847
|
if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
|
|
166617
166848
|
const filePath = join88(assetsPath, file);
|
|
166618
|
-
const stat3 =
|
|
166849
|
+
const stat3 = statSync28(filePath);
|
|
166619
166850
|
if (!stat3.isFile()) continue;
|
|
166620
166851
|
const sizeKb = Math.round(stat3.size / 1024);
|
|
166621
166852
|
const catalogMatch = catalogedAssets.find(
|
|
@@ -166898,11 +167129,11 @@ var screenshotCapture_exports = {};
|
|
|
166898
167129
|
__export(screenshotCapture_exports, {
|
|
166899
167130
|
captureScrollScreenshots: () => captureScrollScreenshots
|
|
166900
167131
|
});
|
|
166901
|
-
import { writeFileSync as writeFileSync36, mkdirSync as
|
|
167132
|
+
import { writeFileSync as writeFileSync36, mkdirSync as mkdirSync44 } from "fs";
|
|
166902
167133
|
import { join as join91 } from "path";
|
|
166903
167134
|
async function captureScrollScreenshots(page, outputDir) {
|
|
166904
167135
|
const screenshotsDir = join91(outputDir, "screenshots");
|
|
166905
|
-
|
|
167136
|
+
mkdirSync44(screenshotsDir, { recursive: true });
|
|
166906
167137
|
const MAX_SCREENSHOTS = 20;
|
|
166907
167138
|
const filePaths = [];
|
|
166908
167139
|
try {
|
|
@@ -167342,7 +167573,7 @@ var capture_exports = {};
|
|
|
167342
167573
|
__export(capture_exports, {
|
|
167343
167574
|
captureWebsite: () => captureWebsite
|
|
167344
167575
|
});
|
|
167345
|
-
import { mkdirSync as
|
|
167576
|
+
import { mkdirSync as mkdirSync45, writeFileSync as writeFileSync37, existsSync as existsSync90 } from "fs";
|
|
167346
167577
|
import { join as join93 } from "path";
|
|
167347
167578
|
async function captureWebsite(opts, onProgress) {
|
|
167348
167579
|
const {
|
|
@@ -167360,9 +167591,9 @@ async function captureWebsite(opts, onProgress) {
|
|
|
167360
167591
|
onProgress?.(stage, detail);
|
|
167361
167592
|
};
|
|
167362
167593
|
loadEnvFile(outputDir);
|
|
167363
|
-
|
|
167364
|
-
|
|
167365
|
-
|
|
167594
|
+
mkdirSync45(join93(outputDir, "extracted"), { recursive: true });
|
|
167595
|
+
mkdirSync45(join93(outputDir, "screenshots"), { recursive: true });
|
|
167596
|
+
mkdirSync45(join93(outputDir, "assets"), { recursive: true });
|
|
167366
167597
|
progress("browser", "Launching headless Chrome...");
|
|
167367
167598
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
167368
167599
|
const browser = await ensureBrowser2();
|
|
@@ -167523,7 +167754,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
167523
167754
|
}
|
|
167524
167755
|
if (discoveredLotties.length > 0) {
|
|
167525
167756
|
const lottieDir = join93(outputDir, "assets", "lottie");
|
|
167526
|
-
|
|
167757
|
+
mkdirSync45(lottieDir, { recursive: true });
|
|
167527
167758
|
const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
|
|
167528
167759
|
if (savedCount > 0) {
|
|
167529
167760
|
await renderLottiePreviews(chromeBrowser, lottieDir, outputDir);
|
|
@@ -168025,8 +168256,8 @@ var init_capture2 = __esm({
|
|
|
168025
168256
|
} catch (err) {
|
|
168026
168257
|
const errMsg = normalizeErrorMessage(err);
|
|
168027
168258
|
try {
|
|
168028
|
-
const { mkdirSync:
|
|
168029
|
-
|
|
168259
|
+
const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync40 } = await import("fs");
|
|
168260
|
+
mkdirSync50(outputDir, { recursive: true });
|
|
168030
168261
|
const isTimeout = /timeout|timed out/i.test(errMsg);
|
|
168031
168262
|
const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
|
|
168032
168263
|
writeFileSync40(
|
|
@@ -168072,14 +168303,14 @@ __export(state_exports, {
|
|
|
168072
168303
|
stateFilePath: () => stateFilePath,
|
|
168073
168304
|
writeStackOutputs: () => writeStackOutputs
|
|
168074
168305
|
});
|
|
168075
|
-
import { existsSync as existsSync91, mkdirSync as
|
|
168306
|
+
import { existsSync as existsSync91, mkdirSync as mkdirSync46, readdirSync as readdirSync34, readFileSync as readFileSync61, rmSync as rmSync19, writeFileSync as writeFileSync38 } from "fs";
|
|
168076
168307
|
import { dirname as dirname40, join as join94 } from "path";
|
|
168077
168308
|
function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
|
|
168078
168309
|
return join94(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
|
|
168079
168310
|
}
|
|
168080
168311
|
function writeStackOutputs(outputs, cwd = process.cwd()) {
|
|
168081
168312
|
const path2 = stateFilePath(outputs.stackName, cwd);
|
|
168082
|
-
|
|
168313
|
+
mkdirSync46(dirname40(path2), { recursive: true });
|
|
168083
168314
|
writeFileSync38(path2, JSON.stringify(outputs, null, 2) + "\n");
|
|
168084
168315
|
return path2;
|
|
168085
168316
|
}
|
|
@@ -168563,10 +168794,10 @@ async function waitForCompletion(executionArn, stack, intervalMs, json) {
|
|
|
168563
168794
|
}
|
|
168564
168795
|
return;
|
|
168565
168796
|
}
|
|
168566
|
-
await
|
|
168797
|
+
await sleep3(intervalMs);
|
|
168567
168798
|
}
|
|
168568
168799
|
}
|
|
168569
|
-
function
|
|
168800
|
+
function sleep3(ms) {
|
|
168570
168801
|
return new Promise((res) => setTimeout(res, ms));
|
|
168571
168802
|
}
|
|
168572
168803
|
var init_render2 = __esm({
|
|
@@ -169632,7 +169863,7 @@ __export(cloudrun_exports, {
|
|
|
169632
169863
|
});
|
|
169633
169864
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
169634
169865
|
import { createRequire as createRequire4 } from "module";
|
|
169635
|
-
import { existsSync as existsSync97, mkdirSync as
|
|
169866
|
+
import { existsSync as existsSync97, mkdirSync as mkdirSync47, readFileSync as readFileSync66, writeFileSync as writeFileSync39 } from "fs";
|
|
169636
169867
|
import { homedir as homedir14 } from "os";
|
|
169637
169868
|
import { dirname as dirname42, join as join100, resolve as resolve61 } from "path";
|
|
169638
169869
|
function stateDir() {
|
|
@@ -169642,7 +169873,7 @@ function statePath() {
|
|
|
169642
169873
|
return join100(stateDir(), "cloudrun-state.json");
|
|
169643
169874
|
}
|
|
169644
169875
|
function writeState(state) {
|
|
169645
|
-
|
|
169876
|
+
mkdirSync47(stateDir(), { recursive: true });
|
|
169646
169877
|
writeFileSync39(statePath(), JSON.stringify(state, null, 2));
|
|
169647
169878
|
}
|
|
169648
169879
|
function readState(args) {
|
|
@@ -169805,7 +170036,7 @@ function findRepoRoot(tfDir) {
|
|
|
169805
170036
|
}
|
|
169806
170037
|
function writeCloudBuildConfig(image) {
|
|
169807
170038
|
const cfgPath = join100(stateDir(), "cloudrun-cloudbuild.yaml");
|
|
169808
|
-
|
|
170039
|
+
mkdirSync47(stateDir(), { recursive: true });
|
|
169809
170040
|
writeFileSync39(
|
|
169810
170041
|
cfgPath,
|
|
169811
170042
|
[
|
|
@@ -170380,7 +170611,7 @@ async function pollUntilTerminal(client, renderId, options = {}) {
|
|
|
170380
170611
|
const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
170381
170612
|
const maxWaitMs = options.maxWaitMs ?? DEFAULT_MAX_WAIT_MS;
|
|
170382
170613
|
const now = options.now ?? (() => Date.now());
|
|
170383
|
-
const
|
|
170614
|
+
const sleep5 = options.sleep ?? defaultAbortableSleep(options.signal);
|
|
170384
170615
|
const started = now();
|
|
170385
170616
|
while (true) {
|
|
170386
170617
|
if (options.signal?.aborted) {
|
|
@@ -170395,7 +170626,7 @@ async function pollUntilTerminal(client, renderId, options = {}) {
|
|
|
170395
170626
|
if (elapsed >= maxWaitMs) {
|
|
170396
170627
|
throw new PollTimeoutError(detail, elapsed);
|
|
170397
170628
|
}
|
|
170398
|
-
await
|
|
170629
|
+
await sleep5(intervalMs);
|
|
170399
170630
|
}
|
|
170400
170631
|
}
|
|
170401
170632
|
function signalAbortError(signal) {
|
|
@@ -170436,7 +170667,7 @@ var init_poll = __esm({
|
|
|
170436
170667
|
});
|
|
170437
170668
|
|
|
170438
170669
|
// src/cloud/download.ts
|
|
170439
|
-
import { createWriteStream as createWriteStream5, mkdirSync as
|
|
170670
|
+
import { createWriteStream as createWriteStream5, mkdirSync as mkdirSync48, unlinkSync as unlinkSync8 } from "fs";
|
|
170440
170671
|
import { dirname as dirname43 } from "path";
|
|
170441
170672
|
async function downloadToFile(url, destPath, options = {}) {
|
|
170442
170673
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
@@ -170447,7 +170678,7 @@ async function downloadToFile(url, destPath, options = {}) {
|
|
|
170447
170678
|
if (!res.body) {
|
|
170448
170679
|
throw new Error(`Failed to download ${url}: empty response body`);
|
|
170449
170680
|
}
|
|
170450
|
-
|
|
170681
|
+
mkdirSync48(dirname43(destPath), { recursive: true });
|
|
170451
170682
|
const totalHeader = res.headers.get("content-length");
|
|
170452
170683
|
const total = totalHeader ? Number.parseInt(totalHeader, 10) : void 0;
|
|
170453
170684
|
const totalOpt = total !== void 0 && Number.isFinite(total) ? total : void 0;
|
|
@@ -170653,6 +170884,33 @@ var init_client2 = __esm({
|
|
|
170653
170884
|
signal: args.signal
|
|
170654
170885
|
});
|
|
170655
170886
|
}
|
|
170887
|
+
/**
|
|
170888
|
+
* Create Asset Upload
|
|
170889
|
+
*
|
|
170890
|
+
* Begin a direct-to-S3 upload. Returns an asset_id and a presigned upload_url; PUT the file bytes to upload_url, then call POST /v3/assets/{asset_id}/complete. Unlike POST /v3/assets (which proxies the bytes), this never sends the file through the API.
|
|
170891
|
+
*/
|
|
170892
|
+
async createAssetUpload(args) {
|
|
170893
|
+
return await this.request({
|
|
170894
|
+
method: "POST",
|
|
170895
|
+
path: "/v3/assets/direct-uploads",
|
|
170896
|
+
body: args.body,
|
|
170897
|
+
idempotencyKey: args.idempotencyKey,
|
|
170898
|
+
signal: args.signal
|
|
170899
|
+
});
|
|
170900
|
+
}
|
|
170901
|
+
/**
|
|
170902
|
+
* Complete Asset Upload
|
|
170903
|
+
*
|
|
170904
|
+
* Finalize a direct-to-S3 upload into a reusable asset. Call after the upload PUT returns 200. Idempotent: repeated calls return the same finalized asset.
|
|
170905
|
+
*/
|
|
170906
|
+
async completeAssetUpload(args) {
|
|
170907
|
+
return await this.request({
|
|
170908
|
+
method: "POST",
|
|
170909
|
+
path: `/v3/assets/${encodeURIComponent(args.asset_id)}/complete`,
|
|
170910
|
+
body: args.body,
|
|
170911
|
+
signal: args.signal
|
|
170912
|
+
});
|
|
170913
|
+
}
|
|
170656
170914
|
/**
|
|
170657
170915
|
* Create HyperFrames Render
|
|
170658
170916
|
*
|
|
@@ -171782,7 +172040,7 @@ var init_errors2 = __esm({
|
|
|
171782
172040
|
init_format();
|
|
171783
172041
|
init_client2();
|
|
171784
172042
|
ERROR_CODE_HINTS = {
|
|
171785
|
-
hyperframes_project_too_large: "The zip exceeded the
|
|
172043
|
+
hyperframes_project_too_large: "The zip exceeded the 200 MB limit. Trim large media (or pre-host them and reference by URL), then try again.",
|
|
171786
172044
|
hyperframes_render_not_found: "The render_id no longer exists \u2014 either soft-deleted or never created.",
|
|
171787
172045
|
invalid_parameter: "Check the listed parameter against `hyperframes cloud render --help` for the accepted values.",
|
|
171788
172046
|
authentication_failed: "Run `hyperframes auth status` to confirm your credential; `hyperframes auth login` to re-auth.",
|
|
@@ -171848,6 +172106,91 @@ var init_parsing = __esm({
|
|
|
171848
172106
|
}
|
|
171849
172107
|
});
|
|
171850
172108
|
|
|
172109
|
+
// src/cloud/upload.ts
|
|
172110
|
+
import { createHash as createHash14 } from "crypto";
|
|
172111
|
+
function sha256Hex2(bytes) {
|
|
172112
|
+
return createHash14("sha256").update(bytes).digest("hex");
|
|
172113
|
+
}
|
|
172114
|
+
function sleep4(ms) {
|
|
172115
|
+
return new Promise((r2) => setTimeout(r2, ms));
|
|
172116
|
+
}
|
|
172117
|
+
function normalizeUploadHeaders(raw) {
|
|
172118
|
+
const out = {};
|
|
172119
|
+
for (const [k2, v2] of Object.entries(raw ?? {})) {
|
|
172120
|
+
if (typeof v2 === "string") out[k2] = v2;
|
|
172121
|
+
else if (typeof v2 === "number" || typeof v2 === "boolean") out[k2] = String(v2);
|
|
172122
|
+
}
|
|
172123
|
+
return out;
|
|
172124
|
+
}
|
|
172125
|
+
async function putBytesToPresignedUrl(fetchImpl, uploadUrl, uploadHeaders, bytes) {
|
|
172126
|
+
const headers = {
|
|
172127
|
+
"content-type": CONTENT_TYPE_ZIP,
|
|
172128
|
+
...normalizeUploadHeaders(uploadHeaders)
|
|
172129
|
+
};
|
|
172130
|
+
const res = await fetchImpl(uploadUrl, {
|
|
172131
|
+
method: "PUT",
|
|
172132
|
+
headers,
|
|
172133
|
+
body: bytes
|
|
172134
|
+
});
|
|
172135
|
+
if (!res.ok) {
|
|
172136
|
+
const detail = await res.text().catch(() => "");
|
|
172137
|
+
throw new Error(
|
|
172138
|
+
`Direct upload PUT failed: ${res.status} ${res.statusText}${detail ? ` \u2014 ${detail.slice(0, 300)}` : ""}`
|
|
172139
|
+
);
|
|
172140
|
+
}
|
|
172141
|
+
}
|
|
172142
|
+
async function completeWithRetry(client, asset_id, checksum_sha256) {
|
|
172143
|
+
let lastErr;
|
|
172144
|
+
for (let attempt = 0; attempt < COMPLETE_MAX_RETRIES; attempt++) {
|
|
172145
|
+
try {
|
|
172146
|
+
return await client.completeAssetUpload({
|
|
172147
|
+
asset_id,
|
|
172148
|
+
body: { checksum_sha256 }
|
|
172149
|
+
});
|
|
172150
|
+
} catch (err) {
|
|
172151
|
+
const retryable = err instanceof HyperframesApiError && err.status === 409;
|
|
172152
|
+
if (!retryable || attempt === COMPLETE_MAX_RETRIES - 1) {
|
|
172153
|
+
throw err;
|
|
172154
|
+
}
|
|
172155
|
+
lastErr = err;
|
|
172156
|
+
await sleep4(COMPLETE_RETRY_BASE_MS * (attempt + 1));
|
|
172157
|
+
}
|
|
172158
|
+
}
|
|
172159
|
+
throw lastErr ?? new Error("completeAssetUpload retries exhausted");
|
|
172160
|
+
}
|
|
172161
|
+
async function uploadZipViaDirectUpload(opts) {
|
|
172162
|
+
const start = Date.now();
|
|
172163
|
+
const { bytes, filename, idempotencyKey } = opts;
|
|
172164
|
+
const size_bytes = bytes.byteLength;
|
|
172165
|
+
const checksum_sha256 = sha256Hex2(bytes);
|
|
172166
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
172167
|
+
opts.onProgress?.({ phase: "initialize" });
|
|
172168
|
+
const initialize = await opts.client.createAssetUpload({
|
|
172169
|
+
body: { filename, content_type: CONTENT_TYPE_ZIP, size_bytes, checksum_sha256 },
|
|
172170
|
+
idempotencyKey
|
|
172171
|
+
});
|
|
172172
|
+
opts.onProgress?.({ phase: "upload", percent: 0 });
|
|
172173
|
+
await putBytesToPresignedUrl(fetchImpl, initialize.upload_url, initialize.upload_headers, bytes);
|
|
172174
|
+
opts.onProgress?.({ phase: "upload", percent: 100 });
|
|
172175
|
+
opts.onProgress?.({ phase: "complete" });
|
|
172176
|
+
const completed = await completeWithRetry(opts.client, initialize.asset_id, checksum_sha256);
|
|
172177
|
+
return {
|
|
172178
|
+
asset_id: completed.asset_id,
|
|
172179
|
+
size_bytes,
|
|
172180
|
+
duration_ms: Date.now() - start
|
|
172181
|
+
};
|
|
172182
|
+
}
|
|
172183
|
+
var COMPLETE_MAX_RETRIES, COMPLETE_RETRY_BASE_MS, CONTENT_TYPE_ZIP;
|
|
172184
|
+
var init_upload = __esm({
|
|
172185
|
+
"src/cloud/upload.ts"() {
|
|
172186
|
+
"use strict";
|
|
172187
|
+
init_client2();
|
|
172188
|
+
COMPLETE_MAX_RETRIES = 5;
|
|
172189
|
+
COMPLETE_RETRY_BASE_MS = 500;
|
|
172190
|
+
CONTENT_TYPE_ZIP = "application/zip";
|
|
172191
|
+
}
|
|
172192
|
+
});
|
|
172193
|
+
|
|
171851
172194
|
// src/cloud/statusColor.ts
|
|
171852
172195
|
function colorStatus(status) {
|
|
171853
172196
|
switch (status) {
|
|
@@ -172008,22 +172351,25 @@ async function maybeUploadProject(client, source, asJson, idempotencyKey) {
|
|
|
172008
172351
|
}
|
|
172009
172352
|
if (!asJson) {
|
|
172010
172353
|
console.log("");
|
|
172011
|
-
console.log(`${c.accent("\u25C6")} Uploading to
|
|
172354
|
+
console.log(`${c.accent("\u25C6")} Uploading (direct-to-S3)`);
|
|
172012
172355
|
}
|
|
172013
172356
|
const uploadStart = Date.now();
|
|
172014
172357
|
let uploaded;
|
|
172015
172358
|
try {
|
|
172016
|
-
uploaded = await
|
|
172017
|
-
|
|
172359
|
+
uploaded = await uploadZipViaDirectUpload({
|
|
172360
|
+
client,
|
|
172361
|
+
bytes: archive.buffer,
|
|
172018
172362
|
filename: `${project.name}.zip`,
|
|
172019
|
-
|
|
172020
|
-
|
|
172021
|
-
|
|
172022
|
-
|
|
172023
|
-
|
|
172024
|
-
|
|
172025
|
-
|
|
172026
|
-
|
|
172363
|
+
idempotencyKey,
|
|
172364
|
+
onProgress: !asJson ? (ev) => {
|
|
172365
|
+
if (ev.phase === "initialize") {
|
|
172366
|
+
console.log(c.dim(` initializing\u2026`));
|
|
172367
|
+
} else if (ev.phase === "upload" && ev.percent === 0) {
|
|
172368
|
+
console.log(c.dim(` uploading to S3\u2026`));
|
|
172369
|
+
} else if (ev.phase === "complete") {
|
|
172370
|
+
console.log(c.dim(` finalizing\u2026`));
|
|
172371
|
+
}
|
|
172372
|
+
} : void 0
|
|
172027
172373
|
});
|
|
172028
172374
|
} catch (err) {
|
|
172029
172375
|
reportApiError("Upload failed", err);
|
|
@@ -172160,6 +172506,7 @@ var init_render3 = __esm({
|
|
|
172160
172506
|
init_cloud();
|
|
172161
172507
|
init_errors2();
|
|
172162
172508
|
init_parsing();
|
|
172509
|
+
init_upload();
|
|
172163
172510
|
init_statusColor();
|
|
172164
172511
|
VALID_QUALITY2 = ["draft", "standard", "high"];
|
|
172165
172512
|
VALID_FORMAT2 = ["mp4", "webm", "mov"];
|
|
@@ -173600,7 +173947,7 @@ __export(autoUpdate_exports, {
|
|
|
173600
173947
|
scheduleBackgroundInstall: () => scheduleBackgroundInstall
|
|
173601
173948
|
});
|
|
173602
173949
|
import { spawn as spawn17 } from "child_process";
|
|
173603
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
173950
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync49, openSync as openSync3 } from "fs";
|
|
173604
173951
|
import { homedir as homedir16 } from "os";
|
|
173605
173952
|
import { join as join103 } from "path";
|
|
173606
173953
|
import { compareVersions as compareVersions3 } from "compare-versions";
|
|
@@ -173617,14 +173964,14 @@ function majorOf(version2) {
|
|
|
173617
173964
|
}
|
|
173618
173965
|
function log(line2) {
|
|
173619
173966
|
try {
|
|
173620
|
-
|
|
173967
|
+
mkdirSync49(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
173621
173968
|
appendFileSync2(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} ${line2}
|
|
173622
173969
|
`, { mode: 384 });
|
|
173623
173970
|
} catch {
|
|
173624
173971
|
}
|
|
173625
173972
|
}
|
|
173626
173973
|
function launchDetachedInstall(installCommand, version2) {
|
|
173627
|
-
|
|
173974
|
+
mkdirSync49(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
173628
173975
|
const configFile = join103(CONFIG_DIR2, "config.json");
|
|
173629
173976
|
const nodeScript = `
|
|
173630
173977
|
const { exec } = require("node:child_process");
|