hyperframes 0.4.38 → 0.5.0-alpha.10
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 +765 -524
- package/dist/skills/hyperframes/SKILL.md +29 -80
- package/dist/skills/hyperframes/house-style.md +1 -3
- package/dist/skills/hyperframes/references/motion-principles.md +0 -73
- package/dist/skills/hyperframes/visual-styles.md +107 -339
- package/dist/studio/assets/index-DKaNgV2Z.css +1 -0
- package/dist/studio/assets/index-peNJzL-4.js +105 -0
- package/dist/studio/index.html +2 -2
- package/package.json +1 -1
- package/dist/skills/hyperframes/references/beat-direction.md +0 -102
- package/dist/skills/hyperframes/references/design-picker.md +0 -117
- package/dist/skills/hyperframes/references/narration.md +0 -92
- package/dist/skills/hyperframes/references/prompt-expansion.md +0 -68
- package/dist/skills/hyperframes/references/techniques.md +0 -387
- package/dist/skills/hyperframes/references/video-composition.md +0 -62
- package/dist/skills/hyperframes/templates/design-picker.html +0 -1432
- package/dist/studio/assets/index-18P_dZeo.js +0 -93
- package/dist/studio/assets/index-BLrgRQSu.css +0 -1
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ var VERSION;
|
|
|
54
54
|
var init_version = __esm({
|
|
55
55
|
"src/version.ts"() {
|
|
56
56
|
"use strict";
|
|
57
|
-
VERSION = true ? "0.
|
|
57
|
+
VERSION = true ? "0.5.0-alpha.10" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -5486,7 +5486,7 @@ var init_captions = __esm({
|
|
|
5486
5486
|
const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(
|
|
5487
5487
|
content
|
|
5488
5488
|
);
|
|
5489
|
-
const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /
|
|
5489
|
+
const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /karaoke|caption[-_]?(?:group|word|line|block)|cg-/.test(content);
|
|
5490
5490
|
if (hasCaptionLoop && hasExitTween && !hasHardKill) {
|
|
5491
5491
|
findings.push({
|
|
5492
5492
|
code: "caption_exit_missing_hard_kill",
|
|
@@ -6182,6 +6182,18 @@ function rewriteAssetPaths(elements, compSrcPath, getAttr2, setAttr) {
|
|
|
6182
6182
|
}
|
|
6183
6183
|
}
|
|
6184
6184
|
}
|
|
6185
|
+
function rewriteInlineStyleAssetUrls(elements, compSrcPath, getStyle, setStyle) {
|
|
6186
|
+
const compDir = dirname(compSrcPath);
|
|
6187
|
+
if (!compDir || compDir === ".") return;
|
|
6188
|
+
for (const el of elements) {
|
|
6189
|
+
const style = getStyle(el);
|
|
6190
|
+
if (!style) continue;
|
|
6191
|
+
const rewritten = rewriteCssAssetUrls(style, compSrcPath);
|
|
6192
|
+
if (rewritten !== style) {
|
|
6193
|
+
setStyle(el, rewritten);
|
|
6194
|
+
}
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6185
6197
|
function rewriteCssAssetUrls(cssText, compSrcPath) {
|
|
6186
6198
|
if (!cssText) return cssText;
|
|
6187
6199
|
return cssText.replace(CSS_URL_RE, (full, quote, rawUrl) => {
|
|
@@ -11636,7 +11648,7 @@ function registerProjectRoutes(api, adapter2) {
|
|
|
11636
11648
|
const project = await adapter2.resolveProject(c2.req.param("id"));
|
|
11637
11649
|
if (!project) return c2.json({ error: "not found" }, 404);
|
|
11638
11650
|
const files = walkDir(project.dir);
|
|
11639
|
-
return c2.json({ id: project.id, files });
|
|
11651
|
+
return c2.json({ id: project.id, dir: project.dir, title: project.title, files });
|
|
11640
11652
|
});
|
|
11641
11653
|
}
|
|
11642
11654
|
var init_projects = __esm({
|
|
@@ -24751,6 +24763,14 @@ function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
|
|
|
24751
24763
|
el.setAttribute(attr, value);
|
|
24752
24764
|
}
|
|
24753
24765
|
);
|
|
24766
|
+
rewriteInlineStyleAssetUrls(
|
|
24767
|
+
contentDoc.querySelectorAll("[style]"),
|
|
24768
|
+
compPath,
|
|
24769
|
+
(el) => el.getAttribute("style"),
|
|
24770
|
+
(el, value) => {
|
|
24771
|
+
el.setAttribute("style", value);
|
|
24772
|
+
}
|
|
24773
|
+
);
|
|
24754
24774
|
for (const styleEl of contentDoc.querySelectorAll("style")) {
|
|
24755
24775
|
styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || "", compPath);
|
|
24756
24776
|
}
|
|
@@ -25145,7 +25165,7 @@ var init_render = __esm({
|
|
|
25145
25165
|
});
|
|
25146
25166
|
|
|
25147
25167
|
// ../core/src/studio-api/routes/thumbnail.ts
|
|
25148
|
-
import { existsSync as existsSync14, readFileSync as readFileSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8 } from "fs";
|
|
25168
|
+
import { existsSync as existsSync14, readFileSync as readFileSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
|
|
25149
25169
|
import { join as join17 } from "path";
|
|
25150
25170
|
function registerThumbnailRoutes(api, adapter2) {
|
|
25151
25171
|
api.get("/projects/:id/thumbnail/*", async (c2) => {
|
|
@@ -25163,13 +25183,16 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
25163
25183
|
const vpWidth = parseInt(url.searchParams.get("w") || "0") || 0;
|
|
25164
25184
|
const vpHeight = parseInt(url.searchParams.get("h") || "0") || 0;
|
|
25165
25185
|
const selector = url.searchParams.get("selector") || void 0;
|
|
25166
|
-
const
|
|
25167
|
-
const
|
|
25186
|
+
const rawSelectorIndex = Number.parseInt(url.searchParams.get("selectorIndex") || "0", 10);
|
|
25187
|
+
const selectorIndex = Number.isFinite(rawSelectorIndex) && rawSelectorIndex > 0 ? rawSelectorIndex : void 0;
|
|
25188
|
+
const urlVersion = url.searchParams.get("v") || "";
|
|
25168
25189
|
let compW = vpWidth || 1920;
|
|
25169
25190
|
let compH = vpHeight || 1080;
|
|
25191
|
+
let sourceMtime = 0;
|
|
25170
25192
|
if (!vpWidth) {
|
|
25171
25193
|
const htmlFile = join17(project.dir, compPath);
|
|
25172
25194
|
if (existsSync14(htmlFile)) {
|
|
25195
|
+
sourceMtime = Math.round(statSync4(htmlFile).mtimeMs);
|
|
25173
25196
|
const html = readFileSync15(htmlFile, "utf-8");
|
|
25174
25197
|
const wMatch = html.match(/data-width=["'](\d+)["']/);
|
|
25175
25198
|
const hMatch = html.match(/data-height=["'](\d+)["']/);
|
|
@@ -25179,12 +25202,13 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
25179
25202
|
}
|
|
25180
25203
|
const previewUrl = compPath === "index.html" ? `http://${c2.req.header("host")}/api/projects/${project.id}/preview` : `http://${c2.req.header("host")}/api/projects/${project.id}/preview/comp/${compPath}`;
|
|
25181
25204
|
const cacheDir = join17(project.dir, ".thumbnails");
|
|
25182
|
-
const selectorKey = selector ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 80)}` : "";
|
|
25183
|
-
const
|
|
25205
|
+
const selectorKey = selector ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 80)}_${selectorIndex ?? 0}` : "";
|
|
25206
|
+
const urlVersionKey = urlVersion ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32)}` : "";
|
|
25207
|
+
const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}_${compPath.replace(/\//g, "_")}_${compW}x${compH}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.jpg`;
|
|
25184
25208
|
const cachePath2 = join17(cacheDir, cacheKey);
|
|
25185
25209
|
if (existsSync14(cachePath2)) {
|
|
25186
25210
|
return new Response(new Uint8Array(readFileSync15(cachePath2)), {
|
|
25187
|
-
headers: { "Content-Type":
|
|
25211
|
+
headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
|
|
25188
25212
|
});
|
|
25189
25213
|
}
|
|
25190
25214
|
try {
|
|
@@ -25196,7 +25220,7 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
25196
25220
|
height: compH,
|
|
25197
25221
|
previewUrl,
|
|
25198
25222
|
selector,
|
|
25199
|
-
|
|
25223
|
+
selectorIndex
|
|
25200
25224
|
});
|
|
25201
25225
|
if (!buffer) {
|
|
25202
25226
|
return c2.json({ error: "Thumbnail generation returned null" }, 500);
|
|
@@ -25204,7 +25228,7 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
25204
25228
|
if (!existsSync14(cacheDir)) mkdirSync8(cacheDir, { recursive: true });
|
|
25205
25229
|
writeFileSync9(cachePath2, buffer);
|
|
25206
25230
|
return new Response(new Uint8Array(buffer), {
|
|
25207
|
-
headers: { "Content-Type":
|
|
25231
|
+
headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
|
|
25208
25232
|
});
|
|
25209
25233
|
} catch (err) {
|
|
25210
25234
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -25216,7 +25240,7 @@ var THUMBNAIL_CACHE_VERSION;
|
|
|
25216
25240
|
var init_thumbnail = __esm({
|
|
25217
25241
|
"../core/src/studio-api/routes/thumbnail.ts"() {
|
|
25218
25242
|
"use strict";
|
|
25219
|
-
THUMBNAIL_CACHE_VERSION = "
|
|
25243
|
+
THUMBNAIL_CACHE_VERSION = "v3";
|
|
25220
25244
|
}
|
|
25221
25245
|
});
|
|
25222
25246
|
|
|
@@ -25264,6 +25288,218 @@ var init_waveform2 = __esm({
|
|
|
25264
25288
|
}
|
|
25265
25289
|
});
|
|
25266
25290
|
|
|
25291
|
+
// ../core/src/studio-api/routes/fonts.ts
|
|
25292
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
25293
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
|
|
25294
|
+
import { homedir as homedir4, platform as platform3 } from "os";
|
|
25295
|
+
import { join as join19 } from "path";
|
|
25296
|
+
function isRecord(value) {
|
|
25297
|
+
return typeof value === "object" && value !== null;
|
|
25298
|
+
}
|
|
25299
|
+
function fontDirectories() {
|
|
25300
|
+
const home = homedir4();
|
|
25301
|
+
if (platform3() === "darwin") {
|
|
25302
|
+
return [
|
|
25303
|
+
join19(home, "Library", "Fonts"),
|
|
25304
|
+
"/Library/Fonts",
|
|
25305
|
+
"/System/Library/Fonts",
|
|
25306
|
+
"/System/Library/Fonts/Supplemental"
|
|
25307
|
+
];
|
|
25308
|
+
}
|
|
25309
|
+
if (platform3() === "win32") {
|
|
25310
|
+
return [join19(process.env.WINDIR || "C:\\Windows", "Fonts")];
|
|
25311
|
+
}
|
|
25312
|
+
return [
|
|
25313
|
+
join19(home, ".fonts"),
|
|
25314
|
+
join19(home, ".local", "share", "fonts"),
|
|
25315
|
+
"/usr/local/share/fonts",
|
|
25316
|
+
"/usr/share/fonts"
|
|
25317
|
+
];
|
|
25318
|
+
}
|
|
25319
|
+
function toFamilyName(fileName) {
|
|
25320
|
+
const withoutExt = fileName.replace(FONT_EXT_RE, "");
|
|
25321
|
+
if (!withoutExt || withoutExt.startsWith(".")) return null;
|
|
25322
|
+
const spaced = withoutExt.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/\s+/g, " ").trim();
|
|
25323
|
+
const words = spaced.split(" ").filter(Boolean);
|
|
25324
|
+
while (words.length > 1 && STYLE_SUFFIXES.has((words.at(-1) ?? "").toLowerCase())) {
|
|
25325
|
+
words.pop();
|
|
25326
|
+
}
|
|
25327
|
+
const family = words.join(" ").trim();
|
|
25328
|
+
return family.length >= 2 ? family : null;
|
|
25329
|
+
}
|
|
25330
|
+
function collectMacSystemProfilerFonts() {
|
|
25331
|
+
if (platform3() !== "darwin") return [];
|
|
25332
|
+
let parsed;
|
|
25333
|
+
try {
|
|
25334
|
+
const raw = execFileSync4("system_profiler", ["SPFontsDataType", "-json"], {
|
|
25335
|
+
encoding: "utf8",
|
|
25336
|
+
maxBuffer: 12 * 1024 * 1024,
|
|
25337
|
+
timeout: 5e3
|
|
25338
|
+
});
|
|
25339
|
+
parsed = JSON.parse(raw);
|
|
25340
|
+
} catch {
|
|
25341
|
+
return [];
|
|
25342
|
+
}
|
|
25343
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.SPFontsDataType)) return [];
|
|
25344
|
+
const fonts = [];
|
|
25345
|
+
for (const fontEntry of parsed.SPFontsDataType) {
|
|
25346
|
+
if (!isRecord(fontEntry)) continue;
|
|
25347
|
+
const typefaces = fontEntry.typefaces;
|
|
25348
|
+
if (!Array.isArray(typefaces)) continue;
|
|
25349
|
+
for (const typeface of typefaces) {
|
|
25350
|
+
if (!isRecord(typeface)) continue;
|
|
25351
|
+
const family = typeface.family;
|
|
25352
|
+
const fullName = typeface.fullname;
|
|
25353
|
+
const name = typeface._name;
|
|
25354
|
+
if (typeof family === "string" && family.trim()) {
|
|
25355
|
+
fonts.push(family.trim());
|
|
25356
|
+
} else if (typeof fullName === "string" && fullName.trim()) {
|
|
25357
|
+
fonts.push(fullName.trim());
|
|
25358
|
+
} else if (typeof name === "string" && name.trim()) {
|
|
25359
|
+
fonts.push(name.trim());
|
|
25360
|
+
}
|
|
25361
|
+
}
|
|
25362
|
+
}
|
|
25363
|
+
return fonts;
|
|
25364
|
+
}
|
|
25365
|
+
function collectFontsFromDir(dir, depth = 0) {
|
|
25366
|
+
if (!existsSync16(dir) || depth > 2) return [];
|
|
25367
|
+
const fonts = [];
|
|
25368
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
25369
|
+
const fullPath = join19(dir, entry.name);
|
|
25370
|
+
if (entry.isDirectory()) {
|
|
25371
|
+
fonts.push(...collectFontsFromDir(fullPath, depth + 1));
|
|
25372
|
+
continue;
|
|
25373
|
+
}
|
|
25374
|
+
if (!entry.isFile() || !FONT_EXT_RE.test(entry.name)) continue;
|
|
25375
|
+
try {
|
|
25376
|
+
if (!statSync5(fullPath).isFile()) continue;
|
|
25377
|
+
} catch {
|
|
25378
|
+
continue;
|
|
25379
|
+
}
|
|
25380
|
+
const family = toFamilyName(entry.name);
|
|
25381
|
+
if (family) fonts.push(family);
|
|
25382
|
+
}
|
|
25383
|
+
return fonts;
|
|
25384
|
+
}
|
|
25385
|
+
function listInstalledFontFamilies() {
|
|
25386
|
+
if (cachedFonts) return cachedFonts;
|
|
25387
|
+
const families = /* @__PURE__ */ new Set();
|
|
25388
|
+
for (const family of collectMacSystemProfilerFonts()) {
|
|
25389
|
+
families.add(family);
|
|
25390
|
+
if (families.size >= MAX_FONT_RESULTS) break;
|
|
25391
|
+
}
|
|
25392
|
+
for (const dir of fontDirectories()) {
|
|
25393
|
+
for (const family of collectFontsFromDir(dir)) {
|
|
25394
|
+
families.add(family);
|
|
25395
|
+
if (families.size >= MAX_FONT_RESULTS) break;
|
|
25396
|
+
}
|
|
25397
|
+
if (families.size >= MAX_FONT_RESULTS) break;
|
|
25398
|
+
}
|
|
25399
|
+
cachedFonts = Array.from(families).sort((a, b) => a.localeCompare(b));
|
|
25400
|
+
return cachedFonts;
|
|
25401
|
+
}
|
|
25402
|
+
function parseGoogleFontMetadata(value) {
|
|
25403
|
+
if (!isRecord(value) || !Array.isArray(value.familyMetadataList)) return [];
|
|
25404
|
+
const families = [];
|
|
25405
|
+
for (const entry of value.familyMetadataList) {
|
|
25406
|
+
if (!isRecord(entry) || typeof entry.family !== "string") continue;
|
|
25407
|
+
families.push(entry.family);
|
|
25408
|
+
}
|
|
25409
|
+
return families;
|
|
25410
|
+
}
|
|
25411
|
+
function stripGoogleJsonGuard(raw) {
|
|
25412
|
+
const prefix = ")]}'";
|
|
25413
|
+
if (!raw.startsWith(prefix)) return raw;
|
|
25414
|
+
let index = prefix.length;
|
|
25415
|
+
while (index < raw.length && (raw[index] === " " || raw[index] === "\n" || raw[index] === "\r" || raw[index] === " " || raw[index] === "\f")) {
|
|
25416
|
+
index += 1;
|
|
25417
|
+
}
|
|
25418
|
+
return raw.slice(index);
|
|
25419
|
+
}
|
|
25420
|
+
async function listGoogleFontFamilies() {
|
|
25421
|
+
if (cachedGoogleFonts) return cachedGoogleFonts;
|
|
25422
|
+
const controller = new AbortController();
|
|
25423
|
+
const timer = setTimeout(() => controller.abort(), GOOGLE_FONTS_FETCH_TIMEOUT_MS);
|
|
25424
|
+
try {
|
|
25425
|
+
const response = await fetch(GOOGLE_FONTS_METADATA_URL, { signal: controller.signal });
|
|
25426
|
+
if (!response.ok) {
|
|
25427
|
+
cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;
|
|
25428
|
+
return cachedGoogleFonts;
|
|
25429
|
+
}
|
|
25430
|
+
const raw = await response.text();
|
|
25431
|
+
const jsonText = stripGoogleJsonGuard(raw);
|
|
25432
|
+
const families = parseGoogleFontMetadata(JSON.parse(jsonText));
|
|
25433
|
+
cachedGoogleFonts = families.length > 0 ? families : GOOGLE_FONT_FALLBACKS;
|
|
25434
|
+
} catch {
|
|
25435
|
+
cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;
|
|
25436
|
+
} finally {
|
|
25437
|
+
clearTimeout(timer);
|
|
25438
|
+
}
|
|
25439
|
+
return cachedGoogleFonts;
|
|
25440
|
+
}
|
|
25441
|
+
function registerFontRoutes(api) {
|
|
25442
|
+
api.get("/fonts", (c2) => c2.json({ fonts: listInstalledFontFamilies() }));
|
|
25443
|
+
api.get("/fonts/google", async (c2) => c2.json({ fonts: await listGoogleFontFamilies() }));
|
|
25444
|
+
}
|
|
25445
|
+
var FONT_EXT_RE, MAX_FONT_RESULTS, GOOGLE_FONTS_METADATA_URL, GOOGLE_FONTS_FETCH_TIMEOUT_MS, cachedFonts, cachedGoogleFonts, STYLE_SUFFIXES, GOOGLE_FONT_FALLBACKS;
|
|
25446
|
+
var init_fonts = __esm({
|
|
25447
|
+
"../core/src/studio-api/routes/fonts.ts"() {
|
|
25448
|
+
"use strict";
|
|
25449
|
+
FONT_EXT_RE = /\.(otf|ttf|ttc|woff2?)$/i;
|
|
25450
|
+
MAX_FONT_RESULTS = 2e3;
|
|
25451
|
+
GOOGLE_FONTS_METADATA_URL = "https://fonts.google.com/metadata/fonts";
|
|
25452
|
+
GOOGLE_FONTS_FETCH_TIMEOUT_MS = 3e3;
|
|
25453
|
+
cachedFonts = null;
|
|
25454
|
+
cachedGoogleFonts = null;
|
|
25455
|
+
STYLE_SUFFIXES = /* @__PURE__ */ new Set([
|
|
25456
|
+
"black",
|
|
25457
|
+
"bold",
|
|
25458
|
+
"book",
|
|
25459
|
+
"condensed",
|
|
25460
|
+
"demi",
|
|
25461
|
+
"demibold",
|
|
25462
|
+
"display",
|
|
25463
|
+
"extra",
|
|
25464
|
+
"extrabold",
|
|
25465
|
+
"hairline",
|
|
25466
|
+
"heavy",
|
|
25467
|
+
"italic",
|
|
25468
|
+
"light",
|
|
25469
|
+
"medium",
|
|
25470
|
+
"normal",
|
|
25471
|
+
"regular",
|
|
25472
|
+
"roman",
|
|
25473
|
+
"semibold",
|
|
25474
|
+
"thin",
|
|
25475
|
+
"ultra",
|
|
25476
|
+
"ultralight"
|
|
25477
|
+
]);
|
|
25478
|
+
GOOGLE_FONT_FALLBACKS = [
|
|
25479
|
+
"Inter",
|
|
25480
|
+
"Roboto",
|
|
25481
|
+
"Open Sans",
|
|
25482
|
+
"Montserrat",
|
|
25483
|
+
"Poppins",
|
|
25484
|
+
"Lato",
|
|
25485
|
+
"Oswald",
|
|
25486
|
+
"Raleway",
|
|
25487
|
+
"Nunito",
|
|
25488
|
+
"Playfair Display",
|
|
25489
|
+
"Merriweather",
|
|
25490
|
+
"Source Sans 3",
|
|
25491
|
+
"Source Serif 4",
|
|
25492
|
+
"Source Code Pro",
|
|
25493
|
+
"DM Sans",
|
|
25494
|
+
"Space Grotesk",
|
|
25495
|
+
"Space Mono",
|
|
25496
|
+
"Bebas Neue",
|
|
25497
|
+
"Outfit",
|
|
25498
|
+
"JetBrains Mono"
|
|
25499
|
+
];
|
|
25500
|
+
}
|
|
25501
|
+
});
|
|
25502
|
+
|
|
25267
25503
|
// ../core/src/studio-api/createStudioApi.ts
|
|
25268
25504
|
import { Hono } from "hono";
|
|
25269
25505
|
function createStudioApi(adapter2) {
|
|
@@ -25275,6 +25511,7 @@ function createStudioApi(adapter2) {
|
|
|
25275
25511
|
registerRenderRoutes(api, adapter2);
|
|
25276
25512
|
registerThumbnailRoutes(api, adapter2);
|
|
25277
25513
|
registerWaveformRoutes(api, adapter2);
|
|
25514
|
+
registerFontRoutes(api);
|
|
25278
25515
|
return api;
|
|
25279
25516
|
}
|
|
25280
25517
|
var init_createStudioApi = __esm({
|
|
@@ -25287,6 +25524,7 @@ var init_createStudioApi = __esm({
|
|
|
25287
25524
|
init_render();
|
|
25288
25525
|
init_thumbnail();
|
|
25289
25526
|
init_waveform2();
|
|
25527
|
+
init_fonts();
|
|
25290
25528
|
}
|
|
25291
25529
|
});
|
|
25292
25530
|
|
|
@@ -25321,9 +25559,9 @@ __export(manager_exports2, {
|
|
|
25321
25559
|
setBrowserPath: () => setBrowserPath
|
|
25322
25560
|
});
|
|
25323
25561
|
import { execSync } from "child_process";
|
|
25324
|
-
import { existsSync as
|
|
25325
|
-
import { homedir as
|
|
25326
|
-
import { join as
|
|
25562
|
+
import { existsSync as existsSync17, rmSync as rmSync4 } from "fs";
|
|
25563
|
+
import { homedir as homedir5 } from "os";
|
|
25564
|
+
import { join as join20 } from "path";
|
|
25327
25565
|
import { Browser, detectBrowserPlatform, getInstalledBrowsers, install } from "@puppeteer/browsers";
|
|
25328
25566
|
function setBrowserPath(path2) {
|
|
25329
25567
|
_browserPathOverride = path2;
|
|
@@ -25343,17 +25581,17 @@ function whichBinary2(name) {
|
|
|
25343
25581
|
}
|
|
25344
25582
|
}
|
|
25345
25583
|
function findFromEnv2() {
|
|
25346
|
-
if (_browserPathOverride &&
|
|
25584
|
+
if (_browserPathOverride && existsSync17(_browserPathOverride)) {
|
|
25347
25585
|
return { executablePath: _browserPathOverride, source: "env" };
|
|
25348
25586
|
}
|
|
25349
25587
|
const envPath = process.env["HYPERFRAMES_BROWSER_PATH"];
|
|
25350
|
-
if (envPath &&
|
|
25588
|
+
if (envPath && existsSync17(envPath)) {
|
|
25351
25589
|
return { executablePath: envPath, source: "env" };
|
|
25352
25590
|
}
|
|
25353
25591
|
return void 0;
|
|
25354
25592
|
}
|
|
25355
25593
|
async function findFromCache() {
|
|
25356
|
-
if (!
|
|
25594
|
+
if (!existsSync17(CACHE_DIR2)) {
|
|
25357
25595
|
return void 0;
|
|
25358
25596
|
}
|
|
25359
25597
|
const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
|
|
@@ -25365,7 +25603,7 @@ async function findFromCache() {
|
|
|
25365
25603
|
}
|
|
25366
25604
|
function findFromSystem2() {
|
|
25367
25605
|
for (const p of SYSTEM_CHROME_PATHS) {
|
|
25368
|
-
if (
|
|
25606
|
+
if (existsSync17(p)) {
|
|
25369
25607
|
return { executablePath: p, source: "system" };
|
|
25370
25608
|
}
|
|
25371
25609
|
}
|
|
@@ -25385,21 +25623,21 @@ async function findBrowser() {
|
|
|
25385
25623
|
async function ensureBrowser(options) {
|
|
25386
25624
|
const existing = await findBrowser();
|
|
25387
25625
|
if (existing) return existing;
|
|
25388
|
-
const
|
|
25389
|
-
if (!
|
|
25626
|
+
const platform6 = detectBrowserPlatform();
|
|
25627
|
+
if (!platform6) {
|
|
25390
25628
|
throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`);
|
|
25391
25629
|
}
|
|
25392
25630
|
const installed = await install({
|
|
25393
25631
|
cacheDir: CACHE_DIR2,
|
|
25394
25632
|
browser: Browser.CHROMEHEADLESSSHELL,
|
|
25395
25633
|
buildId: CHROME_VERSION,
|
|
25396
|
-
platform:
|
|
25634
|
+
platform: platform6,
|
|
25397
25635
|
downloadProgressCallback: options?.onProgress
|
|
25398
25636
|
});
|
|
25399
25637
|
return { executablePath: installed.executablePath, source: "download" };
|
|
25400
25638
|
}
|
|
25401
25639
|
function clearBrowser() {
|
|
25402
|
-
if (!
|
|
25640
|
+
if (!existsSync17(CACHE_DIR2)) {
|
|
25403
25641
|
return false;
|
|
25404
25642
|
}
|
|
25405
25643
|
rmSync4(CACHE_DIR2, { recursive: true, force: true });
|
|
@@ -25410,7 +25648,7 @@ var init_manager2 = __esm({
|
|
|
25410
25648
|
"src/browser/manager.ts"() {
|
|
25411
25649
|
"use strict";
|
|
25412
25650
|
CHROME_VERSION = "131.0.6778.85";
|
|
25413
|
-
CACHE_DIR2 =
|
|
25651
|
+
CACHE_DIR2 = join20(homedir5(), ".cache", "hyperframes", "chrome");
|
|
25414
25652
|
SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : [
|
|
25415
25653
|
"/usr/bin/google-chrome",
|
|
25416
25654
|
"/usr/bin/google-chrome-stable",
|
|
@@ -25537,9 +25775,9 @@ var init_config2 = __esm({
|
|
|
25537
25775
|
});
|
|
25538
25776
|
|
|
25539
25777
|
// ../engine/src/services/browserManager.ts
|
|
25540
|
-
import { existsSync as
|
|
25541
|
-
import { join as
|
|
25542
|
-
import { homedir as
|
|
25778
|
+
import { existsSync as existsSync18, readdirSync as readdirSync7 } from "fs";
|
|
25779
|
+
import { join as join21 } from "path";
|
|
25780
|
+
import { homedir as homedir6 } from "os";
|
|
25543
25781
|
async function getPuppeteer() {
|
|
25544
25782
|
if (_puppeteer) return _puppeteer;
|
|
25545
25783
|
try {
|
|
@@ -25559,19 +25797,19 @@ function resolveHeadlessShellPath(config) {
|
|
|
25559
25797
|
if (process.env.PRODUCER_HEADLESS_SHELL_PATH) {
|
|
25560
25798
|
return process.env.PRODUCER_HEADLESS_SHELL_PATH;
|
|
25561
25799
|
}
|
|
25562
|
-
const baseDir =
|
|
25563
|
-
if (!
|
|
25800
|
+
const baseDir = join21(homedir6(), ".cache", "puppeteer", "chrome-headless-shell");
|
|
25801
|
+
if (!existsSync18(baseDir)) return void 0;
|
|
25564
25802
|
try {
|
|
25565
|
-
const versions =
|
|
25803
|
+
const versions = readdirSync7(baseDir).sort().reverse();
|
|
25566
25804
|
for (const version of versions) {
|
|
25567
25805
|
const candidates = [
|
|
25568
|
-
|
|
25569
|
-
|
|
25570
|
-
|
|
25571
|
-
|
|
25806
|
+
join21(baseDir, version, "chrome-headless-shell-linux64", "chrome-headless-shell"),
|
|
25807
|
+
join21(baseDir, version, "chrome-headless-shell-mac-arm64", "chrome-headless-shell"),
|
|
25808
|
+
join21(baseDir, version, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
|
|
25809
|
+
join21(baseDir, version, "chrome-headless-shell-win64", "chrome-headless-shell.exe")
|
|
25572
25810
|
];
|
|
25573
25811
|
for (const binary of candidates) {
|
|
25574
|
-
if (
|
|
25812
|
+
if (existsSync18(binary)) return binary;
|
|
25575
25813
|
}
|
|
25576
25814
|
}
|
|
25577
25815
|
} catch {
|
|
@@ -26034,10 +26272,10 @@ var init_screenshotService = __esm({
|
|
|
26034
26272
|
});
|
|
26035
26273
|
|
|
26036
26274
|
// ../engine/src/services/frameCapture.ts
|
|
26037
|
-
import { existsSync as
|
|
26038
|
-
import { join as
|
|
26275
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
26276
|
+
import { join as join22 } from "path";
|
|
26039
26277
|
async function createCaptureSession(serverUrl, outputDir, options, onBeforeCapture = null, config) {
|
|
26040
|
-
if (!
|
|
26278
|
+
if (!existsSync19(outputDir)) mkdirSync10(outputDir, { recursive: true });
|
|
26041
26279
|
const headlessShell = resolveHeadlessShellPath(config);
|
|
26042
26280
|
const isLinux = process.platform === "linux";
|
|
26043
26281
|
const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG2.forceScreenshot;
|
|
@@ -26241,9 +26479,9 @@ async function initializeSession(session) {
|
|
|
26241
26479
|
}
|
|
26242
26480
|
async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
|
|
26243
26481
|
try {
|
|
26244
|
-
const diagnosticsDir =
|
|
26245
|
-
if (!
|
|
26246
|
-
const base =
|
|
26482
|
+
const diagnosticsDir = join22(session.outputDir, "diagnostics");
|
|
26483
|
+
if (!existsSync19(diagnosticsDir)) mkdirSync10(diagnosticsDir, { recursive: true });
|
|
26484
|
+
const base = join22(diagnosticsDir, `frame-error-${frameIndex}`);
|
|
26247
26485
|
await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
|
|
26248
26486
|
const html = await session.page.content();
|
|
26249
26487
|
writeFileSync11(`${base}.html`, html, "utf-8");
|
|
@@ -26341,7 +26579,7 @@ async function captureFrame(session, frameIndex, time) {
|
|
|
26341
26579
|
);
|
|
26342
26580
|
const ext = options.format === "png" ? "png" : "jpg";
|
|
26343
26581
|
const frameName = `frame_${String(frameIndex).padStart(6, "0")}.${ext}`;
|
|
26344
|
-
const framePath =
|
|
26582
|
+
const framePath = join22(outputDir, frameName);
|
|
26345
26583
|
writeFileSync11(framePath, buffer);
|
|
26346
26584
|
return { frameIndex, time: quantizedTime, path: framePath, captureTimeMs };
|
|
26347
26585
|
}
|
|
@@ -26362,7 +26600,7 @@ async function closeCaptureSession(session) {
|
|
|
26362
26600
|
session.isInitialized = false;
|
|
26363
26601
|
}
|
|
26364
26602
|
function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
|
|
26365
|
-
if (!
|
|
26603
|
+
if (!existsSync19(outputDir)) {
|
|
26366
26604
|
mkdirSync10(outputDir, { recursive: true });
|
|
26367
26605
|
}
|
|
26368
26606
|
session.outputDir = outputDir;
|
|
@@ -26600,8 +26838,8 @@ var init_runFfmpeg = __esm({
|
|
|
26600
26838
|
|
|
26601
26839
|
// ../engine/src/services/chunkEncoder.ts
|
|
26602
26840
|
import { spawn as spawn5 } from "child_process";
|
|
26603
|
-
import { copyFileSync, existsSync as
|
|
26604
|
-
import { join as
|
|
26841
|
+
import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync11, readdirSync as readdirSync8, statSync as statSync6, writeFileSync as writeFileSync12 } from "fs";
|
|
26842
|
+
import { join as join23, dirname as dirname7 } from "path";
|
|
26605
26843
|
function getEncoderPreset(quality, format = "mp4", hdr) {
|
|
26606
26844
|
const base = ENCODER_PRESETS[quality];
|
|
26607
26845
|
if (format === "webm") {
|
|
@@ -26752,8 +26990,8 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
26752
26990
|
async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config) {
|
|
26753
26991
|
const startTime = Date.now();
|
|
26754
26992
|
const outputDir = dirname7(outputPath);
|
|
26755
|
-
if (!
|
|
26756
|
-
const files =
|
|
26993
|
+
if (!existsSync20(outputDir)) mkdirSync11(outputDir, { recursive: true });
|
|
26994
|
+
const files = readdirSync8(framesDir).filter((f3) => f3.match(/\.(jpg|jpeg|png)$/i));
|
|
26757
26995
|
const frameCount = files.length;
|
|
26758
26996
|
if (frameCount === 0) {
|
|
26759
26997
|
return {
|
|
@@ -26769,7 +27007,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26769
27007
|
if (options.useGpu) {
|
|
26770
27008
|
gpuEncoder = await getCachedGpuEncoder();
|
|
26771
27009
|
}
|
|
26772
|
-
const inputPath =
|
|
27010
|
+
const inputPath = join23(framesDir, framePattern);
|
|
26773
27011
|
const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
|
|
26774
27012
|
const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
|
|
26775
27013
|
return new Promise((resolve39) => {
|
|
@@ -26818,7 +27056,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26818
27056
|
});
|
|
26819
27057
|
return;
|
|
26820
27058
|
}
|
|
26821
|
-
const fileSize =
|
|
27059
|
+
const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
|
|
26822
27060
|
resolve39({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
|
|
26823
27061
|
});
|
|
26824
27062
|
ffmpeg.on("error", (err) => {
|
|
@@ -26837,7 +27075,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26837
27075
|
}
|
|
26838
27076
|
async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, options, chunkSizeFrames, signal) {
|
|
26839
27077
|
const start = Date.now();
|
|
26840
|
-
const files =
|
|
27078
|
+
const files = readdirSync8(framesDir).filter((f3) => f3.match(/\.(jpg|jpeg|png)$/i)).sort();
|
|
26841
27079
|
if (files.length === 0) {
|
|
26842
27080
|
return {
|
|
26843
27081
|
success: false,
|
|
@@ -26850,8 +27088,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26850
27088
|
}
|
|
26851
27089
|
const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
|
|
26852
27090
|
const chunkCount = Math.ceil(files.length / chunkSize);
|
|
26853
|
-
const chunkDir =
|
|
26854
|
-
if (!
|
|
27091
|
+
const chunkDir = join23(dirname7(outputPath), "chunk-encode");
|
|
27092
|
+
if (!existsSync20(chunkDir)) mkdirSync11(chunkDir, { recursive: true });
|
|
26855
27093
|
const chunkPaths = [];
|
|
26856
27094
|
for (let i2 = 0; i2 < chunkCount; i2++) {
|
|
26857
27095
|
if (signal?.aborted) {
|
|
@@ -26867,8 +27105,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26867
27105
|
const startNumber = i2 * chunkSize;
|
|
26868
27106
|
const framesInChunk = Math.min(chunkSize, files.length - startNumber);
|
|
26869
27107
|
const ext = outputPath.endsWith(".webm") ? ".webm" : outputPath.endsWith(".mov") ? ".mov" : ".mp4";
|
|
26870
|
-
const chunkPath =
|
|
26871
|
-
const inputPath =
|
|
27108
|
+
const chunkPath = join23(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
|
|
27109
|
+
const inputPath = join23(framesDir, framePattern);
|
|
26872
27110
|
const inputArgs = [
|
|
26873
27111
|
"-framerate",
|
|
26874
27112
|
String(options.fps),
|
|
@@ -26908,7 +27146,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26908
27146
|
}
|
|
26909
27147
|
chunkPaths.push(chunkPath);
|
|
26910
27148
|
}
|
|
26911
|
-
const concatListPath =
|
|
27149
|
+
const concatListPath = join23(chunkDir, "concat-list.txt");
|
|
26912
27150
|
const concatInput = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
|
|
26913
27151
|
writeFileSync12(concatListPath, concatInput, "utf-8");
|
|
26914
27152
|
const concatArgs = [
|
|
@@ -26947,7 +27185,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26947
27185
|
error: concatResult.error
|
|
26948
27186
|
};
|
|
26949
27187
|
}
|
|
26950
|
-
const fileSize =
|
|
27188
|
+
const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
|
|
26951
27189
|
return {
|
|
26952
27190
|
success: true,
|
|
26953
27191
|
outputPath,
|
|
@@ -26958,7 +27196,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26958
27196
|
}
|
|
26959
27197
|
async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config) {
|
|
26960
27198
|
const outputDir = dirname7(outputPath);
|
|
26961
|
-
if (!
|
|
27199
|
+
if (!existsSync20(outputDir)) mkdirSync11(outputDir, { recursive: true });
|
|
26962
27200
|
const isWebm = outputPath.endsWith(".webm");
|
|
26963
27201
|
const isMov = outputPath.endsWith(".mov");
|
|
26964
27202
|
const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
|
|
@@ -27029,7 +27267,7 @@ var init_chunkEncoder = __esm({
|
|
|
27029
27267
|
|
|
27030
27268
|
// ../engine/src/services/streamingEncoder.ts
|
|
27031
27269
|
import { spawn as spawn6 } from "child_process";
|
|
27032
|
-
import { existsSync as
|
|
27270
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync12, statSync as statSync7 } from "fs";
|
|
27033
27271
|
import { dirname as dirname8 } from "path";
|
|
27034
27272
|
function createFrameReorderBuffer(startFrame, endFrame) {
|
|
27035
27273
|
let cursor = startFrame;
|
|
@@ -27212,7 +27450,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
27212
27450
|
}
|
|
27213
27451
|
async function spawnStreamingEncoder(outputPath, options, signal, config) {
|
|
27214
27452
|
const outputDir = dirname8(outputPath);
|
|
27215
|
-
if (!
|
|
27453
|
+
if (!existsSync21(outputDir)) mkdirSync12(outputDir, { recursive: true });
|
|
27216
27454
|
let gpuEncoder = null;
|
|
27217
27455
|
if (options.useGpu) {
|
|
27218
27456
|
gpuEncoder = await getCachedGpuEncoder();
|
|
@@ -27294,7 +27532,7 @@ Process error: ${err.message}`;
|
|
|
27294
27532
|
error: formatFfmpegError(exitCode, stderr)
|
|
27295
27533
|
};
|
|
27296
27534
|
}
|
|
27297
|
-
const fileSize =
|
|
27535
|
+
const fileSize = existsSync21(outputPath) ? statSync7(outputPath).size : 0;
|
|
27298
27536
|
return { success: true, durationMs, fileSize };
|
|
27299
27537
|
},
|
|
27300
27538
|
getExitStatus: () => exitStatus
|
|
@@ -27586,9 +27824,9 @@ var init_ffprobe = __esm({
|
|
|
27586
27824
|
});
|
|
27587
27825
|
|
|
27588
27826
|
// ../engine/src/utils/urlDownloader.ts
|
|
27589
|
-
import { createWriteStream as createWriteStream2, existsSync as
|
|
27827
|
+
import { createWriteStream as createWriteStream2, existsSync as existsSync22, mkdirSync as mkdirSync13 } from "fs";
|
|
27590
27828
|
import { createHash } from "crypto";
|
|
27591
|
-
import { join as
|
|
27829
|
+
import { join as join24, extname as extname5 } from "path";
|
|
27592
27830
|
import { Readable } from "stream";
|
|
27593
27831
|
import { finished } from "stream/promises";
|
|
27594
27832
|
function getFilenameFromUrl(url) {
|
|
@@ -27599,19 +27837,19 @@ function getFilenameFromUrl(url) {
|
|
|
27599
27837
|
}
|
|
27600
27838
|
async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
|
|
27601
27839
|
const cachedPath = downloadPathCache.get(url);
|
|
27602
|
-
if (cachedPath &&
|
|
27840
|
+
if (cachedPath && existsSync22(cachedPath)) {
|
|
27603
27841
|
return cachedPath;
|
|
27604
27842
|
}
|
|
27605
27843
|
const inFlight = inFlightDownloads.get(url);
|
|
27606
27844
|
if (inFlight) {
|
|
27607
27845
|
return inFlight;
|
|
27608
27846
|
}
|
|
27609
|
-
if (!
|
|
27847
|
+
if (!existsSync22(destDir)) {
|
|
27610
27848
|
mkdirSync13(destDir, { recursive: true });
|
|
27611
27849
|
}
|
|
27612
27850
|
const filename = getFilenameFromUrl(url);
|
|
27613
|
-
const localPath =
|
|
27614
|
-
if (
|
|
27851
|
+
const localPath = join24(destDir, filename);
|
|
27852
|
+
if (existsSync22(localPath)) {
|
|
27615
27853
|
downloadPathCache.set(url, localPath);
|
|
27616
27854
|
return localPath;
|
|
27617
27855
|
}
|
|
@@ -27703,12 +27941,12 @@ var init_htmlTemplate = __esm({
|
|
|
27703
27941
|
|
|
27704
27942
|
// ../engine/src/services/extractionCache.ts
|
|
27705
27943
|
import { createHash as createHash2 } from "crypto";
|
|
27706
|
-
import { mkdirSync as mkdirSync14, readdirSync as
|
|
27707
|
-
import { existsSync as
|
|
27708
|
-
import { join as
|
|
27944
|
+
import { mkdirSync as mkdirSync14, readdirSync as readdirSync9, statSync as statSync8, writeFileSync as writeFileSync13 } from "fs";
|
|
27945
|
+
import { existsSync as existsSync23 } from "fs";
|
|
27946
|
+
import { join as join25 } from "path";
|
|
27709
27947
|
function readKeyStat(videoPath) {
|
|
27710
27948
|
try {
|
|
27711
|
-
const stat3 =
|
|
27949
|
+
const stat3 = statSync8(videoPath);
|
|
27712
27950
|
return { mtimeMs: Math.floor(stat3.mtimeMs), size: stat3.size };
|
|
27713
27951
|
} catch {
|
|
27714
27952
|
return null;
|
|
@@ -27734,23 +27972,23 @@ function cacheEntryDirName(keyHash) {
|
|
|
27734
27972
|
}
|
|
27735
27973
|
function lookupCacheEntry(rootDir, input) {
|
|
27736
27974
|
const keyHash = computeCacheKey(input);
|
|
27737
|
-
const dir =
|
|
27738
|
-
const complete =
|
|
27975
|
+
const dir = join25(rootDir, cacheEntryDirName(keyHash));
|
|
27976
|
+
const complete = existsSync23(join25(dir, COMPLETE_SENTINEL));
|
|
27739
27977
|
return { entry: { dir, keyHash }, hit: complete };
|
|
27740
27978
|
}
|
|
27741
27979
|
function ensureCacheEntryDir(entry) {
|
|
27742
27980
|
mkdirSync14(entry.dir, { recursive: true });
|
|
27743
27981
|
}
|
|
27744
27982
|
function markCacheEntryComplete(entry) {
|
|
27745
|
-
writeFileSync13(
|
|
27983
|
+
writeFileSync13(join25(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
|
|
27746
27984
|
}
|
|
27747
27985
|
function rehydrateCacheEntry(entry, options) {
|
|
27748
27986
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
|
|
27749
27987
|
const framePaths = /* @__PURE__ */ new Map();
|
|
27750
27988
|
const suffix = `.${options.format}`;
|
|
27751
|
-
const files =
|
|
27989
|
+
const files = readdirSync9(entry.dir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(suffix)).sort();
|
|
27752
27990
|
files.forEach((file, idx) => {
|
|
27753
|
-
framePaths.set(idx,
|
|
27991
|
+
framePaths.set(idx, join25(entry.dir, file));
|
|
27754
27992
|
});
|
|
27755
27993
|
return {
|
|
27756
27994
|
videoId: options.videoId,
|
|
@@ -27776,8 +28014,8 @@ var init_extractionCache = __esm({
|
|
|
27776
28014
|
|
|
27777
28015
|
// ../engine/src/services/videoFrameExtractor.ts
|
|
27778
28016
|
import { spawn as spawn8 } from "child_process";
|
|
27779
|
-
import { existsSync as
|
|
27780
|
-
import { isAbsolute as isAbsolute2, join as
|
|
28017
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync15, readdirSync as readdirSync10, rmSync as rmSync5 } from "fs";
|
|
28018
|
+
import { isAbsolute as isAbsolute2, join as join26 } from "path";
|
|
27781
28019
|
function parseVideoElements(html) {
|
|
27782
28020
|
const videos = [];
|
|
27783
28021
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
@@ -27847,12 +28085,12 @@ function parseImageElements(html) {
|
|
|
27847
28085
|
async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config, outputDirOverride) {
|
|
27848
28086
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
27849
28087
|
const { fps, outputDir, quality = 95 } = options;
|
|
27850
|
-
const videoOutputDir = outputDirOverride ??
|
|
27851
|
-
if (!
|
|
28088
|
+
const videoOutputDir = outputDirOverride ?? join26(outputDir, videoId);
|
|
28089
|
+
if (!existsSync24(videoOutputDir)) mkdirSync15(videoOutputDir, { recursive: true });
|
|
27852
28090
|
const metadata = await extractMediaMetadata(videoPath);
|
|
27853
28091
|
const format = resolveFrameFormat(metadata, options.format);
|
|
27854
28092
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
|
|
27855
|
-
const outputPattern =
|
|
28093
|
+
const outputPattern = join26(videoOutputDir, framePattern);
|
|
27856
28094
|
const isHdr = isHdrColorSpace(metadata.colorSpace);
|
|
27857
28095
|
const isMacOS = process.platform === "darwin";
|
|
27858
28096
|
const args = [];
|
|
@@ -27903,9 +28141,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
27903
28141
|
return;
|
|
27904
28142
|
}
|
|
27905
28143
|
const framePaths = /* @__PURE__ */ new Map();
|
|
27906
|
-
const files =
|
|
28144
|
+
const files = readdirSync10(videoOutputDir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(`.${format}`)).sort();
|
|
27907
28145
|
files.forEach((file, index) => {
|
|
27908
|
-
framePaths.set(index,
|
|
28146
|
+
framePaths.set(index, join26(videoOutputDir, file));
|
|
27909
28147
|
});
|
|
27910
28148
|
resolve39({
|
|
27911
28149
|
videoId,
|
|
@@ -28032,15 +28270,15 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
28032
28270
|
try {
|
|
28033
28271
|
let videoPath = video.src;
|
|
28034
28272
|
if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
|
|
28035
|
-
const fromCompiled = compiledDir ?
|
|
28036
|
-
videoPath = fromCompiled &&
|
|
28273
|
+
const fromCompiled = compiledDir ? join26(compiledDir, videoPath) : null;
|
|
28274
|
+
videoPath = fromCompiled && existsSync24(fromCompiled) ? fromCompiled : join26(baseDir, videoPath);
|
|
28037
28275
|
}
|
|
28038
28276
|
if (isHttpUrl(videoPath)) {
|
|
28039
|
-
const downloadDir =
|
|
28277
|
+
const downloadDir = join26(options.outputDir, "_downloads");
|
|
28040
28278
|
mkdirSync15(downloadDir, { recursive: true });
|
|
28041
28279
|
videoPath = await downloadToTemp(videoPath, downloadDir);
|
|
28042
28280
|
}
|
|
28043
|
-
if (!
|
|
28281
|
+
if (!existsSync24(videoPath)) {
|
|
28044
28282
|
errors.push({ videoId: video.id, error: `Video file not found: ${videoPath}` });
|
|
28045
28283
|
continue;
|
|
28046
28284
|
}
|
|
@@ -28073,7 +28311,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
28073
28311
|
const hdrSkippedIndices = /* @__PURE__ */ new Set();
|
|
28074
28312
|
if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
|
|
28075
28313
|
const targetTransfer = hdrInfo.dominantTransfer;
|
|
28076
|
-
const convertDir =
|
|
28314
|
+
const convertDir = join26(options.outputDir, "_hdr_normalized");
|
|
28077
28315
|
mkdirSync15(convertDir, { recursive: true });
|
|
28078
28316
|
for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
|
|
28079
28317
|
if (signal?.aborted) break;
|
|
@@ -28095,7 +28333,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
28095
28333
|
const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
|
|
28096
28334
|
segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
28097
28335
|
}
|
|
28098
|
-
const convertedPath =
|
|
28336
|
+
const convertedPath = join26(convertDir, `${entry.video.id}_hdr.mp4`);
|
|
28099
28337
|
try {
|
|
28100
28338
|
await convertSdrToHdr(
|
|
28101
28339
|
entry.videoPath,
|
|
@@ -28130,7 +28368,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
28130
28368
|
}
|
|
28131
28369
|
}
|
|
28132
28370
|
const vfrPreflightStart = Date.now();
|
|
28133
|
-
const vfrNormDir =
|
|
28371
|
+
const vfrNormDir = join26(options.outputDir, "_vfr_normalized");
|
|
28134
28372
|
for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
|
|
28135
28373
|
if (signal?.aborted) break;
|
|
28136
28374
|
const entry = resolvedVideos[i2];
|
|
@@ -28145,7 +28383,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
28145
28383
|
segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
28146
28384
|
}
|
|
28147
28385
|
mkdirSync15(vfrNormDir, { recursive: true });
|
|
28148
|
-
const normalizedPath =
|
|
28386
|
+
const normalizedPath = join26(vfrNormDir, `${entry.video.id}_cfr.mp4`);
|
|
28149
28387
|
try {
|
|
28150
28388
|
await convertVfrToCfr(
|
|
28151
28389
|
entry.videoPath,
|
|
@@ -28401,7 +28639,7 @@ var init_videoFrameExtractor = __esm({
|
|
|
28401
28639
|
cleanup() {
|
|
28402
28640
|
for (const video of this.videos.values()) {
|
|
28403
28641
|
if (video.extracted.ownedByLookup) continue;
|
|
28404
|
-
if (
|
|
28642
|
+
if (existsSync24(video.extracted.outputDir)) {
|
|
28405
28643
|
rmSync5(video.extracted.outputDir, { recursive: true, force: true });
|
|
28406
28644
|
}
|
|
28407
28645
|
}
|
|
@@ -28737,8 +28975,8 @@ var init_videoFrameInjector = __esm({
|
|
|
28737
28975
|
});
|
|
28738
28976
|
|
|
28739
28977
|
// ../engine/src/services/audioMixer.ts
|
|
28740
|
-
import { existsSync as
|
|
28741
|
-
import { isAbsolute as isAbsolute3, join as
|
|
28978
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
|
|
28979
|
+
import { isAbsolute as isAbsolute3, join as join27, dirname as dirname9 } from "path";
|
|
28742
28980
|
function parseAudioElements(html) {
|
|
28743
28981
|
const elements = [];
|
|
28744
28982
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
@@ -28789,7 +29027,7 @@ function parseAudioElements(html) {
|
|
|
28789
29027
|
async function extractAudioFromVideo(videoPath, outputPath, options, signal, config) {
|
|
28790
29028
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28791
29029
|
const outputDir = dirname9(outputPath);
|
|
28792
|
-
if (!
|
|
29030
|
+
if (!existsSync25(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28793
29031
|
const args = ["-i", videoPath];
|
|
28794
29032
|
if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
|
|
28795
29033
|
if (options?.duration !== void 0) args.push("-t", String(options.duration));
|
|
@@ -28816,7 +29054,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
|
|
|
28816
29054
|
async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config) {
|
|
28817
29055
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28818
29056
|
const outputDir = dirname9(outputPath);
|
|
28819
|
-
if (!
|
|
29057
|
+
if (!existsSync25(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28820
29058
|
const args = [
|
|
28821
29059
|
"-ss",
|
|
28822
29060
|
String(mediaStart),
|
|
@@ -28852,7 +29090,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
|
|
|
28852
29090
|
async function generateSilence(outputPath, duration, signal, config) {
|
|
28853
29091
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28854
29092
|
const outputDir = dirname9(outputPath);
|
|
28855
|
-
if (!
|
|
29093
|
+
if (!existsSync25(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28856
29094
|
const args = [
|
|
28857
29095
|
"-f",
|
|
28858
29096
|
"lavfi",
|
|
@@ -28895,7 +29133,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
|
|
|
28895
29133
|
};
|
|
28896
29134
|
}
|
|
28897
29135
|
const outputDir = dirname9(outputPath);
|
|
28898
|
-
if (!
|
|
29136
|
+
if (!existsSync25(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28899
29137
|
const inputs = [];
|
|
28900
29138
|
const filterParts = [];
|
|
28901
29139
|
tracks.forEach((track, i2) => {
|
|
@@ -28956,7 +29194,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28956
29194
|
const startMs = Date.now();
|
|
28957
29195
|
const tracks = [];
|
|
28958
29196
|
const errors = [];
|
|
28959
|
-
if (!
|
|
29197
|
+
if (!existsSync25(workDir)) mkdirSync16(workDir, { recursive: true });
|
|
28960
29198
|
await Promise.all(
|
|
28961
29199
|
elements.map(async (element) => {
|
|
28962
29200
|
if (signal?.aborted) {
|
|
@@ -28966,8 +29204,8 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28966
29204
|
try {
|
|
28967
29205
|
let srcPath = element.src;
|
|
28968
29206
|
if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
|
|
28969
|
-
const fromCompiled = compiledDir ?
|
|
28970
|
-
srcPath = fromCompiled &&
|
|
29207
|
+
const fromCompiled = compiledDir ? join27(compiledDir, srcPath) : null;
|
|
29208
|
+
srcPath = fromCompiled && existsSync25(fromCompiled) ? fromCompiled : join27(baseDir, srcPath);
|
|
28971
29209
|
}
|
|
28972
29210
|
if (isHttpUrl(srcPath)) {
|
|
28973
29211
|
try {
|
|
@@ -28979,7 +29217,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28979
29217
|
return;
|
|
28980
29218
|
}
|
|
28981
29219
|
}
|
|
28982
|
-
if (!
|
|
29220
|
+
if (!existsSync25(srcPath)) {
|
|
28983
29221
|
errors.push(`Source not found: ${element.id} (${element.src})`);
|
|
28984
29222
|
return;
|
|
28985
29223
|
}
|
|
@@ -28990,7 +29228,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28990
29228
|
}
|
|
28991
29229
|
let audioSrcPath = srcPath;
|
|
28992
29230
|
if (element.type === "video") {
|
|
28993
|
-
const extractedPath =
|
|
29231
|
+
const extractedPath = join27(workDir, `${element.id}-extracted.wav`);
|
|
28994
29232
|
const extractResult = await extractAudioFromVideo(
|
|
28995
29233
|
srcPath,
|
|
28996
29234
|
extractedPath,
|
|
@@ -29007,7 +29245,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
29007
29245
|
}
|
|
29008
29246
|
audioSrcPath = extractedPath;
|
|
29009
29247
|
} else {
|
|
29010
|
-
const trimmedPath =
|
|
29248
|
+
const trimmedPath = join27(workDir, `${element.id}-trimmed.wav`);
|
|
29011
29249
|
const prepResult = await prepareAudioTrack(
|
|
29012
29250
|
srcPath,
|
|
29013
29251
|
trimmedPath,
|
|
@@ -29061,9 +29299,9 @@ var init_audioMixer = __esm({
|
|
|
29061
29299
|
|
|
29062
29300
|
// ../engine/src/services/parallelCoordinator.ts
|
|
29063
29301
|
import { cpus as cpus2, freemem, totalmem as totalmem2 } from "os";
|
|
29064
|
-
import { existsSync as
|
|
29302
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync17, readdirSync as readdirSync11 } from "fs";
|
|
29065
29303
|
import { copyFile, rename } from "fs/promises";
|
|
29066
|
-
import { join as
|
|
29304
|
+
import { join as join28 } from "path";
|
|
29067
29305
|
function calculateOptimalWorkers(totalFrames, requested, config) {
|
|
29068
29306
|
const effectiveMaxWorkers = (() => {
|
|
29069
29307
|
const concurrency = config?.concurrency ?? DEFAULT_CONFIG2.concurrency;
|
|
@@ -29113,7 +29351,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
|
|
|
29113
29351
|
workerId: i2,
|
|
29114
29352
|
startFrame,
|
|
29115
29353
|
endFrame,
|
|
29116
|
-
outputDir:
|
|
29354
|
+
outputDir: join28(workDir, `worker-${i2}`)
|
|
29117
29355
|
});
|
|
29118
29356
|
}
|
|
29119
29357
|
return tasks;
|
|
@@ -29121,7 +29359,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
|
|
|
29121
29359
|
async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config) {
|
|
29122
29360
|
const startTime = Date.now();
|
|
29123
29361
|
let framesCaptured = 0;
|
|
29124
|
-
if (!
|
|
29362
|
+
if (!existsSync26(task.outputDir)) mkdirSync17(task.outputDir, { recursive: true });
|
|
29125
29363
|
let session = null;
|
|
29126
29364
|
let perf;
|
|
29127
29365
|
try {
|
|
@@ -29211,17 +29449,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
|
|
|
29211
29449
|
return results;
|
|
29212
29450
|
}
|
|
29213
29451
|
async function mergeWorkerFrames(workDir, tasks, outputDir) {
|
|
29214
|
-
if (!
|
|
29452
|
+
if (!existsSync26(outputDir)) mkdirSync17(outputDir, { recursive: true });
|
|
29215
29453
|
let totalFrames = 0;
|
|
29216
29454
|
const sortedTasks = [...tasks].sort((a, b) => a.startFrame - b.startFrame);
|
|
29217
29455
|
for (const task of sortedTasks) {
|
|
29218
|
-
if (!
|
|
29456
|
+
if (!existsSync26(task.outputDir)) {
|
|
29219
29457
|
continue;
|
|
29220
29458
|
}
|
|
29221
|
-
const files =
|
|
29459
|
+
const files = readdirSync11(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
|
|
29222
29460
|
const copyTasks = files.map(async (file) => {
|
|
29223
|
-
const sourcePath =
|
|
29224
|
-
const targetPath =
|
|
29461
|
+
const sourcePath = join28(task.outputDir, file);
|
|
29462
|
+
const targetPath = join28(outputDir, file);
|
|
29225
29463
|
try {
|
|
29226
29464
|
await rename(sourcePath, targetPath);
|
|
29227
29465
|
} catch {
|
|
@@ -29258,8 +29496,8 @@ var init_parallelCoordinator = __esm({
|
|
|
29258
29496
|
// ../engine/src/services/fileServer.ts
|
|
29259
29497
|
import { Hono as Hono2 } from "hono";
|
|
29260
29498
|
import { serve } from "@hono/node-server";
|
|
29261
|
-
import { readFileSync as readFileSync18, existsSync as
|
|
29262
|
-
import { join as
|
|
29499
|
+
import { readFileSync as readFileSync18, existsSync as existsSync27, statSync as statSync9 } from "fs";
|
|
29500
|
+
import { join as join29, extname as extname6 } from "path";
|
|
29263
29501
|
function stripEmbeddedRuntimeScripts(html) {
|
|
29264
29502
|
if (!html) return html;
|
|
29265
29503
|
const scriptRe = /<script\b[^>]*>[\s\S]*?<\/script>/gi;
|
|
@@ -29328,12 +29566,12 @@ function createFileServer(options) {
|
|
|
29328
29566
|
let requestPath = c2.req.path;
|
|
29329
29567
|
if (requestPath === "/") requestPath = "/index.html";
|
|
29330
29568
|
const relativePath = requestPath.replace(/^\//, "");
|
|
29331
|
-
const compiledPath = compiledDir ?
|
|
29569
|
+
const compiledPath = compiledDir ? join29(compiledDir, relativePath) : null;
|
|
29332
29570
|
const hasCompiledFile = Boolean(
|
|
29333
|
-
compiledPath &&
|
|
29571
|
+
compiledPath && existsSync27(compiledPath) && statSync9(compiledPath).isFile()
|
|
29334
29572
|
);
|
|
29335
|
-
const filePath = hasCompiledFile ? compiledPath :
|
|
29336
|
-
if (!
|
|
29573
|
+
const filePath = hasCompiledFile ? compiledPath : join29(projectDir, relativePath);
|
|
29574
|
+
if (!existsSync27(filePath) || !statSync9(filePath).isFile()) {
|
|
29337
29575
|
return c2.text("Not found", 404);
|
|
29338
29576
|
}
|
|
29339
29577
|
const ext = extname6(filePath).toLowerCase();
|
|
@@ -30638,9 +30876,9 @@ var init_shaderTransitions = __esm({
|
|
|
30638
30876
|
});
|
|
30639
30877
|
|
|
30640
30878
|
// ../engine/src/services/hdrCapture.ts
|
|
30641
|
-
import { existsSync as
|
|
30642
|
-
import { join as
|
|
30643
|
-
import { homedir as
|
|
30879
|
+
import { existsSync as existsSync28, readdirSync as readdirSync12 } from "fs";
|
|
30880
|
+
import { join as join30 } from "path";
|
|
30881
|
+
import { homedir as homedir7 } from "os";
|
|
30644
30882
|
function linearToPQ(L2) {
|
|
30645
30883
|
const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
|
|
30646
30884
|
const Lm1 = Math.pow(Lp, PQ_M12);
|
|
@@ -30755,12 +30993,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
|
|
|
30755
30993
|
return output;
|
|
30756
30994
|
}
|
|
30757
30995
|
function resolveHeadedChromePath() {
|
|
30758
|
-
const baseDir =
|
|
30759
|
-
if (!
|
|
30760
|
-
const versions =
|
|
30996
|
+
const baseDir = join30(homedir7(), ".cache", "puppeteer", "chrome");
|
|
30997
|
+
if (!existsSync28(baseDir)) return void 0;
|
|
30998
|
+
const versions = readdirSync12(baseDir).sort().reverse();
|
|
30761
30999
|
for (const version of versions) {
|
|
30762
31000
|
const candidates = [
|
|
30763
|
-
|
|
31001
|
+
join30(
|
|
30764
31002
|
baseDir,
|
|
30765
31003
|
version,
|
|
30766
31004
|
"chrome-mac-arm64",
|
|
@@ -30769,7 +31007,7 @@ function resolveHeadedChromePath() {
|
|
|
30769
31007
|
"MacOS",
|
|
30770
31008
|
"Google Chrome for Testing"
|
|
30771
31009
|
),
|
|
30772
|
-
|
|
31010
|
+
join30(
|
|
30773
31011
|
baseDir,
|
|
30774
31012
|
version,
|
|
30775
31013
|
"chrome-mac-x64",
|
|
@@ -30778,11 +31016,11 @@ function resolveHeadedChromePath() {
|
|
|
30778
31016
|
"MacOS",
|
|
30779
31017
|
"Google Chrome for Testing"
|
|
30780
31018
|
),
|
|
30781
|
-
|
|
30782
|
-
|
|
31019
|
+
join30(baseDir, version, "chrome-linux64", "chrome"),
|
|
31020
|
+
join30(baseDir, version, "chrome-win64", "chrome.exe")
|
|
30783
31021
|
];
|
|
30784
31022
|
for (const binary of candidates) {
|
|
30785
|
-
if (
|
|
31023
|
+
if (existsSync28(binary)) return binary;
|
|
30786
31024
|
}
|
|
30787
31025
|
}
|
|
30788
31026
|
return void 0;
|
|
@@ -31309,8 +31547,8 @@ var init_staticGuard = __esm({
|
|
|
31309
31547
|
});
|
|
31310
31548
|
|
|
31311
31549
|
// ../core/src/compiler/htmlBundler.ts
|
|
31312
|
-
import { readFileSync as readFileSync19, existsSync as
|
|
31313
|
-
import { join as
|
|
31550
|
+
import { readFileSync as readFileSync19, existsSync as existsSync29 } from "fs";
|
|
31551
|
+
import { join as join31, resolve as resolve12, isAbsolute as isAbsolute4, sep as sep2 } from "path";
|
|
31314
31552
|
import { transformSync } from "esbuild";
|
|
31315
31553
|
function parseHTMLContent2(html) {
|
|
31316
31554
|
const trimmed = html.trimStart().toLowerCase();
|
|
@@ -31378,7 +31616,7 @@ function isRelativeUrl(url) {
|
|
|
31378
31616
|
return !url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("//") && !url.startsWith("data:") && !isAbsolute4(url);
|
|
31379
31617
|
}
|
|
31380
31618
|
function safeReadFile(filePath) {
|
|
31381
|
-
if (!
|
|
31619
|
+
if (!existsSync29(filePath)) return null;
|
|
31382
31620
|
try {
|
|
31383
31621
|
return readFileSync19(filePath, "utf-8");
|
|
31384
31622
|
} catch {
|
|
@@ -31386,7 +31624,7 @@ function safeReadFile(filePath) {
|
|
|
31386
31624
|
}
|
|
31387
31625
|
}
|
|
31388
31626
|
function safeReadFileBuffer(filePath) {
|
|
31389
|
-
if (!
|
|
31627
|
+
if (!existsSync29(filePath)) return null;
|
|
31390
31628
|
try {
|
|
31391
31629
|
return readFileSync19(filePath);
|
|
31392
31630
|
} catch {
|
|
@@ -31585,8 +31823,8 @@ function stripJsCommentsParserSafe(source) {
|
|
|
31585
31823
|
}
|
|
31586
31824
|
}
|
|
31587
31825
|
async function bundleToSingleHtml(projectDir, options) {
|
|
31588
|
-
const indexPath =
|
|
31589
|
-
if (!
|
|
31826
|
+
const indexPath = join31(projectDir, "index.html");
|
|
31827
|
+
if (!existsSync29(indexPath)) throw new Error("index.html not found in project directory");
|
|
31590
31828
|
const rawHtml = readFileSync19(indexPath, "utf-8");
|
|
31591
31829
|
const compiled = await compileHtml(rawHtml, projectDir, options?.probeMediaDuration);
|
|
31592
31830
|
const staticGuard = validateHyperframeHtmlContract(compiled);
|
|
@@ -31741,6 +31979,15 @@ async function bundleToSingleHtml(projectDir, options) {
|
|
|
31741
31979
|
el.setAttribute(attr, val);
|
|
31742
31980
|
}
|
|
31743
31981
|
);
|
|
31982
|
+
const styledEls = innerRoot ? innerRoot.querySelectorAll("[style]") : contentDoc.querySelectorAll("[style]");
|
|
31983
|
+
rewriteInlineStyleAssetUrls(
|
|
31984
|
+
styledEls,
|
|
31985
|
+
src,
|
|
31986
|
+
(el) => el.getAttribute("style"),
|
|
31987
|
+
(el, val) => {
|
|
31988
|
+
el.setAttribute("style", val);
|
|
31989
|
+
}
|
|
31990
|
+
);
|
|
31744
31991
|
if (innerRoot) {
|
|
31745
31992
|
const innerW = innerRoot.getAttribute("data-width");
|
|
31746
31993
|
const innerH = innerRoot.getAttribute("data-height");
|
|
@@ -31904,7 +32151,7 @@ var init_compiler = __esm({
|
|
|
31904
32151
|
|
|
31905
32152
|
// ../producer/src/services/hyperframeRuntimeLoader.ts
|
|
31906
32153
|
import { createHash as createHash3 } from "crypto";
|
|
31907
|
-
import { existsSync as
|
|
32154
|
+
import { existsSync as existsSync30, readFileSync as readFileSync20 } from "fs";
|
|
31908
32155
|
import { dirname as dirname10, resolve as resolve13 } from "path";
|
|
31909
32156
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31910
32157
|
function resolveHyperframeManifestPath() {
|
|
@@ -31917,7 +32164,7 @@ function resolveHyperframeManifestPath() {
|
|
|
31917
32164
|
MODULE_RELATIVE_MANIFEST_PATH
|
|
31918
32165
|
];
|
|
31919
32166
|
for (const candidate of candidates) {
|
|
31920
|
-
if (
|
|
32167
|
+
if (existsSync30(candidate)) {
|
|
31921
32168
|
return candidate;
|
|
31922
32169
|
}
|
|
31923
32170
|
}
|
|
@@ -31928,7 +32175,7 @@ function getVerifiedHyperframeRuntimeSource() {
|
|
|
31928
32175
|
}
|
|
31929
32176
|
function resolveVerifiedHyperframeRuntime() {
|
|
31930
32177
|
const manifestPath = resolveHyperframeManifestPath();
|
|
31931
|
-
if (!
|
|
32178
|
+
if (!existsSync30(manifestPath)) {
|
|
31932
32179
|
throw new Error(
|
|
31933
32180
|
`[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
|
|
31934
32181
|
);
|
|
@@ -31942,7 +32189,7 @@ function resolveVerifiedHyperframeRuntime() {
|
|
|
31942
32189
|
);
|
|
31943
32190
|
}
|
|
31944
32191
|
const runtimePath = resolve13(dirname10(manifestPath), runtimeFileName);
|
|
31945
|
-
if (!
|
|
32192
|
+
if (!existsSync30(runtimePath)) {
|
|
31946
32193
|
throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
|
|
31947
32194
|
}
|
|
31948
32195
|
const runtimeSource = readFileSync20(runtimePath, "utf8");
|
|
@@ -31984,16 +32231,16 @@ var init_hyperframeRuntimeLoader = __esm({
|
|
|
31984
32231
|
// ../producer/src/services/fileServer.ts
|
|
31985
32232
|
import { Hono as Hono3 } from "hono";
|
|
31986
32233
|
import { serve as serve2 } from "@hono/node-server";
|
|
31987
|
-
import { readFileSync as readFileSync21, existsSync as
|
|
31988
|
-
import { join as
|
|
32234
|
+
import { readFileSync as readFileSync21, existsSync as existsSync31, realpathSync, statSync as statSync10 } from "fs";
|
|
32235
|
+
import { join as join32, extname as extname7, resolve as resolve14, sep as sep3 } from "path";
|
|
31989
32236
|
function isPathInside(child, parent, options = {}) {
|
|
31990
32237
|
const { resolveSymlinks = false, pathModule } = options;
|
|
31991
32238
|
const resolveFn = pathModule?.resolve ?? resolve14;
|
|
31992
32239
|
const separator = pathModule?.sep ?? sep3;
|
|
31993
32240
|
const resolvedChild = resolveFn(child);
|
|
31994
32241
|
const resolvedParent = resolveFn(parent);
|
|
31995
|
-
const normalizedChild = resolveSymlinks &&
|
|
31996
|
-
const normalizedParent = resolveSymlinks &&
|
|
32242
|
+
const normalizedChild = resolveSymlinks && existsSync31(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
|
|
32243
|
+
const normalizedParent = resolveSymlinks && existsSync31(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
|
|
31997
32244
|
if (normalizedChild === normalizedParent) return true;
|
|
31998
32245
|
const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
|
|
31999
32246
|
return normalizedChild.startsWith(parentWithSep);
|
|
@@ -32082,14 +32329,14 @@ function createFileServer2(options) {
|
|
|
32082
32329
|
const relativePath = requestPath.replace(/^\//, "");
|
|
32083
32330
|
let filePath = null;
|
|
32084
32331
|
if (compiledDir) {
|
|
32085
|
-
const candidate =
|
|
32086
|
-
if (
|
|
32332
|
+
const candidate = join32(compiledDir, relativePath);
|
|
32333
|
+
if (existsSync31(candidate) && isPathInside(candidate, compiledDir) && statSync10(candidate).isFile()) {
|
|
32087
32334
|
filePath = candidate;
|
|
32088
32335
|
}
|
|
32089
32336
|
}
|
|
32090
32337
|
if (!filePath) {
|
|
32091
|
-
const candidate =
|
|
32092
|
-
if (
|
|
32338
|
+
const candidate = join32(projectDir, relativePath);
|
|
32339
|
+
if (existsSync31(candidate) && isPathInside(candidate, projectDir) && statSync10(candidate).isFile()) {
|
|
32093
32340
|
filePath = candidate;
|
|
32094
32341
|
}
|
|
32095
32342
|
}
|
|
@@ -32463,7 +32710,7 @@ var init_ffprobe2 = __esm({
|
|
|
32463
32710
|
});
|
|
32464
32711
|
|
|
32465
32712
|
// ../producer/src/utils/paths.ts
|
|
32466
|
-
import { resolve as resolve15, basename as basename2, join as
|
|
32713
|
+
import { resolve as resolve15, basename as basename2, join as join33, relative as relative2, isAbsolute as isAbsolute5 } from "path";
|
|
32467
32714
|
function isPathInside2(childPath, parentPath) {
|
|
32468
32715
|
const absChild = resolve15(childPath);
|
|
32469
32716
|
const absParent = resolve15(parentPath);
|
|
@@ -32484,7 +32731,7 @@ function toExternalAssetKey(absPath) {
|
|
|
32484
32731
|
function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
|
|
32485
32732
|
const absoluteProjectDir = resolve15(projectDir);
|
|
32486
32733
|
const projectName = basename2(absoluteProjectDir);
|
|
32487
|
-
const resolvedOutputPath = outputPath ??
|
|
32734
|
+
const resolvedOutputPath = outputPath ?? join33(rendersDir, `${projectName}.mp4`);
|
|
32488
32735
|
const absoluteOutputPath = resolve15(resolvedOutputPath);
|
|
32489
32736
|
return { absoluteProjectDir, absoluteOutputPath };
|
|
32490
32737
|
}
|
|
@@ -32557,9 +32804,9 @@ var init_fontData_generated = __esm({
|
|
|
32557
32804
|
});
|
|
32558
32805
|
|
|
32559
32806
|
// ../producer/src/services/deterministicFonts.ts
|
|
32560
|
-
import { existsSync as
|
|
32561
|
-
import { homedir as
|
|
32562
|
-
import { join as
|
|
32807
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync18, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
|
|
32808
|
+
import { homedir as homedir8 } from "os";
|
|
32809
|
+
import { join as join34 } from "path";
|
|
32563
32810
|
function normalizeFamilyName(family) {
|
|
32564
32811
|
return family.trim().replace(/^['"]|['"]$/g, "").trim().toLowerCase();
|
|
32565
32812
|
}
|
|
@@ -32670,14 +32917,14 @@ function fontSlug(familyName) {
|
|
|
32670
32917
|
return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
32671
32918
|
}
|
|
32672
32919
|
function fontCacheDir(slug) {
|
|
32673
|
-
const dir =
|
|
32674
|
-
if (!
|
|
32920
|
+
const dir = join34(GOOGLE_FONTS_CACHE_DIR, slug);
|
|
32921
|
+
if (!existsSync32(dir)) {
|
|
32675
32922
|
mkdirSync18(dir, { recursive: true });
|
|
32676
32923
|
}
|
|
32677
32924
|
return dir;
|
|
32678
32925
|
}
|
|
32679
32926
|
function cachedWoff2Path(slug, weight, style) {
|
|
32680
|
-
return
|
|
32927
|
+
return join34(fontCacheDir(slug), `${weight}-${style}.woff2`);
|
|
32681
32928
|
}
|
|
32682
32929
|
async function fetchGoogleFont(familyName) {
|
|
32683
32930
|
const slug = fontSlug(familyName);
|
|
@@ -32703,7 +32950,7 @@ async function fetchGoogleFont(familyName) {
|
|
|
32703
32950
|
const woff2Url = match[3] || "";
|
|
32704
32951
|
if (!woff2Url) continue;
|
|
32705
32952
|
const cachePath2 = cachedWoff2Path(slug, weight, style);
|
|
32706
|
-
if (!
|
|
32953
|
+
if (!existsSync32(cachePath2)) {
|
|
32707
32954
|
try {
|
|
32708
32955
|
const fontRes = await fetch(woff2Url);
|
|
32709
32956
|
if (!fontRes.ok) continue;
|
|
@@ -32889,14 +33136,14 @@ var init_deterministicFonts = __esm({
|
|
|
32889
33136
|
poppins: "poppins",
|
|
32890
33137
|
"segoe ui": "roboto"
|
|
32891
33138
|
};
|
|
32892
|
-
GOOGLE_FONTS_CACHE_DIR =
|
|
33139
|
+
GOOGLE_FONTS_CACHE_DIR = join34(homedir8(), ".cache", "hyperframes", "fonts");
|
|
32893
33140
|
WOFF2_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
|
|
32894
33141
|
}
|
|
32895
33142
|
});
|
|
32896
33143
|
|
|
32897
33144
|
// ../producer/src/services/htmlCompiler.ts
|
|
32898
|
-
import { readFileSync as readFileSync23, existsSync as
|
|
32899
|
-
import { join as
|
|
33145
|
+
import { readFileSync as readFileSync23, existsSync as existsSync33, mkdirSync as mkdirSync19 } from "fs";
|
|
33146
|
+
import { join as join35, dirname as dirname11, resolve as resolve16 } from "path";
|
|
32900
33147
|
function dedupeElementsById(elements) {
|
|
32901
33148
|
const deduped = /* @__PURE__ */ new Map();
|
|
32902
33149
|
for (const element of elements) {
|
|
@@ -32957,16 +33204,16 @@ function detectShaderTransitionUsage(html) {
|
|
|
32957
33204
|
async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
|
|
32958
33205
|
let filePath = src;
|
|
32959
33206
|
if (isHttpUrl(src)) {
|
|
32960
|
-
if (!
|
|
33207
|
+
if (!existsSync33(downloadDir)) mkdirSync19(downloadDir, { recursive: true });
|
|
32961
33208
|
try {
|
|
32962
33209
|
filePath = await downloadToTemp(src, downloadDir);
|
|
32963
33210
|
} catch {
|
|
32964
33211
|
return { duration: 0, resolvedPath: src };
|
|
32965
33212
|
}
|
|
32966
33213
|
} else if (!filePath.startsWith("/")) {
|
|
32967
|
-
filePath =
|
|
33214
|
+
filePath = join35(baseDir, filePath);
|
|
32968
33215
|
}
|
|
32969
|
-
if (!
|
|
33216
|
+
if (!existsSync33(filePath)) {
|
|
32970
33217
|
return { duration: 0, resolvedPath: filePath };
|
|
32971
33218
|
}
|
|
32972
33219
|
let metadata;
|
|
@@ -33044,7 +33291,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
|
|
|
33044
33291
|
if (visited.has(filePath)) {
|
|
33045
33292
|
continue;
|
|
33046
33293
|
}
|
|
33047
|
-
if (!
|
|
33294
|
+
if (!existsSync33(filePath)) {
|
|
33048
33295
|
continue;
|
|
33049
33296
|
}
|
|
33050
33297
|
const rawSubHtml = readFileSync23(filePath, "utf-8");
|
|
@@ -33233,7 +33480,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
|
|
|
33233
33480
|
let compHtml = subCompositions.get(srcPath) || null;
|
|
33234
33481
|
if (!compHtml) {
|
|
33235
33482
|
const filePath = resolve16(projectDir, srcPath);
|
|
33236
|
-
if (
|
|
33483
|
+
if (existsSync33(filePath)) {
|
|
33237
33484
|
compHtml = readFileSync23(filePath, "utf-8");
|
|
33238
33485
|
}
|
|
33239
33486
|
}
|
|
@@ -33435,7 +33682,7 @@ function collectExternalAssets(html, projectDir) {
|
|
|
33435
33682
|
if (isPathInside2(absPath, absProjectDir)) {
|
|
33436
33683
|
return null;
|
|
33437
33684
|
}
|
|
33438
|
-
if (!
|
|
33685
|
+
if (!existsSync33(absPath)) return null;
|
|
33439
33686
|
const safeKey = toExternalAssetKey(absPath);
|
|
33440
33687
|
externalAssets.set(safeKey, absPath);
|
|
33441
33688
|
return safeKey;
|
|
@@ -33786,20 +34033,20 @@ var init_hdrImageTransferCache = __esm({
|
|
|
33786
34033
|
|
|
33787
34034
|
// ../producer/src/services/renderOrchestrator.ts
|
|
33788
34035
|
import {
|
|
33789
|
-
existsSync as
|
|
34036
|
+
existsSync as existsSync34,
|
|
33790
34037
|
mkdirSync as mkdirSync20,
|
|
33791
34038
|
rmSync as rmSync7,
|
|
33792
34039
|
readFileSync as readFileSync24,
|
|
33793
34040
|
openSync,
|
|
33794
34041
|
readSync,
|
|
33795
34042
|
closeSync,
|
|
33796
|
-
readdirSync as
|
|
33797
|
-
statSync as
|
|
34043
|
+
readdirSync as readdirSync13,
|
|
34044
|
+
statSync as statSync11,
|
|
33798
34045
|
writeFileSync as writeFileSync15,
|
|
33799
34046
|
copyFileSync as copyFileSync2,
|
|
33800
34047
|
appendFileSync
|
|
33801
34048
|
} from "fs";
|
|
33802
|
-
import { join as
|
|
34049
|
+
import { join as join36, dirname as dirname12, resolve as resolve17 } from "path";
|
|
33803
34050
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
33804
34051
|
import { freemem as freemem2 } from "os";
|
|
33805
34052
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -33820,14 +34067,14 @@ function sampleDirectoryBytes(dir) {
|
|
|
33820
34067
|
if (!current) continue;
|
|
33821
34068
|
let entries2 = [];
|
|
33822
34069
|
try {
|
|
33823
|
-
entries2 =
|
|
34070
|
+
entries2 = readdirSync13(current);
|
|
33824
34071
|
} catch {
|
|
33825
34072
|
continue;
|
|
33826
34073
|
}
|
|
33827
34074
|
for (const name of entries2) {
|
|
33828
|
-
const full =
|
|
34075
|
+
const full = join36(current, name);
|
|
33829
34076
|
try {
|
|
33830
|
-
const st2 =
|
|
34077
|
+
const st2 = statSync11(full);
|
|
33831
34078
|
if (st2.isDirectory()) {
|
|
33832
34079
|
stack.push(full);
|
|
33833
34080
|
} else if (st2.isFile()) {
|
|
@@ -33988,16 +34235,16 @@ function installDebugLogger(logPath, log2 = defaultLogger) {
|
|
|
33988
34235
|
};
|
|
33989
34236
|
}
|
|
33990
34237
|
function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
33991
|
-
const compileDir =
|
|
34238
|
+
const compileDir = join36(workDir, "compiled");
|
|
33992
34239
|
mkdirSync20(compileDir, { recursive: true });
|
|
33993
|
-
writeFileSync15(
|
|
34240
|
+
writeFileSync15(join36(compileDir, "index.html"), compiled.html, "utf-8");
|
|
33994
34241
|
for (const [srcPath, html] of compiled.subCompositions) {
|
|
33995
|
-
const outPath =
|
|
34242
|
+
const outPath = join36(compileDir, srcPath);
|
|
33996
34243
|
mkdirSync20(dirname12(outPath), { recursive: true });
|
|
33997
34244
|
writeFileSync15(outPath, html, "utf-8");
|
|
33998
34245
|
}
|
|
33999
34246
|
for (const [relativePath, absolutePath] of compiled.externalAssets) {
|
|
34000
|
-
const outPath = resolve17(
|
|
34247
|
+
const outPath = resolve17(join36(compileDir, relativePath));
|
|
34001
34248
|
if (!isPathInside2(outPath, compileDir)) {
|
|
34002
34249
|
console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
|
|
34003
34250
|
continue;
|
|
@@ -34028,7 +34275,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
34028
34275
|
renderModeHints: compiled.renderModeHints,
|
|
34029
34276
|
hasShaderTransitions: compiled.hasShaderTransitions
|
|
34030
34277
|
};
|
|
34031
|
-
writeFileSync15(
|
|
34278
|
+
writeFileSync15(join36(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
|
|
34032
34279
|
}
|
|
34033
34280
|
}
|
|
34034
34281
|
function applyRenderModeHints(cfg, compiled, log2 = defaultLogger) {
|
|
@@ -34154,8 +34401,8 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
|
|
|
34154
34401
|
const ranges = [];
|
|
34155
34402
|
let rangeStart = null;
|
|
34156
34403
|
for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
|
|
34157
|
-
const framePath =
|
|
34158
|
-
const missing = !
|
|
34404
|
+
const framePath = join36(framesDir, `frame_${String(frameIndex).padStart(6, "0")}.${frameExt}`);
|
|
34405
|
+
const missing = !existsSync34(framePath);
|
|
34159
34406
|
if (missing && rangeStart === null) {
|
|
34160
34407
|
rangeStart = frameIndex;
|
|
34161
34408
|
} else if (!missing && rangeStart !== null) {
|
|
@@ -34177,7 +34424,7 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt) {
|
|
|
34177
34424
|
workerId,
|
|
34178
34425
|
startFrame: range.startFrame,
|
|
34179
34426
|
endFrame: range.endFrame,
|
|
34180
|
-
outputDir:
|
|
34427
|
+
outputDir: join36(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`)
|
|
34181
34428
|
}));
|
|
34182
34429
|
batches.push(batch);
|
|
34183
34430
|
}
|
|
@@ -34201,8 +34448,8 @@ function shouldFallbackToScreenshotAfterCalibrationError(error) {
|
|
|
34201
34448
|
function countCapturedFrames(totalFrames, framesDir, frameExt) {
|
|
34202
34449
|
let captured = 0;
|
|
34203
34450
|
for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
|
|
34204
|
-
const framePath =
|
|
34205
|
-
if (
|
|
34451
|
+
const framePath = join36(framesDir, `frame_${String(frameIndex).padStart(6, "0")}.${frameExt}`);
|
|
34452
|
+
if (existsSync34(framePath)) captured++;
|
|
34206
34453
|
}
|
|
34207
34454
|
return captured;
|
|
34208
34455
|
}
|
|
@@ -34239,7 +34486,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
|
|
|
34239
34486
|
frameCount,
|
|
34240
34487
|
reason: attempt === 0 ? "initial" : "retry"
|
|
34241
34488
|
});
|
|
34242
|
-
const attemptWorkDir =
|
|
34489
|
+
const attemptWorkDir = join36(options.workDir, `capture-attempt-${attempt}`);
|
|
34243
34490
|
const batches = missingRanges ? buildMissingFrameRetryBatches(missingRanges, currentWorkers, attemptWorkDir, attempt) : [distributeFrames(options.totalFrames, currentWorkers, attemptWorkDir)];
|
|
34244
34491
|
try {
|
|
34245
34492
|
for (const tasks of batches) {
|
|
@@ -34656,7 +34903,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
|
|
|
34656
34903
|
if (shouldLog && debugDumpDir) {
|
|
34657
34904
|
const after2 = countNonZeroRgb48(canvas);
|
|
34658
34905
|
const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
|
|
34659
|
-
const dumpPath =
|
|
34906
|
+
const dumpPath = join36(debugDumpDir, dumpName);
|
|
34660
34907
|
writeFileSync15(dumpPath, domPng);
|
|
34661
34908
|
log2.info("[diag] dom layer blit", {
|
|
34662
34909
|
frame: debugFrameIndex,
|
|
@@ -34730,8 +34977,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
|
|
|
34730
34977
|
async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
|
|
34731
34978
|
const moduleDir = dirname12(fileURLToPath3(import.meta.url));
|
|
34732
34979
|
const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve17(process.env.PRODUCER_RENDERS_DIR, "..") : resolve17(moduleDir, "../..");
|
|
34733
|
-
const debugDir =
|
|
34734
|
-
const workDir = job.config.debug ?
|
|
34980
|
+
const debugDir = join36(producerRoot, ".debug");
|
|
34981
|
+
const workDir = job.config.debug ? join36(debugDir, job.id) : join36(dirname12(outputPath), `work-${job.id}`);
|
|
34735
34982
|
const pipelineStart = Date.now();
|
|
34736
34983
|
const log2 = job.config.logger ?? defaultLogger;
|
|
34737
34984
|
let fileServer = null;
|
|
@@ -34744,7 +34991,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34744
34991
|
imageDecodeFailures: 0
|
|
34745
34992
|
};
|
|
34746
34993
|
let hdrPerf;
|
|
34747
|
-
const perfOutputPath =
|
|
34994
|
+
const perfOutputPath = join36(workDir, "perf-summary.json");
|
|
34748
34995
|
const cfg = { ...job.config.producerConfig ?? resolveConfig() };
|
|
34749
34996
|
const outputFormat = job.config.format ?? "mp4";
|
|
34750
34997
|
const isWebm = outputFormat === "webm";
|
|
@@ -34778,22 +35025,22 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34778
35025
|
};
|
|
34779
35026
|
job.startedAt = /* @__PURE__ */ new Date();
|
|
34780
35027
|
assertNotAborted();
|
|
34781
|
-
if (!
|
|
35028
|
+
if (!existsSync34(workDir)) mkdirSync20(workDir, { recursive: true });
|
|
34782
35029
|
if (job.config.debug) {
|
|
34783
|
-
const logPath =
|
|
35030
|
+
const logPath = join36(workDir, "render.log");
|
|
34784
35031
|
restoreLogger = installDebugLogger(logPath, log2);
|
|
34785
35032
|
}
|
|
34786
35033
|
const entryFile = job.config.entryFile || "index.html";
|
|
34787
|
-
let htmlPath =
|
|
34788
|
-
if (!
|
|
35034
|
+
let htmlPath = join36(projectDir, entryFile);
|
|
35035
|
+
if (!existsSync34(htmlPath)) {
|
|
34789
35036
|
throw new Error(`Entry file not found: ${htmlPath}`);
|
|
34790
35037
|
}
|
|
34791
35038
|
assertNotAborted();
|
|
34792
35039
|
const rawEntry = readFileSync24(htmlPath, "utf-8");
|
|
34793
35040
|
if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
|
|
34794
|
-
const wrapperPath =
|
|
34795
|
-
const projectIndexPath =
|
|
34796
|
-
if (!
|
|
35041
|
+
const wrapperPath = join36(workDir, "standalone-entry.html");
|
|
35042
|
+
const projectIndexPath = join36(projectDir, "index.html");
|
|
35043
|
+
if (!existsSync34(projectIndexPath)) {
|
|
34797
35044
|
throw new Error(
|
|
34798
35045
|
`Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
|
|
34799
35046
|
);
|
|
@@ -34816,7 +35063,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34816
35063
|
const stage1Start = Date.now();
|
|
34817
35064
|
updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
|
|
34818
35065
|
const compileStart = Date.now();
|
|
34819
|
-
let compiled = await compileForRender(projectDir, htmlPath,
|
|
35066
|
+
let compiled = await compileForRender(projectDir, htmlPath, join36(workDir, "downloads"));
|
|
34820
35067
|
assertNotAborted();
|
|
34821
35068
|
perfStages.compileOnlyMs = Date.now() - compileStart;
|
|
34822
35069
|
applyRenderModeHints(cfg, compiled, log2);
|
|
@@ -34848,7 +35095,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34848
35095
|
reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
|
|
34849
35096
|
fileServer = await createFileServer2({
|
|
34850
35097
|
projectDir,
|
|
34851
|
-
compiledDir:
|
|
35098
|
+
compiledDir: join36(workDir, "compiled"),
|
|
34852
35099
|
port: 0,
|
|
34853
35100
|
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
34854
35101
|
});
|
|
@@ -34862,7 +35109,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34862
35109
|
};
|
|
34863
35110
|
probeSession = await createCaptureSession(
|
|
34864
35111
|
fileServer.url,
|
|
34865
|
-
|
|
35112
|
+
join36(workDir, "probe"),
|
|
34866
35113
|
captureOpts,
|
|
34867
35114
|
null,
|
|
34868
35115
|
cfg
|
|
@@ -34894,7 +35141,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34894
35141
|
compiled,
|
|
34895
35142
|
resolutions,
|
|
34896
35143
|
projectDir,
|
|
34897
|
-
|
|
35144
|
+
join36(workDir, "downloads")
|
|
34898
35145
|
);
|
|
34899
35146
|
assertNotAborted();
|
|
34900
35147
|
composition.videos = compiled.videos;
|
|
@@ -35048,7 +35295,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35048
35295
|
const stage2Start = Date.now();
|
|
35049
35296
|
updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
|
|
35050
35297
|
let frameLookup = null;
|
|
35051
|
-
const compiledDir =
|
|
35298
|
+
const compiledDir = join36(workDir, "compiled");
|
|
35052
35299
|
let extractionResult = null;
|
|
35053
35300
|
const nativeHdrVideoIds = /* @__PURE__ */ new Set();
|
|
35054
35301
|
const videoTransfers = /* @__PURE__ */ new Map();
|
|
@@ -35057,10 +35304,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35057
35304
|
composition.videos.map(async (v) => {
|
|
35058
35305
|
let videoPath = v.src;
|
|
35059
35306
|
if (!videoPath.startsWith("/")) {
|
|
35060
|
-
const fromCompiled =
|
|
35307
|
+
const fromCompiled = existsSync34(join36(compiledDir, videoPath)) ? join36(compiledDir, videoPath) : join36(projectDir, videoPath);
|
|
35061
35308
|
videoPath = fromCompiled;
|
|
35062
35309
|
}
|
|
35063
|
-
if (!
|
|
35310
|
+
if (!existsSync34(videoPath)) return;
|
|
35064
35311
|
const meta = await extractMediaMetadata(videoPath);
|
|
35065
35312
|
if (isHdrColorSpace(meta.colorSpace)) {
|
|
35066
35313
|
nativeHdrVideoIds.add(v.id);
|
|
@@ -35078,10 +35325,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35078
35325
|
composition.images.map(async (img) => {
|
|
35079
35326
|
let imgPath = img.src;
|
|
35080
35327
|
if (!imgPath.startsWith("/")) {
|
|
35081
|
-
const fromCompiled =
|
|
35328
|
+
const fromCompiled = existsSync34(join36(compiledDir, imgPath)) ? join36(compiledDir, imgPath) : join36(projectDir, imgPath);
|
|
35082
35329
|
imgPath = fromCompiled;
|
|
35083
35330
|
}
|
|
35084
|
-
if (!
|
|
35331
|
+
if (!existsSync34(imgPath)) return null;
|
|
35085
35332
|
const meta = await extractMediaMetadata(imgPath);
|
|
35086
35333
|
if (isHdrColorSpace(meta.colorSpace)) {
|
|
35087
35334
|
nativeHdrImageIds.add(img.id);
|
|
@@ -35097,7 +35344,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35097
35344
|
extractionResult = await extractAllVideoFrames(
|
|
35098
35345
|
composition.videos,
|
|
35099
35346
|
projectDir,
|
|
35100
|
-
{ fps: job.config.fps, outputDir:
|
|
35347
|
+
{ fps: job.config.fps, outputDir: join36(workDir, "video-frames") },
|
|
35101
35348
|
abortSignal,
|
|
35102
35349
|
{ extractCacheDir: cfg.extractCacheDir },
|
|
35103
35350
|
compiledDir
|
|
@@ -35180,13 +35427,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35180
35427
|
}
|
|
35181
35428
|
const stage3Start = Date.now();
|
|
35182
35429
|
updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
|
|
35183
|
-
const audioOutputPath =
|
|
35430
|
+
const audioOutputPath = join36(workDir, "audio.aac");
|
|
35184
35431
|
let hasAudio = false;
|
|
35185
35432
|
if (composition.audios.length > 0) {
|
|
35186
35433
|
const audioResult = await processCompositionAudio(
|
|
35187
35434
|
composition.audios,
|
|
35188
35435
|
projectDir,
|
|
35189
|
-
|
|
35436
|
+
join36(workDir, "audio-work"),
|
|
35190
35437
|
audioOutputPath,
|
|
35191
35438
|
job.duration,
|
|
35192
35439
|
abortSignal,
|
|
@@ -35204,14 +35451,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35204
35451
|
if (!fileServer) {
|
|
35205
35452
|
fileServer = await createFileServer2({
|
|
35206
35453
|
projectDir,
|
|
35207
|
-
compiledDir:
|
|
35454
|
+
compiledDir: join36(workDir, "compiled"),
|
|
35208
35455
|
port: 0,
|
|
35209
35456
|
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
35210
35457
|
});
|
|
35211
35458
|
assertNotAborted();
|
|
35212
35459
|
}
|
|
35213
|
-
const framesDir =
|
|
35214
|
-
if (!
|
|
35460
|
+
const framesDir = join36(workDir, "captured-frames");
|
|
35461
|
+
if (!existsSync34(framesDir)) mkdirSync20(framesDir, { recursive: true });
|
|
35215
35462
|
const captureOptions = {
|
|
35216
35463
|
width,
|
|
35217
35464
|
height,
|
|
@@ -35226,7 +35473,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35226
35473
|
let captureCalibration;
|
|
35227
35474
|
let switchedToScreenshotAfterCalibration = false;
|
|
35228
35475
|
if (job.config.workers === void 0 && totalFrames >= 60) {
|
|
35229
|
-
const calibrationDir =
|
|
35476
|
+
const calibrationDir = join36(workDir, "capture-calibration");
|
|
35230
35477
|
const calibrationCfg = createCaptureCalibrationConfig(cfg);
|
|
35231
35478
|
const videoInjector = createVideoFrameInjector(frameLookup);
|
|
35232
35479
|
let calibrationSession = null;
|
|
@@ -35325,7 +35572,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35325
35572
|
"png-sequence": ""
|
|
35326
35573
|
};
|
|
35327
35574
|
const videoExt = FORMAT_EXT2[outputFormat] ?? ".mp4";
|
|
35328
|
-
const videoOnlyPath =
|
|
35575
|
+
const videoOnlyPath = join36(workDir, `video-only${videoExt}`);
|
|
35329
35576
|
const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
|
|
35330
35577
|
const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
|
|
35331
35578
|
const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
|
|
@@ -35349,8 +35596,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35349
35596
|
if (!hdrVideoIds.includes(v.id)) continue;
|
|
35350
35597
|
let srcPath = v.src;
|
|
35351
35598
|
if (!srcPath.startsWith("/")) {
|
|
35352
|
-
const fromCompiled =
|
|
35353
|
-
srcPath =
|
|
35599
|
+
const fromCompiled = join36(compiledDir, srcPath);
|
|
35600
|
+
srcPath = existsSync34(fromCompiled) ? fromCompiled : join36(projectDir, srcPath);
|
|
35354
35601
|
}
|
|
35355
35602
|
hdrVideoSrcPaths.set(v.id, srcPath);
|
|
35356
35603
|
}
|
|
@@ -35480,11 +35727,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35480
35727
|
for (const [videoId, srcPath] of hdrVideoSrcPaths) {
|
|
35481
35728
|
const video = composition.videos.find((v) => v.id === videoId);
|
|
35482
35729
|
if (!video) continue;
|
|
35483
|
-
const frameDir =
|
|
35730
|
+
const frameDir = join36(framesDir, `hdr_${videoId}`);
|
|
35484
35731
|
mkdirSync20(frameDir, { recursive: true });
|
|
35485
35732
|
const duration = video.end - video.start;
|
|
35486
35733
|
const dims = hdrExtractionDims.get(videoId) ?? { width, height };
|
|
35487
|
-
const rawPath =
|
|
35734
|
+
const rawPath = join36(frameDir, "frames.rgb48le");
|
|
35488
35735
|
const ffmpegArgs = [
|
|
35489
35736
|
"-ss",
|
|
35490
35737
|
String(video.mediaStart),
|
|
@@ -35516,7 +35763,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35516
35763
|
);
|
|
35517
35764
|
}
|
|
35518
35765
|
const frameSize = dims.width * dims.height * 6;
|
|
35519
|
-
const frameCount = Math.floor(
|
|
35766
|
+
const frameCount = Math.floor(statSync11(rawPath).size / frameSize);
|
|
35520
35767
|
if (frameCount < 1) {
|
|
35521
35768
|
hdrDiagnostics.videoExtractionFailures += 1;
|
|
35522
35769
|
throw new Error(
|
|
@@ -35586,8 +35833,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35586
35833
|
}
|
|
35587
35834
|
}
|
|
35588
35835
|
const debugDumpEnabled = process.env.KEEP_TEMP === "1";
|
|
35589
|
-
const debugDumpDir = debugDumpEnabled ?
|
|
35590
|
-
if (debugDumpDir && !
|
|
35836
|
+
const debugDumpDir = debugDumpEnabled ? join36(framesDir, "debug-composite") : null;
|
|
35837
|
+
if (debugDumpDir && !existsSync34(debugDumpDir)) {
|
|
35591
35838
|
mkdirSync20(debugDumpDir, { recursive: true });
|
|
35592
35839
|
}
|
|
35593
35840
|
if (!effectiveHdr) {
|
|
@@ -35771,7 +36018,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
35771
36018
|
);
|
|
35772
36019
|
addHdrTiming(hdrPerf, "normalCompositeMs", timingStart);
|
|
35773
36020
|
if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
|
|
35774
|
-
const previewPath =
|
|
36021
|
+
const previewPath = join36(
|
|
35775
36022
|
debugDumpDir,
|
|
35776
36023
|
`frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`
|
|
35777
36024
|
);
|
|
@@ -36049,19 +36296,19 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
36049
36296
|
if (isPngSequence) {
|
|
36050
36297
|
const stage5Start = Date.now();
|
|
36051
36298
|
updateJobStatus(job, "encoding", "Writing PNG sequence", 75, onProgress);
|
|
36052
|
-
if (!
|
|
36053
|
-
const captured =
|
|
36299
|
+
if (!existsSync34(outputPath)) mkdirSync20(outputPath, { recursive: true });
|
|
36300
|
+
const captured = readdirSync13(framesDir).filter((name) => name.endsWith(".png")).sort();
|
|
36054
36301
|
if (captured.length === 0) {
|
|
36055
36302
|
throw new Error(
|
|
36056
36303
|
`[Render] png-sequence output requested but no PNGs were captured to ${framesDir}`
|
|
36057
36304
|
);
|
|
36058
36305
|
}
|
|
36059
36306
|
captured.forEach((name, i2) => {
|
|
36060
|
-
const dst =
|
|
36061
|
-
copyFileSync2(
|
|
36307
|
+
const dst = join36(outputPath, `frame_${String(i2 + 1).padStart(6, "0")}.png`);
|
|
36308
|
+
copyFileSync2(join36(framesDir, name), dst);
|
|
36062
36309
|
});
|
|
36063
|
-
if (hasAudio &&
|
|
36064
|
-
copyFileSync2(audioOutputPath,
|
|
36310
|
+
if (hasAudio && existsSync34(audioOutputPath)) {
|
|
36311
|
+
copyFileSync2(audioOutputPath, join36(outputPath, "audio.aac"));
|
|
36065
36312
|
log2.info(
|
|
36066
36313
|
`[Render] png-sequence: audio.aac sidecar written to ${outputPath}/audio.aac`
|
|
36067
36314
|
);
|
|
@@ -36153,7 +36400,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
36153
36400
|
updateJobStatus(job, "complete", "Render complete", 100, onProgress);
|
|
36154
36401
|
const totalElapsed = Date.now() - pipelineStart;
|
|
36155
36402
|
sampleMemory();
|
|
36156
|
-
const tmpPeakBytes =
|
|
36403
|
+
const tmpPeakBytes = existsSync34(workDir) ? sampleDirectoryBytes(workDir) : 0;
|
|
36157
36404
|
const perfSummary = {
|
|
36158
36405
|
renderId: job.id,
|
|
36159
36406
|
totalElapsedMs: totalElapsed,
|
|
@@ -36195,8 +36442,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
36195
36442
|
}
|
|
36196
36443
|
}
|
|
36197
36444
|
if (job.config.debug) {
|
|
36198
|
-
if (!isPngSequence &&
|
|
36199
|
-
const debugOutput =
|
|
36445
|
+
if (!isPngSequence && existsSync34(outputPath)) {
|
|
36446
|
+
const debugOutput = join36(workDir, `output${videoExt}`);
|
|
36200
36447
|
copyFileSync2(outputPath, debugOutput);
|
|
36201
36448
|
}
|
|
36202
36449
|
} else if (process.env.KEEP_TEMP === "1") {
|
|
@@ -36282,7 +36529,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
36282
36529
|
await safeCleanup(
|
|
36283
36530
|
"remove workDir (error)",
|
|
36284
36531
|
() => {
|
|
36285
|
-
if (
|
|
36532
|
+
if (existsSync34(workDir)) rmSync7(workDir, { recursive: true, force: true });
|
|
36286
36533
|
},
|
|
36287
36534
|
log2
|
|
36288
36535
|
);
|
|
@@ -36344,8 +36591,8 @@ var init_config3 = __esm({
|
|
|
36344
36591
|
});
|
|
36345
36592
|
|
|
36346
36593
|
// ../producer/src/services/hyperframeLint.ts
|
|
36347
|
-
import { existsSync as
|
|
36348
|
-
import { resolve as resolve18, join as
|
|
36594
|
+
import { existsSync as existsSync35, readFileSync as readFileSync25, statSync as statSync12 } from "fs";
|
|
36595
|
+
import { resolve as resolve18, join as join37 } from "path";
|
|
36349
36596
|
function isStringRecord(value) {
|
|
36350
36597
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
36351
36598
|
return false;
|
|
@@ -36373,7 +36620,7 @@ function pickEntryFile(files, preferredEntryFile) {
|
|
|
36373
36620
|
}
|
|
36374
36621
|
function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
36375
36622
|
const absProjectDir = resolve18(projectDir);
|
|
36376
|
-
if (!
|
|
36623
|
+
if (!existsSync35(absProjectDir) || !statSync12(absProjectDir).isDirectory()) {
|
|
36377
36624
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
36378
36625
|
}
|
|
36379
36626
|
const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
|
|
@@ -36384,7 +36631,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
|
36384
36631
|
if (!absoluteEntryPath.startsWith(absProjectDir)) {
|
|
36385
36632
|
return { error: `Entry file must stay inside project directory: ${entryFile}` };
|
|
36386
36633
|
}
|
|
36387
|
-
if (
|
|
36634
|
+
if (existsSync35(absoluteEntryPath) && statSync12(absoluteEntryPath).isFile()) {
|
|
36388
36635
|
return {
|
|
36389
36636
|
entryFile,
|
|
36390
36637
|
html: readFileSync25(absoluteEntryPath, "utf-8"),
|
|
@@ -36393,7 +36640,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
|
36393
36640
|
}
|
|
36394
36641
|
}
|
|
36395
36642
|
return {
|
|
36396
|
-
error: `No HTML entry file found in project directory: ${
|
|
36643
|
+
error: `No HTML entry file found in project directory: ${join37(absProjectDir, preferredEntryFile || "index.html")}`
|
|
36397
36644
|
};
|
|
36398
36645
|
}
|
|
36399
36646
|
function prepareHyperframeLintBody(body) {
|
|
@@ -36481,15 +36728,15 @@ var init_semaphore = __esm({
|
|
|
36481
36728
|
|
|
36482
36729
|
// ../producer/src/server.ts
|
|
36483
36730
|
import {
|
|
36484
|
-
existsSync as
|
|
36731
|
+
existsSync as existsSync36,
|
|
36485
36732
|
mkdirSync as mkdirSync21,
|
|
36486
|
-
statSync as
|
|
36733
|
+
statSync as statSync13,
|
|
36487
36734
|
mkdtempSync as mkdtempSync2,
|
|
36488
36735
|
writeFileSync as writeFileSync16,
|
|
36489
36736
|
rmSync as rmSync8,
|
|
36490
36737
|
createReadStream
|
|
36491
36738
|
} from "fs";
|
|
36492
|
-
import { resolve as resolve19, dirname as dirname13, join as
|
|
36739
|
+
import { resolve as resolve19, dirname as dirname13, join as join38 } from "path";
|
|
36493
36740
|
import { tmpdir as tmpdir3 } from "os";
|
|
36494
36741
|
import { parseArgs as parseArgs2 } from "util";
|
|
36495
36742
|
import crypto2 from "crypto";
|
|
@@ -36512,11 +36759,11 @@ async function prepareRenderBody(body) {
|
|
|
36512
36759
|
const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
|
|
36513
36760
|
if (projectDir) {
|
|
36514
36761
|
const absProjectDir = resolve19(projectDir);
|
|
36515
|
-
if (!
|
|
36762
|
+
if (!existsSync36(absProjectDir) || !statSync13(absProjectDir).isDirectory()) {
|
|
36516
36763
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
36517
36764
|
}
|
|
36518
36765
|
const entry = options.entryFile || "index.html";
|
|
36519
|
-
if (!
|
|
36766
|
+
if (!existsSync36(resolve19(absProjectDir, entry))) {
|
|
36520
36767
|
return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
|
|
36521
36768
|
}
|
|
36522
36769
|
return { prepared: { input: { projectDir: absProjectDir, ...options } } };
|
|
@@ -36541,8 +36788,8 @@ async function prepareRenderBody(body) {
|
|
|
36541
36788
|
}
|
|
36542
36789
|
}
|
|
36543
36790
|
const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir3();
|
|
36544
|
-
const tempProjectDir = mkdtempSync2(
|
|
36545
|
-
writeFileSync16(
|
|
36791
|
+
const tempProjectDir = mkdtempSync2(join38(tempRoot, "producer-project-"));
|
|
36792
|
+
writeFileSync16(join38(tempProjectDir, "index.html"), htmlContent, "utf-8");
|
|
36546
36793
|
return {
|
|
36547
36794
|
prepared: {
|
|
36548
36795
|
input: {
|
|
@@ -36665,7 +36912,7 @@ function createRenderHandlers(options = {}) {
|
|
|
36665
36912
|
log2
|
|
36666
36913
|
);
|
|
36667
36914
|
const outputDir = dirname13(absoluteOutputPath);
|
|
36668
|
-
if (!
|
|
36915
|
+
if (!existsSync36(outputDir)) mkdirSync21(outputDir, { recursive: true });
|
|
36669
36916
|
const release2 = await renderSemaphore.acquire();
|
|
36670
36917
|
log2.info("render started", {
|
|
36671
36918
|
requestId,
|
|
@@ -36692,7 +36939,7 @@ function createRenderHandlers(options = {}) {
|
|
|
36692
36939
|
log2.info(`render progress ${pct}%`, { requestId, stage: j2.currentStage, message });
|
|
36693
36940
|
}
|
|
36694
36941
|
});
|
|
36695
|
-
const fileSize =
|
|
36942
|
+
const fileSize = existsSync36(absoluteOutputPath) ? statSync13(absoluteOutputPath).size : 0;
|
|
36696
36943
|
const durationMs = Date.now() - t0;
|
|
36697
36944
|
const outputToken = store.register(absoluteOutputPath);
|
|
36698
36945
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
@@ -36776,7 +37023,7 @@ function createRenderHandlers(options = {}) {
|
|
|
36776
37023
|
log2
|
|
36777
37024
|
);
|
|
36778
37025
|
const outputDir = dirname13(absoluteOutputPath);
|
|
36779
|
-
if (!
|
|
37026
|
+
if (!existsSync36(outputDir)) mkdirSync21(outputDir, { recursive: true });
|
|
36780
37027
|
log2.info("render-stream started", { requestId, projectDir: input.projectDir });
|
|
36781
37028
|
const job = createRenderJob({
|
|
36782
37029
|
fps: input.fps,
|
|
@@ -36821,7 +37068,7 @@ function createRenderHandlers(options = {}) {
|
|
|
36821
37068
|
},
|
|
36822
37069
|
abortController.signal
|
|
36823
37070
|
);
|
|
36824
|
-
const fileSize =
|
|
37071
|
+
const fileSize = existsSync36(absoluteOutputPath) ? statSync13(absoluteOutputPath).size : 0;
|
|
36825
37072
|
const outputToken = store.register(absoluteOutputPath);
|
|
36826
37073
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
36827
37074
|
log2.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
|
|
@@ -36880,11 +37127,11 @@ function createRenderHandlers(options = {}) {
|
|
|
36880
37127
|
if (!artifact) {
|
|
36881
37128
|
return c2.json({ success: false, error: "Output artifact not found or expired" }, 404);
|
|
36882
37129
|
}
|
|
36883
|
-
if (!
|
|
37130
|
+
if (!existsSync36(artifact.path)) {
|
|
36884
37131
|
store.delete(token);
|
|
36885
37132
|
return c2.json({ success: false, error: "Output artifact file missing" }, 404);
|
|
36886
37133
|
}
|
|
36887
|
-
const stats =
|
|
37134
|
+
const stats = statSync13(artifact.path);
|
|
36888
37135
|
return new Response(createReadStream(artifact.path), {
|
|
36889
37136
|
headers: {
|
|
36890
37137
|
"content-type": "video/mp4",
|
|
@@ -37018,20 +37265,20 @@ __export(studioServer_exports, {
|
|
|
37018
37265
|
});
|
|
37019
37266
|
import { Hono as Hono5 } from "hono";
|
|
37020
37267
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
37021
|
-
import { existsSync as
|
|
37022
|
-
import { resolve as resolve20, join as
|
|
37268
|
+
import { existsSync as existsSync37, readFileSync as readFileSync26, writeFileSync as writeFileSync17, statSync as statSync14 } from "fs";
|
|
37269
|
+
import { resolve as resolve20, join as join39, basename as basename3 } from "path";
|
|
37023
37270
|
function resolveDistDir() {
|
|
37024
37271
|
return resolveStudioBundle().dir;
|
|
37025
37272
|
}
|
|
37026
37273
|
function resolveStudioBundle() {
|
|
37027
37274
|
const builtPath = resolve20(__dirname, "studio");
|
|
37028
37275
|
const builtIndex = resolve20(builtPath, "index.html");
|
|
37029
|
-
if (
|
|
37276
|
+
if (existsSync37(builtIndex)) {
|
|
37030
37277
|
return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
|
|
37031
37278
|
}
|
|
37032
37279
|
const devPath = resolve20(__dirname, "..", "..", "..", "studio", "dist");
|
|
37033
37280
|
const devIndex = resolve20(devPath, "index.html");
|
|
37034
|
-
if (
|
|
37281
|
+
if (existsSync37(devIndex)) {
|
|
37035
37282
|
return {
|
|
37036
37283
|
dir: devPath,
|
|
37037
37284
|
indexPath: devIndex,
|
|
@@ -37048,9 +37295,9 @@ function resolveStudioBundle() {
|
|
|
37048
37295
|
}
|
|
37049
37296
|
function resolveRuntimePath() {
|
|
37050
37297
|
const builtPath = resolve20(__dirname, "hyperframe-runtime.js");
|
|
37051
|
-
if (
|
|
37298
|
+
if (existsSync37(builtPath)) return builtPath;
|
|
37052
37299
|
const iifePath = resolve20(__dirname, "hyperframe.runtime.iife.js");
|
|
37053
|
-
if (
|
|
37300
|
+
if (existsSync37(iifePath)) return iifePath;
|
|
37054
37301
|
const devPath = resolve20(
|
|
37055
37302
|
__dirname,
|
|
37056
37303
|
"..",
|
|
@@ -37060,7 +37307,7 @@ function resolveRuntimePath() {
|
|
|
37060
37307
|
"dist",
|
|
37061
37308
|
"hyperframe.runtime.iife.js"
|
|
37062
37309
|
);
|
|
37063
|
-
if (
|
|
37310
|
+
if (existsSync37(devPath)) return devPath;
|
|
37064
37311
|
return builtPath;
|
|
37065
37312
|
}
|
|
37066
37313
|
async function getThumbnailBrowser() {
|
|
@@ -37122,7 +37369,7 @@ function createStudioServer(options) {
|
|
|
37122
37369
|
return lintHyperframeHtml2(html, opts);
|
|
37123
37370
|
},
|
|
37124
37371
|
runtimeUrl: "/api/runtime.js",
|
|
37125
|
-
rendersDir: () =>
|
|
37372
|
+
rendersDir: () => join39(projectDir, "renders"),
|
|
37126
37373
|
startRender(opts) {
|
|
37127
37374
|
const state = {
|
|
37128
37375
|
id: opts.jobId,
|
|
@@ -37194,34 +37441,40 @@ function createStudioServer(options) {
|
|
|
37194
37441
|
await new Promise((r2) => setTimeout(r2, 200));
|
|
37195
37442
|
let clip;
|
|
37196
37443
|
if (opts.selector) {
|
|
37197
|
-
clip = await page.evaluate(
|
|
37198
|
-
|
|
37199
|
-
|
|
37200
|
-
|
|
37201
|
-
|
|
37202
|
-
|
|
37203
|
-
|
|
37204
|
-
|
|
37205
|
-
|
|
37206
|
-
|
|
37207
|
-
|
|
37208
|
-
|
|
37209
|
-
|
|
37210
|
-
|
|
37211
|
-
|
|
37212
|
-
|
|
37213
|
-
|
|
37444
|
+
clip = await page.evaluate(
|
|
37445
|
+
(selector, selectorIndex) => {
|
|
37446
|
+
const matches2 = Array.from(document.querySelectorAll(selector)).filter(
|
|
37447
|
+
(el2) => el2 instanceof HTMLElement
|
|
37448
|
+
);
|
|
37449
|
+
const safeIndex = Math.max(
|
|
37450
|
+
0,
|
|
37451
|
+
Math.min(matches2.length - 1, Math.floor(selectorIndex ?? 0))
|
|
37452
|
+
);
|
|
37453
|
+
const el = matches2[safeIndex] ?? null;
|
|
37454
|
+
if (!(el instanceof HTMLElement)) return void 0;
|
|
37455
|
+
const rect = el.getBoundingClientRect();
|
|
37456
|
+
if (rect.width < 4 || rect.height < 4) return void 0;
|
|
37457
|
+
const pad = 8;
|
|
37458
|
+
const x4 = Math.max(0, rect.left - pad);
|
|
37459
|
+
const y2 = Math.max(0, rect.top - pad);
|
|
37460
|
+
const maxWidth = window.innerWidth - x4;
|
|
37461
|
+
const maxHeight = window.innerHeight - y2;
|
|
37462
|
+
return {
|
|
37463
|
+
x: x4,
|
|
37464
|
+
y: y2,
|
|
37465
|
+
width: Math.max(1, Math.min(rect.width + pad * 2, maxWidth)),
|
|
37466
|
+
height: Math.max(1, Math.min(rect.height + pad * 2, maxHeight))
|
|
37467
|
+
};
|
|
37468
|
+
},
|
|
37469
|
+
opts.selector,
|
|
37470
|
+
opts.selectorIndex
|
|
37471
|
+
);
|
|
37214
37472
|
}
|
|
37215
|
-
const screenshot = await page.screenshot(
|
|
37216
|
-
|
|
37217
|
-
|
|
37218
|
-
|
|
37219
|
-
|
|
37220
|
-
type: "jpeg",
|
|
37221
|
-
quality: 80,
|
|
37222
|
-
...clip ? { clip } : {}
|
|
37223
|
-
}
|
|
37224
|
-
);
|
|
37473
|
+
const screenshot = await page.screenshot({
|
|
37474
|
+
type: "jpeg",
|
|
37475
|
+
quality: 80,
|
|
37476
|
+
...clip ? { clip } : {}
|
|
37477
|
+
});
|
|
37225
37478
|
return screenshot;
|
|
37226
37479
|
} catch {
|
|
37227
37480
|
return null;
|
|
@@ -37242,7 +37495,7 @@ function createStudioServer(options) {
|
|
|
37242
37495
|
});
|
|
37243
37496
|
app.get("/api/runtime.js", (c2) => {
|
|
37244
37497
|
const serve4 = async () => {
|
|
37245
|
-
const runtimeSource = await loadRuntimeSource() ?? (
|
|
37498
|
+
const runtimeSource = await loadRuntimeSource() ?? (existsSync37(runtimePath) ? readFileSync26(runtimePath, "utf-8") : null);
|
|
37246
37499
|
if (!runtimeSource) return c2.text("runtime not available", 404);
|
|
37247
37500
|
return c2.body(runtimeSource, 200, {
|
|
37248
37501
|
"Content-Type": "text/javascript",
|
|
@@ -37278,7 +37531,7 @@ function createStudioServer(options) {
|
|
|
37278
37531
|
});
|
|
37279
37532
|
app.get("/assets/*", (c2) => {
|
|
37280
37533
|
const filePath = resolve20(studioDir, c2.req.path.slice(1));
|
|
37281
|
-
if (!
|
|
37534
|
+
if (!existsSync37(filePath) || !statSync14(filePath).isFile()) return c2.text("not found", 404);
|
|
37282
37535
|
const content = readFileSync26(filePath);
|
|
37283
37536
|
return new Response(content, {
|
|
37284
37537
|
headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
|
|
@@ -37286,7 +37539,7 @@ function createStudioServer(options) {
|
|
|
37286
37539
|
});
|
|
37287
37540
|
app.get("/icons/*", (c2) => {
|
|
37288
37541
|
const filePath = resolve20(studioDir, c2.req.path.slice(1));
|
|
37289
|
-
if (!
|
|
37542
|
+
if (!existsSync37(filePath) || !statSync14(filePath).isFile()) return c2.text("not found", 404);
|
|
37290
37543
|
const content = readFileSync26(filePath);
|
|
37291
37544
|
return new Response(content, {
|
|
37292
37545
|
headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
|
|
@@ -37294,7 +37547,7 @@ function createStudioServer(options) {
|
|
|
37294
37547
|
});
|
|
37295
37548
|
app.get("*", (c2) => {
|
|
37296
37549
|
const indexPath = resolve20(studioDir, "index.html");
|
|
37297
|
-
if (!
|
|
37550
|
+
if (!existsSync37(indexPath)) {
|
|
37298
37551
|
return c2.html(
|
|
37299
37552
|
`<!doctype html>
|
|
37300
37553
|
<html>
|
|
@@ -37374,20 +37627,20 @@ __export(preview_exports, {
|
|
|
37374
37627
|
examples: () => examples
|
|
37375
37628
|
});
|
|
37376
37629
|
import { spawn as spawn9 } from "child_process";
|
|
37377
|
-
import { existsSync as
|
|
37378
|
-
import { resolve as resolve21, dirname as dirname14, basename as basename4, join as
|
|
37630
|
+
import { existsSync as existsSync38, lstatSync, symlinkSync, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync22 } from "fs";
|
|
37631
|
+
import { resolve as resolve21, dirname as dirname14, basename as basename4, join as join40 } from "path";
|
|
37379
37632
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
37380
37633
|
import { createRequire } from "module";
|
|
37381
37634
|
async function runDevMode(dir, projectName) {
|
|
37382
37635
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
37383
37636
|
const repoRoot = resolve21(dirname14(thisFile), "..", "..", "..", "..");
|
|
37384
|
-
const projectsDir =
|
|
37637
|
+
const projectsDir = join40(repoRoot, "packages", "studio", "data", "projects");
|
|
37385
37638
|
const pName = projectName ?? basename4(dir);
|
|
37386
|
-
const symlinkPath =
|
|
37639
|
+
const symlinkPath = join40(projectsDir, pName);
|
|
37387
37640
|
mkdirSync22(projectsDir, { recursive: true });
|
|
37388
37641
|
let createdSymlink = false;
|
|
37389
37642
|
if (dir !== symlinkPath) {
|
|
37390
|
-
if (
|
|
37643
|
+
if (existsSync38(symlinkPath)) {
|
|
37391
37644
|
try {
|
|
37392
37645
|
const stat3 = lstatSync(symlinkPath);
|
|
37393
37646
|
if (stat3.isSymbolicLink()) {
|
|
@@ -37399,7 +37652,7 @@ async function runDevMode(dir, projectName) {
|
|
|
37399
37652
|
} catch {
|
|
37400
37653
|
}
|
|
37401
37654
|
}
|
|
37402
|
-
if (!
|
|
37655
|
+
if (!existsSync38(symlinkPath)) {
|
|
37403
37656
|
symlinkSync(dir, symlinkPath, "dir");
|
|
37404
37657
|
createdSymlink = true;
|
|
37405
37658
|
}
|
|
@@ -37407,7 +37660,7 @@ async function runDevMode(dir, projectName) {
|
|
|
37407
37660
|
Wt2(c.bold("hyperframes preview"));
|
|
37408
37661
|
const s2 = be();
|
|
37409
37662
|
s2.start("Starting studio...");
|
|
37410
|
-
const studioPkgDir =
|
|
37663
|
+
const studioPkgDir = join40(repoRoot, "packages", "studio");
|
|
37411
37664
|
const child = spawn9("pnpm", ["exec", "vite"], {
|
|
37412
37665
|
cwd: studioPkgDir,
|
|
37413
37666
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -37441,7 +37694,7 @@ async function runDevMode(dir, projectName) {
|
|
|
37441
37694
|
if (createdSymlink) {
|
|
37442
37695
|
process.on("exit", () => {
|
|
37443
37696
|
try {
|
|
37444
|
-
if (
|
|
37697
|
+
if (existsSync38(symlinkPath)) unlinkSync5(symlinkPath);
|
|
37445
37698
|
} catch {
|
|
37446
37699
|
}
|
|
37447
37700
|
});
|
|
@@ -37452,7 +37705,7 @@ async function runDevMode(dir, projectName) {
|
|
|
37452
37705
|
}
|
|
37453
37706
|
function hasLocalStudio(dir) {
|
|
37454
37707
|
try {
|
|
37455
|
-
const req = createRequire(
|
|
37708
|
+
const req = createRequire(join40(dir, "package.json"));
|
|
37456
37709
|
req.resolve("@hyperframes/studio/package.json");
|
|
37457
37710
|
return true;
|
|
37458
37711
|
} catch {
|
|
@@ -37460,20 +37713,20 @@ function hasLocalStudio(dir) {
|
|
|
37460
37713
|
}
|
|
37461
37714
|
}
|
|
37462
37715
|
async function runLocalStudioMode(dir, projectName) {
|
|
37463
|
-
const req = createRequire(
|
|
37716
|
+
const req = createRequire(join40(dir, "package.json"));
|
|
37464
37717
|
const studioPkgPath = dirname14(req.resolve("@hyperframes/studio/package.json"));
|
|
37465
37718
|
const pName = projectName ?? basename4(dir);
|
|
37466
|
-
const projectsDir =
|
|
37467
|
-
const symlinkPath =
|
|
37719
|
+
const projectsDir = join40(studioPkgPath, "data", "projects");
|
|
37720
|
+
const symlinkPath = join40(projectsDir, pName);
|
|
37468
37721
|
mkdirSync22(projectsDir, { recursive: true });
|
|
37469
37722
|
let createdSymlink = false;
|
|
37470
37723
|
if (dir !== symlinkPath) {
|
|
37471
|
-
if (
|
|
37724
|
+
if (existsSync38(symlinkPath) && lstatSync(symlinkPath).isSymbolicLink()) {
|
|
37472
37725
|
if (resolve21(readlinkSync(symlinkPath)) !== resolve21(dir)) {
|
|
37473
37726
|
unlinkSync5(symlinkPath);
|
|
37474
37727
|
}
|
|
37475
37728
|
}
|
|
37476
|
-
if (!
|
|
37729
|
+
if (!existsSync38(symlinkPath)) {
|
|
37477
37730
|
symlinkSync(dir, symlinkPath, "dir");
|
|
37478
37731
|
createdSymlink = true;
|
|
37479
37732
|
}
|
|
@@ -37512,7 +37765,7 @@ async function runLocalStudioMode(dir, projectName) {
|
|
|
37512
37765
|
if (createdSymlink) {
|
|
37513
37766
|
process.on("exit", () => {
|
|
37514
37767
|
try {
|
|
37515
|
-
if (
|
|
37768
|
+
if (existsSync38(symlinkPath)) unlinkSync5(symlinkPath);
|
|
37516
37769
|
} catch {
|
|
37517
37770
|
}
|
|
37518
37771
|
});
|
|
@@ -37688,8 +37941,8 @@ var init_preview2 = __esm({
|
|
|
37688
37941
|
const dir = resolve21(rawArg ?? ".");
|
|
37689
37942
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
37690
37943
|
const projectName = isImplicitCwd ? basename4(process.env.PWD ?? dir) : basename4(dir);
|
|
37691
|
-
const indexPath =
|
|
37692
|
-
if (
|
|
37944
|
+
const indexPath = join40(dir, "index.html");
|
|
37945
|
+
if (existsSync38(indexPath)) {
|
|
37693
37946
|
const project = { dir, name: projectName, indexPath };
|
|
37694
37947
|
const lintResult = lintProject(project);
|
|
37695
37948
|
if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
|
|
@@ -37718,20 +37971,20 @@ __export(init_exports, {
|
|
|
37718
37971
|
examples: () => examples2
|
|
37719
37972
|
});
|
|
37720
37973
|
import {
|
|
37721
|
-
existsSync as
|
|
37974
|
+
existsSync as existsSync39,
|
|
37722
37975
|
mkdirSync as mkdirSync23,
|
|
37723
37976
|
copyFileSync as copyFileSync3,
|
|
37724
37977
|
cpSync,
|
|
37725
37978
|
writeFileSync as writeFileSync18,
|
|
37726
37979
|
readFileSync as readFileSync27,
|
|
37727
|
-
readdirSync as
|
|
37980
|
+
readdirSync as readdirSync14
|
|
37728
37981
|
} from "fs";
|
|
37729
|
-
import { resolve as resolve22, basename as basename5, join as
|
|
37982
|
+
import { resolve as resolve22, basename as basename5, join as join41, dirname as dirname15 } from "path";
|
|
37730
37983
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
37731
|
-
import { execFileSync as
|
|
37984
|
+
import { execFileSync as execFileSync5, spawn as spawn10 } from "child_process";
|
|
37732
37985
|
function probeVideo(filePath) {
|
|
37733
37986
|
try {
|
|
37734
|
-
const raw =
|
|
37987
|
+
const raw = execFileSync5(
|
|
37735
37988
|
"ffprobe",
|
|
37736
37989
|
["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", filePath],
|
|
37737
37990
|
{ encoding: "utf-8", timeout: 15e3 }
|
|
@@ -37798,7 +38051,7 @@ function resolveAssetDir(devSegments, builtSegments) {
|
|
|
37798
38051
|
const base = dirname15(fileURLToPath5(import.meta.url));
|
|
37799
38052
|
const devPath = resolve22(base, ...devSegments);
|
|
37800
38053
|
const builtPath = resolve22(base, ...builtSegments);
|
|
37801
|
-
return
|
|
38054
|
+
return existsSync39(devPath) ? devPath : builtPath;
|
|
37802
38055
|
}
|
|
37803
38056
|
function getStaticTemplateDir(templateId) {
|
|
37804
38057
|
return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
|
|
@@ -37807,7 +38060,7 @@ function getSharedTemplateDir() {
|
|
|
37807
38060
|
return resolveAssetDir(["..", "templates", "_shared"], ["templates", "_shared"]);
|
|
37808
38061
|
}
|
|
37809
38062
|
function patchVideoSrc(dir, videoFilename, durationSeconds) {
|
|
37810
|
-
const htmlFiles =
|
|
38063
|
+
const htmlFiles = readdirSync14(dir, { withFileTypes: true, recursive: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".html")).map((e2) => join41(e2.parentPath ?? e2.path, e2.name));
|
|
37811
38064
|
for (const file of htmlFiles) {
|
|
37812
38065
|
let content = readFileSync27(file, "utf-8");
|
|
37813
38066
|
if (videoFilename) {
|
|
@@ -37914,7 +38167,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
|
|
|
37914
38167
|
async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds) {
|
|
37915
38168
|
mkdirSync23(destDir, { recursive: true });
|
|
37916
38169
|
const templateDir = getStaticTemplateDir(templateId);
|
|
37917
|
-
if (
|
|
38170
|
+
if (existsSync39(templateDir)) {
|
|
37918
38171
|
cpSync(templateDir, destDir, { recursive: true });
|
|
37919
38172
|
} else {
|
|
37920
38173
|
await fetchRemoteTemplate(templateId, destDir);
|
|
@@ -37933,14 +38186,14 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
|
|
|
37933
38186
|
),
|
|
37934
38187
|
"utf-8"
|
|
37935
38188
|
);
|
|
37936
|
-
if (!
|
|
38189
|
+
if (!existsSync39(resolve22(destDir, "hyperframes.json"))) {
|
|
37937
38190
|
const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
|
|
37938
38191
|
writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
|
|
37939
38192
|
}
|
|
37940
38193
|
const sharedDir = getSharedTemplateDir();
|
|
37941
|
-
if (
|
|
37942
|
-
for (const entry of
|
|
37943
|
-
const src =
|
|
38194
|
+
if (existsSync39(sharedDir)) {
|
|
38195
|
+
for (const entry of readdirSync14(sharedDir, { withFileTypes: true })) {
|
|
38196
|
+
const src = join41(sharedDir, entry.name);
|
|
37944
38197
|
const dest = resolve22(destDir, entry.name);
|
|
37945
38198
|
if (entry.isFile() || entry.isSymbolicLink()) {
|
|
37946
38199
|
copyFileSync3(src, dest);
|
|
@@ -38054,7 +38307,7 @@ var init_init = __esm({
|
|
|
38054
38307
|
const templateId2 = exampleFlag ?? "blank";
|
|
38055
38308
|
const name2 = args.name ?? "my-video";
|
|
38056
38309
|
const destDir2 = resolve22(name2);
|
|
38057
|
-
if (
|
|
38310
|
+
if (existsSync39(destDir2) && readdirSync14(destDir2).length > 0) {
|
|
38058
38311
|
console.error(c.error(`Directory already exists and is not empty: ${name2}`));
|
|
38059
38312
|
process.exit(1);
|
|
38060
38313
|
}
|
|
@@ -38068,7 +38321,7 @@ var init_init = __esm({
|
|
|
38068
38321
|
}
|
|
38069
38322
|
if (videoFlag) {
|
|
38070
38323
|
const videoPath = resolve22(videoFlag);
|
|
38071
|
-
if (!
|
|
38324
|
+
if (!existsSync39(videoPath)) {
|
|
38072
38325
|
console.error(c.error(`Video file not found: ${videoFlag}`));
|
|
38073
38326
|
process.exit(1);
|
|
38074
38327
|
}
|
|
@@ -38082,7 +38335,7 @@ var init_init = __esm({
|
|
|
38082
38335
|
}
|
|
38083
38336
|
if (audioFlag) {
|
|
38084
38337
|
const audioPath = resolve22(audioFlag);
|
|
38085
|
-
if (!
|
|
38338
|
+
if (!existsSync39(audioPath)) {
|
|
38086
38339
|
console.error(c.error(`Audio file not found: ${audioFlag}`));
|
|
38087
38340
|
process.exit(1);
|
|
38088
38341
|
}
|
|
@@ -38128,11 +38381,11 @@ var init_init = __esm({
|
|
|
38128
38381
|
}
|
|
38129
38382
|
trackInitTemplate(templateId2);
|
|
38130
38383
|
const transcriptFile2 = resolve22(destDir2, "transcript.json");
|
|
38131
|
-
if (
|
|
38384
|
+
if (existsSync39(transcriptFile2)) {
|
|
38132
38385
|
await patchTranscript(destDir2, transcriptFile2);
|
|
38133
38386
|
}
|
|
38134
38387
|
console.log(c.success(`Created ${c.accent(name2 + "/")}`));
|
|
38135
|
-
for (const f3 of
|
|
38388
|
+
for (const f3 of readdirSync14(destDir2).filter((f4) => !f4.startsWith("."))) {
|
|
38136
38389
|
console.log(` ${c.accent(f3)}`);
|
|
38137
38390
|
}
|
|
38138
38391
|
console.log();
|
|
@@ -38180,7 +38433,7 @@ var init_init = __esm({
|
|
|
38180
38433
|
name = nameResult;
|
|
38181
38434
|
}
|
|
38182
38435
|
const destDir = resolve22(name);
|
|
38183
|
-
if (
|
|
38436
|
+
if (existsSync39(destDir) && readdirSync14(destDir).length > 0) {
|
|
38184
38437
|
const overwrite = await Rt({
|
|
38185
38438
|
message: `Directory ${c.accent(name)} already exists and is not empty. Overwrite?`,
|
|
38186
38439
|
initialValue: false
|
|
@@ -38195,7 +38448,7 @@ var init_init = __esm({
|
|
|
38195
38448
|
let videoDuration;
|
|
38196
38449
|
if (videoFlag) {
|
|
38197
38450
|
const videoPath = resolve22(videoFlag);
|
|
38198
|
-
if (!
|
|
38451
|
+
if (!existsSync39(videoPath)) {
|
|
38199
38452
|
R2.error(`File not found: ${videoFlag}`);
|
|
38200
38453
|
Nt("Setup cancelled.");
|
|
38201
38454
|
process.exit(1);
|
|
@@ -38207,7 +38460,7 @@ var init_init = __esm({
|
|
|
38207
38460
|
videoDuration = result.meta.durationSeconds;
|
|
38208
38461
|
} else if (audioFlag) {
|
|
38209
38462
|
const audioPath = resolve22(audioFlag);
|
|
38210
|
-
if (!
|
|
38463
|
+
if (!existsSync39(audioPath)) {
|
|
38211
38464
|
R2.error(`File not found: ${audioFlag}`);
|
|
38212
38465
|
Nt("Setup cancelled.");
|
|
38213
38466
|
process.exit(1);
|
|
@@ -38300,10 +38553,10 @@ ${c.dim("Use --example blank for offline use.")}`
|
|
|
38300
38553
|
}
|
|
38301
38554
|
trackInitTemplate(templateId);
|
|
38302
38555
|
const transcriptFile = resolve22(destDir, "transcript.json");
|
|
38303
|
-
if (
|
|
38556
|
+
if (existsSync39(transcriptFile)) {
|
|
38304
38557
|
await patchTranscript(destDir, transcriptFile);
|
|
38305
38558
|
}
|
|
38306
|
-
const files =
|
|
38559
|
+
const files = readdirSync14(destDir);
|
|
38307
38560
|
Vt2(files.map((f3) => c.accent(f3)).join("\n"), c.success(`Created ${name}/`));
|
|
38308
38561
|
if (!skipSkills) {
|
|
38309
38562
|
const installSkills = await Rt({
|
|
@@ -38332,9 +38585,9 @@ ${c.dim("Use --example blank for offline use.")}`
|
|
|
38332
38585
|
|
|
38333
38586
|
// src/utils/clipboard.ts
|
|
38334
38587
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
38335
|
-
import { platform as
|
|
38588
|
+
import { platform as platform4 } from "os";
|
|
38336
38589
|
function detectProvider() {
|
|
38337
|
-
const os =
|
|
38590
|
+
const os = platform4();
|
|
38338
38591
|
if (os === "darwin") {
|
|
38339
38592
|
return { cmd: "pbcopy", args: [] };
|
|
38340
38593
|
}
|
|
@@ -38386,7 +38639,7 @@ __export(add_exports, {
|
|
|
38386
38639
|
remapTarget: () => remapTarget,
|
|
38387
38640
|
runAdd: () => runAdd
|
|
38388
38641
|
});
|
|
38389
|
-
import { existsSync as
|
|
38642
|
+
import { existsSync as existsSync40 } from "fs";
|
|
38390
38643
|
import { resolve as resolve23, relative as relative3 } from "path";
|
|
38391
38644
|
function remapTarget(item, originalTarget, paths) {
|
|
38392
38645
|
if (item.type === "hyperframes:block") {
|
|
@@ -38412,8 +38665,8 @@ function buildSnippet(item, relativeTarget) {
|
|
|
38412
38665
|
async function runAdd(opts) {
|
|
38413
38666
|
const projectDir = resolve23(opts.projectDir);
|
|
38414
38667
|
let config = loadProjectConfig(projectDir);
|
|
38415
|
-
const hasConfig =
|
|
38416
|
-
if (!hasConfig &&
|
|
38668
|
+
const hasConfig = existsSync40(projectConfigPath(projectDir));
|
|
38669
|
+
if (!hasConfig && existsSync40(resolve23(projectDir, "index.html"))) {
|
|
38417
38670
|
writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
|
|
38418
38671
|
config = DEFAULT_PROJECT_CONFIG;
|
|
38419
38672
|
}
|
|
@@ -38512,10 +38765,10 @@ var init_add = __esm({
|
|
|
38512
38765
|
const projectDir = resolve23(args.dir ?? process.cwd());
|
|
38513
38766
|
const json = args.json === true;
|
|
38514
38767
|
const skipClipboard = args["no-clipboard"] === true;
|
|
38515
|
-
const hasConfigBefore =
|
|
38768
|
+
const hasConfigBefore = existsSync40(projectConfigPath(projectDir));
|
|
38516
38769
|
try {
|
|
38517
38770
|
const result = await runAdd({ name: args.name, projectDir, skipClipboard });
|
|
38518
|
-
const wroteConfig = !hasConfigBefore &&
|
|
38771
|
+
const wroteConfig = !hasConfigBefore && existsSync40(projectConfigPath(projectDir));
|
|
38519
38772
|
if (json) {
|
|
38520
38773
|
console.log(JSON.stringify(result));
|
|
38521
38774
|
return;
|
|
@@ -38725,17 +38978,17 @@ var init_format = __esm({
|
|
|
38725
38978
|
});
|
|
38726
38979
|
|
|
38727
38980
|
// src/utils/project.ts
|
|
38728
|
-
import { existsSync as
|
|
38981
|
+
import { existsSync as existsSync41, statSync as statSync15 } from "fs";
|
|
38729
38982
|
import { resolve as resolve25, basename as basename6 } from "path";
|
|
38730
38983
|
function resolveProject(dirArg) {
|
|
38731
38984
|
const dir = resolve25(dirArg ?? ".");
|
|
38732
38985
|
const name = basename6(dir);
|
|
38733
38986
|
const indexPath = resolve25(dir, "index.html");
|
|
38734
|
-
if (!
|
|
38987
|
+
if (!existsSync41(dir) || !statSync15(dir).isDirectory()) {
|
|
38735
38988
|
errorBox("Not a directory: " + dir);
|
|
38736
38989
|
process.exit(1);
|
|
38737
38990
|
}
|
|
38738
|
-
if (!
|
|
38991
|
+
if (!existsSync41(indexPath)) {
|
|
38739
38992
|
errorBox(
|
|
38740
38993
|
"No composition found in " + dir,
|
|
38741
38994
|
"No index.html file found.",
|
|
@@ -38758,7 +39011,7 @@ __export(play_exports, {
|
|
|
38758
39011
|
default: () => play_default,
|
|
38759
39012
|
examples: () => examples5
|
|
38760
39013
|
});
|
|
38761
|
-
import { existsSync as
|
|
39014
|
+
import { existsSync as existsSync42, readFileSync as readFileSync28 } from "fs";
|
|
38762
39015
|
import { resolve as resolve26, dirname as dirname16 } from "path";
|
|
38763
39016
|
function commandDir() {
|
|
38764
39017
|
return dirname16(new URL(import.meta.url).pathname);
|
|
@@ -38773,7 +39026,7 @@ function resolveRuntimePath2() {
|
|
|
38773
39026
|
resolve26(d, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
|
|
38774
39027
|
];
|
|
38775
39028
|
for (const p of candidates) {
|
|
38776
|
-
if (
|
|
39029
|
+
if (existsSync42(p)) return p;
|
|
38777
39030
|
}
|
|
38778
39031
|
return null;
|
|
38779
39032
|
}
|
|
@@ -38787,7 +39040,7 @@ function resolvePlayerPath() {
|
|
|
38787
39040
|
resolve26(d, "..", "hyperframes-player.global.js")
|
|
38788
39041
|
];
|
|
38789
39042
|
for (const p of candidates) {
|
|
38790
|
-
if (
|
|
39043
|
+
if (existsSync42(p)) return p;
|
|
38791
39044
|
}
|
|
38792
39045
|
return null;
|
|
38793
39046
|
}
|
|
@@ -38889,7 +39142,7 @@ var init_play = __esm({
|
|
|
38889
39142
|
const reqPath = ctx.req.path.replace("/composition/", "");
|
|
38890
39143
|
const filePath = resolve26(project.dir, reqPath);
|
|
38891
39144
|
if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
|
|
38892
|
-
if (!
|
|
39145
|
+
if (!existsSync42(filePath)) return ctx.text("Not found", 404);
|
|
38893
39146
|
const content = readFileSync28(filePath, "utf-8");
|
|
38894
39147
|
if (filePath.endsWith(".html")) {
|
|
38895
39148
|
const injected = injectRuntime(content);
|
|
@@ -38965,14 +39218,14 @@ var init_play = __esm({
|
|
|
38965
39218
|
});
|
|
38966
39219
|
|
|
38967
39220
|
// src/utils/publishProject.ts
|
|
38968
|
-
import { basename as basename7, join as
|
|
38969
|
-
import { readdirSync as
|
|
39221
|
+
import { basename as basename7, join as join42, relative as relative4 } from "path";
|
|
39222
|
+
import { readdirSync as readdirSync15, readFileSync as readFileSync29, statSync as statSync16 } from "fs";
|
|
38970
39223
|
import AdmZip from "adm-zip";
|
|
38971
|
-
function
|
|
39224
|
+
function isRecord2(value) {
|
|
38972
39225
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38973
39226
|
}
|
|
38974
39227
|
function dataRecord(payload) {
|
|
38975
|
-
if (!
|
|
39228
|
+
if (!isRecord2(payload) || !isRecord2(payload["data"])) return null;
|
|
38976
39229
|
return payload["data"];
|
|
38977
39230
|
}
|
|
38978
39231
|
function stringField(record, key2) {
|
|
@@ -39015,7 +39268,7 @@ function parseStagedUploadResponse(payload, archiveByteLength) {
|
|
|
39015
39268
|
function getUploadHeaders(data, uploadUrl, contentType, archiveByteLength) {
|
|
39016
39269
|
const headers = {};
|
|
39017
39270
|
const uploadHeaders = data["upload_headers"];
|
|
39018
|
-
if (
|
|
39271
|
+
if (isRecord2(uploadHeaders)) {
|
|
39019
39272
|
for (const [key2, value] of Object.entries(uploadHeaders)) {
|
|
39020
39273
|
if (typeof value === "string" && key2.trim()) {
|
|
39021
39274
|
headers[key2] = value;
|
|
@@ -39041,7 +39294,7 @@ async function readErrorMessage(response, fallback) {
|
|
|
39041
39294
|
const contentType = response.headers.get("content-type") || "";
|
|
39042
39295
|
if (contentType.includes("application/json")) {
|
|
39043
39296
|
const payload = await readJson(response);
|
|
39044
|
-
if (
|
|
39297
|
+
if (isRecord2(payload) && typeof payload["message"] === "string") {
|
|
39045
39298
|
return payload["message"];
|
|
39046
39299
|
}
|
|
39047
39300
|
}
|
|
@@ -39055,16 +39308,16 @@ function shouldIgnoreSegment(segment) {
|
|
|
39055
39308
|
return segment.startsWith(".") || IGNORED_DIRS.has(segment) || IGNORED_FILES.has(segment);
|
|
39056
39309
|
}
|
|
39057
39310
|
function collectProjectFiles(rootDir, currentDir, paths) {
|
|
39058
|
-
for (const entry of
|
|
39311
|
+
for (const entry of readdirSync15(currentDir, { withFileTypes: true })) {
|
|
39059
39312
|
if (shouldIgnoreSegment(entry.name)) continue;
|
|
39060
|
-
const absolutePath =
|
|
39313
|
+
const absolutePath = join42(currentDir, entry.name);
|
|
39061
39314
|
const relativePath = relative4(rootDir, absolutePath).replaceAll("\\", "/");
|
|
39062
39315
|
if (!relativePath) continue;
|
|
39063
39316
|
if (entry.isDirectory()) {
|
|
39064
39317
|
collectProjectFiles(rootDir, absolutePath, paths);
|
|
39065
39318
|
continue;
|
|
39066
39319
|
}
|
|
39067
|
-
if (!
|
|
39320
|
+
if (!statSync16(absolutePath).isFile()) continue;
|
|
39068
39321
|
paths.push(relativePath);
|
|
39069
39322
|
}
|
|
39070
39323
|
}
|
|
@@ -39076,7 +39329,7 @@ function createPublishArchive(projectDir) {
|
|
|
39076
39329
|
}
|
|
39077
39330
|
const archive = new AdmZip();
|
|
39078
39331
|
for (const filePath of filePaths) {
|
|
39079
|
-
archive.addFile(filePath, readFileSync29(
|
|
39332
|
+
archive.addFile(filePath, readFileSync29(join42(projectDir, filePath)));
|
|
39080
39333
|
}
|
|
39081
39334
|
return {
|
|
39082
39335
|
buffer: archive.toBuffer(),
|
|
@@ -39192,8 +39445,8 @@ __export(publish_exports, {
|
|
|
39192
39445
|
examples: () => examples6
|
|
39193
39446
|
});
|
|
39194
39447
|
import { basename as basename8, resolve as resolve27 } from "path";
|
|
39195
|
-
import { existsSync as
|
|
39196
|
-
import { join as
|
|
39448
|
+
import { existsSync as existsSync43 } from "fs";
|
|
39449
|
+
import { join as join43 } from "path";
|
|
39197
39450
|
var examples6, publish_default;
|
|
39198
39451
|
var init_publish = __esm({
|
|
39199
39452
|
"src/commands/publish.ts"() {
|
|
@@ -39228,8 +39481,8 @@ var init_publish = __esm({
|
|
|
39228
39481
|
const dir = resolve27(rawArg ?? ".");
|
|
39229
39482
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
39230
39483
|
const projectName = isImplicitCwd ? basename8(process.env["PWD"] ?? dir) : basename8(dir);
|
|
39231
|
-
const indexPath =
|
|
39232
|
-
if (
|
|
39484
|
+
const indexPath = join43(dir, "index.html");
|
|
39485
|
+
if (existsSync43(indexPath)) {
|
|
39233
39486
|
const lintResult = lintProject({ dir, name: projectName, indexPath });
|
|
39234
39487
|
if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
|
|
39235
39488
|
console.log();
|
|
@@ -39400,10 +39653,10 @@ __export(render_exports, {
|
|
|
39400
39653
|
default: () => render_default,
|
|
39401
39654
|
examples: () => examples7
|
|
39402
39655
|
});
|
|
39403
|
-
import { mkdirSync as mkdirSync24, readFileSync as readFileSync30, statSync as
|
|
39656
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync30, statSync as statSync17, writeFileSync as writeFileSync19, rmSync as rmSync9 } from "fs";
|
|
39404
39657
|
import { cpus as cpus3, freemem as freemem3, tmpdir as tmpdir4 } from "os";
|
|
39405
|
-
import { resolve as resolve28, dirname as dirname17, join as
|
|
39406
|
-
import { execFileSync as
|
|
39658
|
+
import { resolve as resolve28, dirname as dirname17, join as join44, basename as basename9 } from "path";
|
|
39659
|
+
import { execFileSync as execFileSync6, spawn as spawn11 } from "child_process";
|
|
39407
39660
|
function dockerImageTag(version) {
|
|
39408
39661
|
return `${DOCKER_IMAGE_PREFIX}:${version}`;
|
|
39409
39662
|
}
|
|
@@ -39412,7 +39665,7 @@ function resolveDockerfilePath() {
|
|
|
39412
39665
|
const devPath = resolve28(__dirname, "..", "src", "docker", "Dockerfile.render");
|
|
39413
39666
|
for (const p of [builtPath, devPath]) {
|
|
39414
39667
|
try {
|
|
39415
|
-
|
|
39668
|
+
statSync17(p);
|
|
39416
39669
|
return p;
|
|
39417
39670
|
} catch {
|
|
39418
39671
|
continue;
|
|
@@ -39422,7 +39675,7 @@ function resolveDockerfilePath() {
|
|
|
39422
39675
|
}
|
|
39423
39676
|
function dockerImageExists(tag) {
|
|
39424
39677
|
try {
|
|
39425
|
-
|
|
39678
|
+
execFileSync6("docker", ["image", "inspect", tag], { stdio: "pipe", timeout: 1e4 });
|
|
39426
39679
|
return true;
|
|
39427
39680
|
} catch {
|
|
39428
39681
|
return false;
|
|
@@ -39436,11 +39689,11 @@ function ensureDockerImage(version, quiet) {
|
|
|
39436
39689
|
}
|
|
39437
39690
|
if (!quiet) console.log(c.dim(` Building Docker image: ${tag}...`));
|
|
39438
39691
|
const dockerfilePath = resolveDockerfilePath();
|
|
39439
|
-
const tmpDir =
|
|
39692
|
+
const tmpDir = join44(tmpdir4(), `hyperframes-docker-${Date.now()}`);
|
|
39440
39693
|
mkdirSync24(tmpDir, { recursive: true });
|
|
39441
|
-
writeFileSync19(
|
|
39694
|
+
writeFileSync19(join44(tmpDir, "Dockerfile"), readFileSync30(dockerfilePath));
|
|
39442
39695
|
try {
|
|
39443
|
-
|
|
39696
|
+
execFileSync6(
|
|
39444
39697
|
"docker",
|
|
39445
39698
|
[
|
|
39446
39699
|
"build",
|
|
@@ -39625,7 +39878,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet) {
|
|
|
39625
39878
|
if (quiet) return;
|
|
39626
39879
|
let fileSize = "unknown";
|
|
39627
39880
|
try {
|
|
39628
|
-
fileSize = formatBytes(
|
|
39881
|
+
fileSize = formatBytes(statSync17(outputPath).size);
|
|
39629
39882
|
} catch {
|
|
39630
39883
|
}
|
|
39631
39884
|
const duration = formatDuration(elapsedMs);
|
|
@@ -39791,7 +40044,7 @@ var init_render2 = __esm({
|
|
|
39791
40044
|
const now = /* @__PURE__ */ new Date();
|
|
39792
40045
|
const datePart = now.toISOString().slice(0, 10);
|
|
39793
40046
|
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
|
39794
|
-
const outputPath = args.output ? resolve28(args.output) :
|
|
40047
|
+
const outputPath = args.output ? resolve28(args.output) : join44(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
|
|
39795
40048
|
mkdirSync24(dirname17(outputPath), { recursive: true });
|
|
39796
40049
|
const useDocker = args.docker ?? false;
|
|
39797
40050
|
const useGpu = args.gpu ?? false;
|
|
@@ -40270,8 +40523,8 @@ __export(layout_exports, {
|
|
|
40270
40523
|
examples: () => examples9
|
|
40271
40524
|
});
|
|
40272
40525
|
import { createServer } from "http";
|
|
40273
|
-
import { existsSync as
|
|
40274
|
-
import { dirname as dirname18, isAbsolute as isAbsolute6, join as
|
|
40526
|
+
import { existsSync as existsSync44, readFileSync as readFileSync31 } from "fs";
|
|
40527
|
+
import { dirname as dirname18, isAbsolute as isAbsolute6, join as join45, relative as relative5, resolve as resolve29 } from "path";
|
|
40275
40528
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
40276
40529
|
async function getCompositionDuration2(page) {
|
|
40277
40530
|
return page.evaluate(() => {
|
|
@@ -40341,7 +40594,7 @@ async function bundleProjectHtml(projectDir) {
|
|
|
40341
40594
|
"dist",
|
|
40342
40595
|
"hyperframe.runtime.iife.js"
|
|
40343
40596
|
);
|
|
40344
|
-
if (
|
|
40597
|
+
if (existsSync44(runtimePath)) {
|
|
40345
40598
|
const runtimeSource = readFileSync31(runtimePath, "utf-8");
|
|
40346
40599
|
html = html.replace(
|
|
40347
40600
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
@@ -40366,7 +40619,7 @@ async function serveProject(projectDir, html) {
|
|
|
40366
40619
|
res.end();
|
|
40367
40620
|
return;
|
|
40368
40621
|
}
|
|
40369
|
-
if (
|
|
40622
|
+
if (existsSync44(filePath)) {
|
|
40370
40623
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
40371
40624
|
res.end(readFileSync31(filePath));
|
|
40372
40625
|
return;
|
|
@@ -40470,11 +40723,11 @@ async function runLayoutAudit(projectDir, opts) {
|
|
|
40470
40723
|
}
|
|
40471
40724
|
function loadLayoutAuditScript() {
|
|
40472
40725
|
const candidates = [
|
|
40473
|
-
|
|
40474
|
-
|
|
40726
|
+
join45(__dirname2, "layout-audit.browser.js"),
|
|
40727
|
+
join45(__dirname2, "commands", "layout-audit.browser.js")
|
|
40475
40728
|
];
|
|
40476
40729
|
for (const candidate of candidates) {
|
|
40477
|
-
if (
|
|
40730
|
+
if (existsSync44(candidate)) return readFileSync31(candidate, "utf-8");
|
|
40478
40731
|
}
|
|
40479
40732
|
throw new Error("Missing layout audit browser script");
|
|
40480
40733
|
}
|
|
@@ -40694,16 +40947,16 @@ __export(info_exports, {
|
|
|
40694
40947
|
default: () => info_default,
|
|
40695
40948
|
examples: () => examples11
|
|
40696
40949
|
});
|
|
40697
|
-
import { readFileSync as readFileSync32, readdirSync as
|
|
40698
|
-
import { join as
|
|
40950
|
+
import { readFileSync as readFileSync32, readdirSync as readdirSync16, statSync as statSync18 } from "fs";
|
|
40951
|
+
import { join as join46 } from "path";
|
|
40699
40952
|
function totalSize(dir) {
|
|
40700
40953
|
let total = 0;
|
|
40701
|
-
for (const entry of
|
|
40702
|
-
const path2 =
|
|
40954
|
+
for (const entry of readdirSync16(dir, { withFileTypes: true })) {
|
|
40955
|
+
const path2 = join46(dir, entry.name);
|
|
40703
40956
|
if (entry.isDirectory()) {
|
|
40704
40957
|
total += totalSize(path2);
|
|
40705
40958
|
} else {
|
|
40706
|
-
total +=
|
|
40959
|
+
total += statSync18(path2).size;
|
|
40707
40960
|
}
|
|
40708
40961
|
}
|
|
40709
40962
|
return total;
|
|
@@ -40787,7 +41040,7 @@ __export(compositions_exports, {
|
|
|
40787
41040
|
default: () => compositions_default,
|
|
40788
41041
|
examples: () => examples12
|
|
40789
41042
|
});
|
|
40790
|
-
import { existsSync as
|
|
41043
|
+
import { existsSync as existsSync45, readFileSync as readFileSync33 } from "fs";
|
|
40791
41044
|
import { resolve as resolve30, dirname as dirname19 } from "path";
|
|
40792
41045
|
function parseCompositions(html, baseDir) {
|
|
40793
41046
|
const parser = new DOMParser();
|
|
@@ -40801,7 +41054,7 @@ function parseCompositions(html, baseDir) {
|
|
|
40801
41054
|
const compositionSrc = div.getAttribute("data-composition-src");
|
|
40802
41055
|
if (compositionSrc) {
|
|
40803
41056
|
const subPath = resolve30(baseDir, compositionSrc);
|
|
40804
|
-
if (
|
|
41057
|
+
if (existsSync45(subPath)) {
|
|
40805
41058
|
const subHtml = readFileSync33(subPath, "utf-8");
|
|
40806
41059
|
const subInfo = parseSubComposition(subHtml, id, width, height);
|
|
40807
41060
|
compositions.push({ ...subInfo, source: compositionSrc });
|
|
@@ -40934,8 +41187,8 @@ __export(benchmark_exports, {
|
|
|
40934
41187
|
default: () => benchmark_default,
|
|
40935
41188
|
examples: () => examples13
|
|
40936
41189
|
});
|
|
40937
|
-
import { existsSync as
|
|
40938
|
-
import { resolve as resolve31, join as
|
|
41190
|
+
import { existsSync as existsSync46, statSync as statSync19 } from "fs";
|
|
41191
|
+
import { resolve as resolve31, join as join47 } from "path";
|
|
40939
41192
|
var examples13, DEFAULT_CONFIGS, benchmark_default;
|
|
40940
41193
|
var init_benchmark = __esm({
|
|
40941
41194
|
"src/commands/benchmark.ts"() {
|
|
@@ -41010,7 +41263,7 @@ var init_benchmark = __esm({
|
|
|
41010
41263
|
s2?.start(`Benchmarking ${config.label}...`);
|
|
41011
41264
|
for (let i2 = 0; i2 < runsPerConfig; i2++) {
|
|
41012
41265
|
s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
|
|
41013
|
-
const outputPath =
|
|
41266
|
+
const outputPath = join47(
|
|
41014
41267
|
benchDir,
|
|
41015
41268
|
`${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
|
|
41016
41269
|
);
|
|
@@ -41024,8 +41277,8 @@ var init_benchmark = __esm({
|
|
|
41024
41277
|
await producer.executeRenderJob(job, project.dir, outputPath);
|
|
41025
41278
|
const elapsedMs = Date.now() - startTime;
|
|
41026
41279
|
let fileSize = null;
|
|
41027
|
-
if (
|
|
41028
|
-
const stat3 =
|
|
41280
|
+
if (existsSync46(outputPath)) {
|
|
41281
|
+
const stat3 = statSync19(outputPath);
|
|
41029
41282
|
fileSize = stat3.size;
|
|
41030
41283
|
}
|
|
41031
41284
|
runs.push({ elapsedMs, fileSize });
|
|
@@ -41240,8 +41493,8 @@ __export(transcribe_exports2, {
|
|
|
41240
41493
|
default: () => transcribe_default,
|
|
41241
41494
|
examples: () => examples15
|
|
41242
41495
|
});
|
|
41243
|
-
import { existsSync as
|
|
41244
|
-
import { resolve as resolve32, join as
|
|
41496
|
+
import { existsSync as existsSync47, writeFileSync as writeFileSync20 } from "fs";
|
|
41497
|
+
import { resolve as resolve32, join as join48, extname as extname8 } from "path";
|
|
41245
41498
|
async function importTranscript(inputPath, dir, json) {
|
|
41246
41499
|
const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
|
|
41247
41500
|
const { words, format } = loadTranscript2(inputPath);
|
|
@@ -41249,7 +41502,7 @@ async function importTranscript(inputPath, dir, json) {
|
|
|
41249
41502
|
console.error(c.error("No words found in transcript."));
|
|
41250
41503
|
process.exit(1);
|
|
41251
41504
|
}
|
|
41252
|
-
const outPath =
|
|
41505
|
+
const outPath = join48(dir, "transcript.json");
|
|
41253
41506
|
writeFileSync20(outPath, JSON.stringify(words, null, 2));
|
|
41254
41507
|
patchCaptionHtml2(dir, words);
|
|
41255
41508
|
if (json) {
|
|
@@ -41366,7 +41619,7 @@ var init_transcribe2 = __esm({
|
|
|
41366
41619
|
},
|
|
41367
41620
|
async run({ args }) {
|
|
41368
41621
|
const inputPath = resolve32(args.input);
|
|
41369
|
-
if (!
|
|
41622
|
+
if (!existsSync47(inputPath)) {
|
|
41370
41623
|
console.error(c.error(`File not found: ${args.input}`));
|
|
41371
41624
|
process.exit(1);
|
|
41372
41625
|
}
|
|
@@ -41387,9 +41640,9 @@ var init_transcribe2 = __esm({
|
|
|
41387
41640
|
});
|
|
41388
41641
|
|
|
41389
41642
|
// src/tts/manager.ts
|
|
41390
|
-
import { existsSync as
|
|
41391
|
-
import { homedir as
|
|
41392
|
-
import { join as
|
|
41643
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync25 } from "fs";
|
|
41644
|
+
import { homedir as homedir9 } from "os";
|
|
41645
|
+
import { join as join49 } from "path";
|
|
41393
41646
|
function inferLangFromVoiceId(voiceId) {
|
|
41394
41647
|
const first = voiceId.charAt(0).toLowerCase();
|
|
41395
41648
|
return VOICE_PREFIX_LANG[first] ?? "en-us";
|
|
@@ -41398,8 +41651,8 @@ function isSupportedLang(value) {
|
|
|
41398
41651
|
return SUPPORTED_LANGS.includes(value);
|
|
41399
41652
|
}
|
|
41400
41653
|
async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
41401
|
-
const modelPath =
|
|
41402
|
-
if (
|
|
41654
|
+
const modelPath = join49(MODELS_DIR2, `${model}.onnx`);
|
|
41655
|
+
if (existsSync48(modelPath)) return modelPath;
|
|
41403
41656
|
const url = MODEL_URLS[model];
|
|
41404
41657
|
if (!url) {
|
|
41405
41658
|
throw new Error(
|
|
@@ -41409,18 +41662,18 @@ async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
|
41409
41662
|
mkdirSync25(MODELS_DIR2, { recursive: true });
|
|
41410
41663
|
options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
|
|
41411
41664
|
await downloadFile(url, modelPath);
|
|
41412
|
-
if (!
|
|
41665
|
+
if (!existsSync48(modelPath)) {
|
|
41413
41666
|
throw new Error(`Model download failed: ${model}`);
|
|
41414
41667
|
}
|
|
41415
41668
|
return modelPath;
|
|
41416
41669
|
}
|
|
41417
41670
|
async function ensureVoices(options) {
|
|
41418
|
-
const voicesPath =
|
|
41419
|
-
if (
|
|
41671
|
+
const voicesPath = join49(VOICES_DIR, "voices-v1.0.bin");
|
|
41672
|
+
if (existsSync48(voicesPath)) return voicesPath;
|
|
41420
41673
|
mkdirSync25(VOICES_DIR, { recursive: true });
|
|
41421
41674
|
options?.onProgress?.("Downloading voice data (~27 MB)...");
|
|
41422
41675
|
await downloadFile(VOICES_URL, voicesPath);
|
|
41423
|
-
if (!
|
|
41676
|
+
if (!existsSync48(voicesPath)) {
|
|
41424
41677
|
throw new Error("Voice data download failed");
|
|
41425
41678
|
}
|
|
41426
41679
|
return voicesPath;
|
|
@@ -41430,9 +41683,9 @@ var init_manager3 = __esm({
|
|
|
41430
41683
|
"src/tts/manager.ts"() {
|
|
41431
41684
|
"use strict";
|
|
41432
41685
|
init_download();
|
|
41433
|
-
CACHE_DIR3 =
|
|
41434
|
-
MODELS_DIR2 =
|
|
41435
|
-
VOICES_DIR =
|
|
41686
|
+
CACHE_DIR3 = join49(homedir9(), ".cache", "hyperframes", "tts");
|
|
41687
|
+
MODELS_DIR2 = join49(CACHE_DIR3, "models");
|
|
41688
|
+
VOICES_DIR = join49(CACHE_DIR3, "voices");
|
|
41436
41689
|
DEFAULT_MODEL2 = "kokoro-v1.0";
|
|
41437
41690
|
MODEL_URLS = {
|
|
41438
41691
|
"kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
|
|
@@ -41492,22 +41745,22 @@ var synthesize_exports = {};
|
|
|
41492
41745
|
__export(synthesize_exports, {
|
|
41493
41746
|
synthesize: () => synthesize
|
|
41494
41747
|
});
|
|
41495
|
-
import { execFileSync as
|
|
41496
|
-
import { existsSync as
|
|
41497
|
-
import { join as
|
|
41498
|
-
import { homedir as
|
|
41748
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
41749
|
+
import { existsSync as existsSync49, writeFileSync as writeFileSync21, mkdirSync as mkdirSync26, readdirSync as readdirSync17, unlinkSync as unlinkSync6 } from "fs";
|
|
41750
|
+
import { join as join50, dirname as dirname20, basename as basename10 } from "path";
|
|
41751
|
+
import { homedir as homedir10 } from "os";
|
|
41499
41752
|
function findPython() {
|
|
41500
41753
|
for (const name of ["python3", "python"]) {
|
|
41501
41754
|
try {
|
|
41502
41755
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
41503
|
-
const output =
|
|
41756
|
+
const output = execFileSync7(cmd, [name], {
|
|
41504
41757
|
encoding: "utf-8",
|
|
41505
41758
|
stdio: ["pipe", "pipe", "pipe"],
|
|
41506
41759
|
timeout: 5e3
|
|
41507
41760
|
});
|
|
41508
41761
|
const first = output.split(/\r?\n/).map((s2) => s2.trim()).find(Boolean);
|
|
41509
41762
|
if (!first) continue;
|
|
41510
|
-
const version =
|
|
41763
|
+
const version = execFileSync7(first, ["--version"], {
|
|
41511
41764
|
encoding: "utf-8",
|
|
41512
41765
|
stdio: ["pipe", "pipe", "pipe"],
|
|
41513
41766
|
timeout: 5e3
|
|
@@ -41520,7 +41773,7 @@ function findPython() {
|
|
|
41520
41773
|
}
|
|
41521
41774
|
function hasPythonPackage(python, pkg) {
|
|
41522
41775
|
try {
|
|
41523
|
-
|
|
41776
|
+
execFileSync7(python, ["-c", `import ${pkg}`], {
|
|
41524
41777
|
stdio: ["pipe", "pipe", "pipe"],
|
|
41525
41778
|
timeout: 1e4
|
|
41526
41779
|
});
|
|
@@ -41530,15 +41783,15 @@ function hasPythonPackage(python, pkg) {
|
|
|
41530
41783
|
}
|
|
41531
41784
|
}
|
|
41532
41785
|
function ensureSynthScript() {
|
|
41533
|
-
if (!
|
|
41786
|
+
if (!existsSync49(SCRIPT_PATH)) {
|
|
41534
41787
|
mkdirSync26(SCRIPT_DIR, { recursive: true });
|
|
41535
41788
|
writeFileSync21(SCRIPT_PATH, SYNTH_SCRIPT);
|
|
41536
41789
|
const currentName = basename10(SCRIPT_PATH);
|
|
41537
41790
|
try {
|
|
41538
|
-
for (const entry of
|
|
41791
|
+
for (const entry of readdirSync17(SCRIPT_DIR)) {
|
|
41539
41792
|
if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
|
|
41540
41793
|
try {
|
|
41541
|
-
unlinkSync6(
|
|
41794
|
+
unlinkSync6(join50(SCRIPT_DIR, entry));
|
|
41542
41795
|
} catch {
|
|
41543
41796
|
}
|
|
41544
41797
|
}
|
|
@@ -41575,7 +41828,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
41575
41828
|
mkdirSync26(dirname20(outputPath), { recursive: true });
|
|
41576
41829
|
options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
|
|
41577
41830
|
try {
|
|
41578
|
-
const stdout2 =
|
|
41831
|
+
const stdout2 = execFileSync7(
|
|
41579
41832
|
python,
|
|
41580
41833
|
[scriptPath, modelPath, voicesPath, text, voice, String(speed), outputPath, lang],
|
|
41581
41834
|
{
|
|
@@ -41584,7 +41837,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
41584
41837
|
stdio: ["pipe", "pipe", "pipe"]
|
|
41585
41838
|
}
|
|
41586
41839
|
);
|
|
41587
|
-
if (!
|
|
41840
|
+
if (!existsSync49(outputPath)) {
|
|
41588
41841
|
throw new Error("Synthesis completed but no output file was created");
|
|
41589
41842
|
}
|
|
41590
41843
|
const lines = stdout2.trim().split("\n");
|
|
@@ -41597,7 +41850,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
41597
41850
|
langApplied: result.langApplied
|
|
41598
41851
|
};
|
|
41599
41852
|
} catch (err) {
|
|
41600
|
-
if (err instanceof SyntaxError &&
|
|
41853
|
+
if (err instanceof SyntaxError && existsSync49(outputPath)) {
|
|
41601
41854
|
throw new Error(
|
|
41602
41855
|
"Speech was generated but metadata could not be read. Check the output file manually."
|
|
41603
41856
|
);
|
|
@@ -41648,8 +41901,8 @@ print(json.dumps({
|
|
|
41648
41901
|
"langApplied": bool(lang and supports_lang),
|
|
41649
41902
|
}))
|
|
41650
41903
|
`;
|
|
41651
|
-
SCRIPT_DIR =
|
|
41652
|
-
SCRIPT_PATH =
|
|
41904
|
+
SCRIPT_DIR = join50(homedir10(), ".cache", "hyperframes", "tts");
|
|
41905
|
+
SCRIPT_PATH = join50(SCRIPT_DIR, "synth-v2.py");
|
|
41653
41906
|
}
|
|
41654
41907
|
});
|
|
41655
41908
|
|
|
@@ -41659,7 +41912,7 @@ __export(tts_exports, {
|
|
|
41659
41912
|
default: () => tts_default,
|
|
41660
41913
|
examples: () => examples16
|
|
41661
41914
|
});
|
|
41662
|
-
import { existsSync as
|
|
41915
|
+
import { existsSync as existsSync50, readFileSync as readFileSync34 } from "fs";
|
|
41663
41916
|
import { resolve as resolve33, extname as extname9 } from "path";
|
|
41664
41917
|
function listVoices(json) {
|
|
41665
41918
|
const rows = BUNDLED_VOICES.map((v) => ({ ...v, defaultLang: inferLangFromVoiceId(v.id) }));
|
|
@@ -41769,7 +42022,7 @@ var init_tts = __esm({
|
|
|
41769
42022
|
}
|
|
41770
42023
|
let text;
|
|
41771
42024
|
const maybeFile = resolve33(args.input);
|
|
41772
|
-
if (
|
|
42025
|
+
if (existsSync50(maybeFile) && extname9(maybeFile).toLowerCase() === ".txt") {
|
|
41773
42026
|
text = readFileSync34(maybeFile, "utf-8").trim();
|
|
41774
42027
|
if (!text) {
|
|
41775
42028
|
console.error(c.error("File is empty."));
|
|
@@ -41862,15 +42115,15 @@ __export(docs_exports, {
|
|
|
41862
42115
|
default: () => docs_default,
|
|
41863
42116
|
examples: () => examples17
|
|
41864
42117
|
});
|
|
41865
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
41866
|
-
import { resolve as resolve34, dirname as dirname21, join as
|
|
42118
|
+
import { readFileSync as readFileSync35, existsSync as existsSync51 } from "fs";
|
|
42119
|
+
import { resolve as resolve34, dirname as dirname21, join as join51 } from "path";
|
|
41867
42120
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
41868
42121
|
function docsDir() {
|
|
41869
42122
|
const thisFile = fileURLToPath7(import.meta.url);
|
|
41870
42123
|
const dir = dirname21(thisFile);
|
|
41871
42124
|
const devPath = resolve34(dir, "..", "docs");
|
|
41872
42125
|
const builtPath = resolve34(dir, "docs");
|
|
41873
|
-
return
|
|
42126
|
+
return existsSync51(devPath) ? devPath : builtPath;
|
|
41874
42127
|
}
|
|
41875
42128
|
function formatInlineCode(line) {
|
|
41876
42129
|
return line.replace(/`([^`]+)`/g, (_match, code) => c.accent(code));
|
|
@@ -41967,8 +42220,8 @@ var init_docs = __esm({
|
|
|
41967
42220
|
}
|
|
41968
42221
|
process.exit(1);
|
|
41969
42222
|
}
|
|
41970
|
-
const filePath =
|
|
41971
|
-
if (!
|
|
42223
|
+
const filePath = join51(docsDir(), entry.file);
|
|
42224
|
+
if (!existsSync51(filePath)) {
|
|
41972
42225
|
console.error(c.error(`Doc file not found: ${filePath}`));
|
|
41973
42226
|
process.exit(1);
|
|
41974
42227
|
}
|
|
@@ -41987,7 +42240,7 @@ __export(doctor_exports, {
|
|
|
41987
42240
|
examples: () => examples18
|
|
41988
42241
|
});
|
|
41989
42242
|
import { execSync as execSync3 } from "child_process";
|
|
41990
|
-
import { freemem as freemem4, platform as
|
|
42243
|
+
import { freemem as freemem4, platform as platform5 } from "os";
|
|
41991
42244
|
function checkFFmpeg() {
|
|
41992
42245
|
const path2 = findFFmpeg();
|
|
41993
42246
|
if (path2) {
|
|
@@ -42152,7 +42405,7 @@ var init_doctor = __esm({
|
|
|
42152
42405
|
{ name: "Memory", run: checkMemory },
|
|
42153
42406
|
{ name: "Disk", run: checkDisk }
|
|
42154
42407
|
];
|
|
42155
|
-
if (
|
|
42408
|
+
if (platform5() === "linux") {
|
|
42156
42409
|
checks.push({ name: "/dev/shm", run: checkShm });
|
|
42157
42410
|
}
|
|
42158
42411
|
checks.push(
|
|
@@ -42384,20 +42637,11 @@ Run ${c.accent("hyperframes telemetry --help")} for usage.`
|
|
|
42384
42637
|
// src/commands/validate.ts
|
|
42385
42638
|
var validate_exports = {};
|
|
42386
42639
|
__export(validate_exports, {
|
|
42387
|
-
default: () => validate_default
|
|
42388
|
-
shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
|
|
42640
|
+
default: () => validate_default
|
|
42389
42641
|
});
|
|
42390
|
-
import { existsSync as
|
|
42391
|
-
import { resolve as resolve35, join as
|
|
42642
|
+
import { existsSync as existsSync52, readFileSync as readFileSync36 } from "fs";
|
|
42643
|
+
import { resolve as resolve35, join as join52, dirname as dirname22 } from "path";
|
|
42392
42644
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
42393
|
-
function shouldIgnoreRequestFailure(url, errorText) {
|
|
42394
|
-
if (errorText !== "net::ERR_ABORTED") return false;
|
|
42395
|
-
try {
|
|
42396
|
-
return MEDIA_EXTENSIONS.test(new URL(url).pathname);
|
|
42397
|
-
} catch {
|
|
42398
|
-
return false;
|
|
42399
|
-
}
|
|
42400
|
-
}
|
|
42401
42645
|
async function getCompositionDuration3(page) {
|
|
42402
42646
|
return page.evaluate(() => {
|
|
42403
42647
|
if (window.__hf?.duration && window.__hf.duration > 0) return window.__hf.duration;
|
|
@@ -42440,11 +42684,11 @@ async function runContrastAudit(page) {
|
|
|
42440
42684
|
}
|
|
42441
42685
|
function loadContrastAuditScript() {
|
|
42442
42686
|
const candidates = [
|
|
42443
|
-
|
|
42444
|
-
|
|
42687
|
+
join52(__dirname3, "contrast-audit.browser.js"),
|
|
42688
|
+
join52(__dirname3, "commands", "contrast-audit.browser.js")
|
|
42445
42689
|
];
|
|
42446
42690
|
for (const candidate of candidates) {
|
|
42447
|
-
if (
|
|
42691
|
+
if (existsSync52(candidate)) return readFileSync36(candidate, "utf-8");
|
|
42448
42692
|
}
|
|
42449
42693
|
throw new Error("Missing contrast audit browser script");
|
|
42450
42694
|
}
|
|
@@ -42461,7 +42705,7 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
42461
42705
|
"dist",
|
|
42462
42706
|
"hyperframe.runtime.iife.js"
|
|
42463
42707
|
);
|
|
42464
|
-
if (
|
|
42708
|
+
if (existsSync52(runtimePath)) {
|
|
42465
42709
|
const runtimeSource = readFileSync36(runtimePath, "utf-8");
|
|
42466
42710
|
html = html.replace(
|
|
42467
42711
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
@@ -42477,8 +42721,8 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
42477
42721
|
res.end(html);
|
|
42478
42722
|
return;
|
|
42479
42723
|
}
|
|
42480
|
-
const filePath =
|
|
42481
|
-
if (
|
|
42724
|
+
const filePath = join52(projectDir, decodeURIComponent(url));
|
|
42725
|
+
if (existsSync52(filePath)) {
|
|
42482
42726
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
42483
42727
|
res.end(readFileSync36(filePath));
|
|
42484
42728
|
return;
|
|
@@ -42522,12 +42766,10 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
42522
42766
|
page.on("requestfailed", (req) => {
|
|
42523
42767
|
const url = req.url();
|
|
42524
42768
|
if (url.includes("favicon") || url.startsWith("data:")) return;
|
|
42525
|
-
const failureText = req.failure()?.errorText;
|
|
42526
|
-
if (shouldIgnoreRequestFailure(url, failureText)) return;
|
|
42527
42769
|
const path2 = decodeURIComponent(new URL(url).pathname).replace(/^\//, "");
|
|
42528
42770
|
errors.push({
|
|
42529
42771
|
level: "error",
|
|
42530
|
-
text: `Failed to load ${path2}: ${
|
|
42772
|
+
text: `Failed to load ${path2}: ${req.failure()?.errorText ?? "net::ERR_FAILED"}`,
|
|
42531
42773
|
url
|
|
42532
42774
|
});
|
|
42533
42775
|
});
|
|
@@ -42560,7 +42802,7 @@ function printContrastFailures(failures) {
|
|
|
42560
42802
|
);
|
|
42561
42803
|
}
|
|
42562
42804
|
}
|
|
42563
|
-
var __filename2, __dirname3, CONTRAST_SAMPLES, SEEK_SETTLE_MS2,
|
|
42805
|
+
var __filename2, __dirname3, CONTRAST_SAMPLES, SEEK_SETTLE_MS2, validate_default;
|
|
42564
42806
|
var init_validate = __esm({
|
|
42565
42807
|
"src/commands/validate.ts"() {
|
|
42566
42808
|
"use strict";
|
|
@@ -42572,7 +42814,6 @@ var init_validate = __esm({
|
|
|
42572
42814
|
__dirname3 = dirname22(__filename2);
|
|
42573
42815
|
CONTRAST_SAMPLES = 5;
|
|
42574
42816
|
SEEK_SETTLE_MS2 = 150;
|
|
42575
|
-
MEDIA_EXTENSIONS = /\.(aac|flac|m4a|mov|mp3|mp4|oga|ogg|wav|webm)$/i;
|
|
42576
42817
|
validate_default = defineCommand({
|
|
42577
42818
|
meta: {
|
|
42578
42819
|
name: "validate",
|
|
@@ -42673,12 +42914,12 @@ __export(snapshot_exports, {
|
|
|
42673
42914
|
examples: () => examples21
|
|
42674
42915
|
});
|
|
42675
42916
|
import { spawn as spawn12 } from "child_process";
|
|
42676
|
-
import { existsSync as
|
|
42917
|
+
import { existsSync as existsSync53, mkdtempSync as mkdtempSync3, readFileSync as readFileSync37, mkdirSync as mkdirSync27, rmSync as rmSync10 } from "fs";
|
|
42677
42918
|
import { tmpdir as tmpdir5 } from "os";
|
|
42678
|
-
import { resolve as resolve36, join as
|
|
42919
|
+
import { resolve as resolve36, join as join53, relative as relative6, isAbsolute as isAbsolute7 } from "path";
|
|
42679
42920
|
async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
|
|
42680
|
-
const tmp = mkdtempSync3(
|
|
42681
|
-
const outPath =
|
|
42921
|
+
const tmp = mkdtempSync3(join53(tmpdir5(), "hf-snapshot-frame-"));
|
|
42922
|
+
const outPath = join53(tmp, "frame.png");
|
|
42682
42923
|
try {
|
|
42683
42924
|
const result = await new Promise(
|
|
42684
42925
|
(resolvePromise) => {
|
|
@@ -42718,7 +42959,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
|
|
|
42718
42959
|
});
|
|
42719
42960
|
}
|
|
42720
42961
|
);
|
|
42721
|
-
if (result.code !== 0 || result.timedOut || !
|
|
42962
|
+
if (result.code !== 0 || result.timedOut || !existsSync53(outPath)) return null;
|
|
42722
42963
|
return readFileSync37(outPath);
|
|
42723
42964
|
} finally {
|
|
42724
42965
|
try {
|
|
@@ -42756,7 +42997,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
42756
42997
|
res.end();
|
|
42757
42998
|
return;
|
|
42758
42999
|
}
|
|
42759
|
-
if (
|
|
43000
|
+
if (existsSync53(filePath)) {
|
|
42760
43001
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
42761
43002
|
res.end(readFileSync37(filePath));
|
|
42762
43003
|
return;
|
|
@@ -42831,7 +43072,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
42831
43072
|
return [];
|
|
42832
43073
|
}
|
|
42833
43074
|
const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_2, i2) => i2 / (numFrames - 1) * duration);
|
|
42834
|
-
const snapshotDir =
|
|
43075
|
+
const snapshotDir = join53(projectDir, "snapshots");
|
|
42835
43076
|
mkdirSync27(snapshotDir, { recursive: true });
|
|
42836
43077
|
let injectVideoFramesBatch2 = null;
|
|
42837
43078
|
let syncVideoFrameVisibility2 = null;
|
|
@@ -42906,7 +43147,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
42906
43147
|
const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
|
|
42907
43148
|
const candidate = resolve36(projectDir, decodedPath);
|
|
42908
43149
|
const rel = relative6(projectDir, candidate);
|
|
42909
|
-
if (!rel.startsWith("..") && !isAbsolute7(rel) &&
|
|
43150
|
+
if (!rel.startsWith("..") && !isAbsolute7(rel) && existsSync53(candidate)) {
|
|
42910
43151
|
filePath = candidate;
|
|
42911
43152
|
}
|
|
42912
43153
|
} catch {
|
|
@@ -42936,7 +43177,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
42936
43177
|
}
|
|
42937
43178
|
const timeLabel = opts.at?.length ? `${time.toFixed(1)}s` : `${Math.round(time / duration * 100)}pct`;
|
|
42938
43179
|
const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
|
|
42939
|
-
const framePath =
|
|
43180
|
+
const framePath = join53(snapshotDir, filename);
|
|
42940
43181
|
await page.screenshot({ path: framePath, type: "png" });
|
|
42941
43182
|
savedPaths.push(`snapshots/${filename}`);
|
|
42942
43183
|
}
|
|
@@ -43020,13 +43261,13 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
|
43020
43261
|
|
|
43021
43262
|
// src/capture/assetDownloader.ts
|
|
43022
43263
|
import { writeFileSync as writeFileSync22, mkdirSync as mkdirSync28 } from "fs";
|
|
43023
|
-
import { join as
|
|
43264
|
+
import { join as join54, extname as extname10 } from "path";
|
|
43024
43265
|
async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
|
|
43025
|
-
const assetsDir =
|
|
43266
|
+
const assetsDir = join54(outputDir, "assets");
|
|
43026
43267
|
mkdirSync28(assetsDir, { recursive: true });
|
|
43027
43268
|
const assets = [];
|
|
43028
43269
|
const downloadedUrls = /* @__PURE__ */ new Set();
|
|
43029
|
-
mkdirSync28(
|
|
43270
|
+
mkdirSync28(join54(outputDir, "assets", "svgs"), { recursive: true });
|
|
43030
43271
|
for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
|
|
43031
43272
|
const svg = tokens.svgs[i2];
|
|
43032
43273
|
if (!svg.outerHTML || svg.outerHTML.length < 50) continue;
|
|
@@ -43034,7 +43275,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
43034
43275
|
const name = label2 ? slugify(label2) + ".svg" : svg.isLogo ? `logo-${i2}.svg` : `icon-${i2}.svg`;
|
|
43035
43276
|
const localPath = `assets/svgs/${name}`;
|
|
43036
43277
|
try {
|
|
43037
|
-
writeFileSync22(
|
|
43278
|
+
writeFileSync22(join54(outputDir, localPath), svg.outerHTML, "utf-8");
|
|
43038
43279
|
assets.push({ url: "", localPath, type: "svg" });
|
|
43039
43280
|
} catch {
|
|
43040
43281
|
}
|
|
@@ -43047,7 +43288,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
43047
43288
|
const localPath = `assets/${name}`;
|
|
43048
43289
|
const buffer = await fetchBuffer(icon.href);
|
|
43049
43290
|
if (buffer) {
|
|
43050
|
-
writeFileSync22(
|
|
43291
|
+
writeFileSync22(join54(outputDir, localPath), buffer);
|
|
43051
43292
|
assets.push({ url: icon.href, localPath, type: "favicon" });
|
|
43052
43293
|
break;
|
|
43053
43294
|
}
|
|
@@ -43104,7 +43345,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
43104
43345
|
const slug = isMeaningful ? slugify(rawName) : `${prefix}-${imgIdx}`;
|
|
43105
43346
|
const name = `${slug}${ext}`;
|
|
43106
43347
|
const localPath = `assets/${name}`;
|
|
43107
|
-
writeFileSync22(
|
|
43348
|
+
writeFileSync22(join54(outputDir, localPath), buffer);
|
|
43108
43349
|
assets.push({ url, localPath, type: "image" });
|
|
43109
43350
|
imgIdx++;
|
|
43110
43351
|
} catch {
|
|
@@ -43117,7 +43358,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
43117
43358
|
const localPath = `assets/og-image${ext}`;
|
|
43118
43359
|
const buffer = await fetchBuffer(tokens.ogImage);
|
|
43119
43360
|
if (buffer && buffer.length > 5e3) {
|
|
43120
|
-
writeFileSync22(
|
|
43361
|
+
writeFileSync22(join54(outputDir, localPath), buffer);
|
|
43121
43362
|
assets.push({ url: tokens.ogImage, localPath, type: "image" });
|
|
43122
43363
|
}
|
|
43123
43364
|
} catch {
|
|
@@ -43140,7 +43381,7 @@ function normalizeUrl(u) {
|
|
|
43140
43381
|
}
|
|
43141
43382
|
}
|
|
43142
43383
|
async function downloadAndRewriteFonts(css, outputDir) {
|
|
43143
|
-
const assetsDir =
|
|
43384
|
+
const assetsDir = join54(outputDir, "assets", "fonts");
|
|
43144
43385
|
mkdirSync28(assetsDir, { recursive: true });
|
|
43145
43386
|
const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
|
|
43146
43387
|
const fontUrls = /* @__PURE__ */ new Set();
|
|
@@ -43176,7 +43417,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
|
|
|
43176
43417
|
try {
|
|
43177
43418
|
const urlObj = new URL(fontUrl);
|
|
43178
43419
|
const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
|
|
43179
|
-
const localPath =
|
|
43420
|
+
const localPath = join54(assetsDir, filename);
|
|
43180
43421
|
const relativePath = `assets/fonts/${filename}`;
|
|
43181
43422
|
const buffer = await fetchBuffer(fontUrl);
|
|
43182
43423
|
if (buffer) {
|
|
@@ -43973,8 +44214,8 @@ var init_animationCataloger = __esm({
|
|
|
43973
44214
|
});
|
|
43974
44215
|
|
|
43975
44216
|
// src/capture/mediaCapture.ts
|
|
43976
|
-
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync23, readdirSync as
|
|
43977
|
-
import { join as
|
|
44217
|
+
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync23, readdirSync as readdirSync18, readFileSync as readFileSync38, statSync as statSync20 } from "fs";
|
|
44218
|
+
import { join as join55 } from "path";
|
|
43978
44219
|
async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
43979
44220
|
let savedCount = 0;
|
|
43980
44221
|
const savedHashes = /* @__PURE__ */ new Set();
|
|
@@ -44007,7 +44248,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
44007
44248
|
const hash2 = buf.toString("base64").slice(0, 100);
|
|
44008
44249
|
if (savedHashes.has(hash2)) continue;
|
|
44009
44250
|
savedHashes.add(hash2);
|
|
44010
|
-
writeFileSync23(
|
|
44251
|
+
writeFileSync23(join55(lottieDir, `animation-${savedCount}.lottie`), buf);
|
|
44011
44252
|
savedCount++;
|
|
44012
44253
|
continue;
|
|
44013
44254
|
}
|
|
@@ -44025,7 +44266,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
44025
44266
|
} catch {
|
|
44026
44267
|
continue;
|
|
44027
44268
|
}
|
|
44028
|
-
writeFileSync23(
|
|
44269
|
+
writeFileSync23(join55(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
|
|
44029
44270
|
savedCount++;
|
|
44030
44271
|
}
|
|
44031
44272
|
} catch {
|
|
@@ -44035,22 +44276,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
44035
44276
|
}
|
|
44036
44277
|
async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
44037
44278
|
const manifest = [];
|
|
44038
|
-
const previewDir =
|
|
44279
|
+
const previewDir = join55(lottieDir, "previews");
|
|
44039
44280
|
mkdirSync29(previewDir, { recursive: true });
|
|
44040
|
-
for (const file of
|
|
44281
|
+
for (const file of readdirSync18(lottieDir)) {
|
|
44041
44282
|
if (!file.endsWith(".json")) continue;
|
|
44042
44283
|
try {
|
|
44043
|
-
const raw = JSON.parse(readFileSync38(
|
|
44284
|
+
const raw = JSON.parse(readFileSync38(join55(lottieDir, file), "utf-8"));
|
|
44044
44285
|
const fr = raw.fr || 30;
|
|
44045
44286
|
const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
|
|
44046
44287
|
const previewName = file.replace(".json", "-preview.png");
|
|
44047
|
-
const fileSize =
|
|
44288
|
+
const fileSize = statSync20(join55(lottieDir, file)).size;
|
|
44048
44289
|
if (fileSize > 2e6) continue;
|
|
44049
44290
|
let previewPage;
|
|
44050
44291
|
try {
|
|
44051
44292
|
previewPage = await chromeBrowser.newPage();
|
|
44052
44293
|
await previewPage.setViewport({ width: 400, height: 400 });
|
|
44053
|
-
const animData = JSON.parse(readFileSync38(
|
|
44294
|
+
const animData = JSON.parse(readFileSync38(join55(lottieDir, file), "utf-8"));
|
|
44054
44295
|
const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
|
|
44055
44296
|
await previewPage.setContent(
|
|
44056
44297
|
`<!DOCTYPE html>
|
|
@@ -44080,7 +44321,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
44080
44321
|
await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
|
|
44081
44322
|
});
|
|
44082
44323
|
await previewPage.screenshot({
|
|
44083
|
-
path:
|
|
44324
|
+
path: join55(previewDir, previewName),
|
|
44084
44325
|
type: "png",
|
|
44085
44326
|
omitBackground: true
|
|
44086
44327
|
});
|
|
@@ -44104,7 +44345,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
44104
44345
|
}
|
|
44105
44346
|
if (manifest.length > 0) {
|
|
44106
44347
|
writeFileSync23(
|
|
44107
|
-
|
|
44348
|
+
join55(outputDir, "extracted", "lottie-manifest.json"),
|
|
44108
44349
|
JSON.stringify(manifest, null, 2),
|
|
44109
44350
|
"utf-8"
|
|
44110
44351
|
);
|
|
@@ -44166,15 +44407,15 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
44166
44407
|
return true;
|
|
44167
44408
|
});
|
|
44168
44409
|
if (uniqueVideos.length > 0) {
|
|
44169
|
-
const videoManifestDir =
|
|
44410
|
+
const videoManifestDir = join55(outputDir, "assets", "videos");
|
|
44170
44411
|
mkdirSync29(videoManifestDir, { recursive: true });
|
|
44171
|
-
const previewDir =
|
|
44412
|
+
const previewDir = join55(videoManifestDir, "previews");
|
|
44172
44413
|
mkdirSync29(previewDir, { recursive: true });
|
|
44173
44414
|
const videoManifest = [];
|
|
44174
44415
|
for (let vi = 0; vi < uniqueVideos.length && vi < 20; vi++) {
|
|
44175
44416
|
const v = uniqueVideos[vi];
|
|
44176
44417
|
const previewName = `video-${vi}-preview.png`;
|
|
44177
|
-
const previewPath =
|
|
44418
|
+
const previewPath = join55(previewDir, previewName);
|
|
44178
44419
|
try {
|
|
44179
44420
|
await page.evaluate(`window.scrollTo(0, ${Math.max(0, v.top - 100)})`);
|
|
44180
44421
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
@@ -44213,7 +44454,7 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
44213
44454
|
}
|
|
44214
44455
|
if (videoManifest.length > 0) {
|
|
44215
44456
|
writeFileSync23(
|
|
44216
|
-
|
|
44457
|
+
join55(outputDir, "extracted", "video-manifest.json"),
|
|
44217
44458
|
JSON.stringify(videoManifest, null, 2),
|
|
44218
44459
|
"utf-8"
|
|
44219
44460
|
);
|
|
@@ -51167,7 +51408,7 @@ var require_node_domexception = __commonJS({
|
|
|
51167
51408
|
});
|
|
51168
51409
|
|
|
51169
51410
|
// ../../node_modules/.bun/fetch-blob@3.2.0/node_modules/fetch-blob/from.js
|
|
51170
|
-
import { statSync as
|
|
51411
|
+
import { statSync as statSync21, createReadStream as createReadStream2, promises as fs2 } from "fs";
|
|
51171
51412
|
import { basename as basename11 } from "path";
|
|
51172
51413
|
var import_node_domexception, stat, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
|
|
51173
51414
|
var init_from = __esm({
|
|
@@ -51177,10 +51418,10 @@ var init_from = __esm({
|
|
|
51177
51418
|
init_file();
|
|
51178
51419
|
init_fetch_blob();
|
|
51179
51420
|
({ stat } = fs2);
|
|
51180
|
-
blobFromSync = (path2, type) => fromBlob(
|
|
51421
|
+
blobFromSync = (path2, type) => fromBlob(statSync21(path2), path2, type);
|
|
51181
51422
|
blobFrom = (path2, type) => stat(path2).then((stat3) => fromBlob(stat3, path2, type));
|
|
51182
51423
|
fileFrom = (path2, type) => stat(path2).then((stat3) => fromFile(stat3, path2, type));
|
|
51183
|
-
fileFromSync = (path2, type) => fromFile(
|
|
51424
|
+
fileFromSync = (path2, type) => fromFile(statSync21(path2), path2, type);
|
|
51184
51425
|
fromBlob = (stat3, path2, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
51185
51426
|
path: path2,
|
|
51186
51427
|
size: stat3.size,
|
|
@@ -84668,8 +84909,8 @@ ${underline2}`);
|
|
|
84668
84909
|
});
|
|
84669
84910
|
|
|
84670
84911
|
// src/capture/contentExtractor.ts
|
|
84671
|
-
import { readdirSync as
|
|
84672
|
-
import { join as
|
|
84912
|
+
import { readdirSync as readdirSync19, statSync as statSync22, readFileSync as readFileSync39 } from "fs";
|
|
84913
|
+
import { join as join56 } from "path";
|
|
84673
84914
|
async function detectLibraries(page, capturedShaders) {
|
|
84674
84915
|
let detectedLibraries = [];
|
|
84675
84916
|
try {
|
|
@@ -84789,7 +85030,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
84789
85030
|
try {
|
|
84790
85031
|
const { GoogleGenAI: GoogleGenAI2 } = await Promise.resolve().then(() => (init_node4(), node_exports));
|
|
84791
85032
|
const ai = new GoogleGenAI2({ apiKey: geminiKey });
|
|
84792
|
-
const imageFiles =
|
|
85033
|
+
const imageFiles = readdirSync19(join56(outputDir, "assets")).filter(
|
|
84793
85034
|
(f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
|
|
84794
85035
|
);
|
|
84795
85036
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -84798,8 +85039,8 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
84798
85039
|
const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
|
|
84799
85040
|
const results = await Promise.allSettled(
|
|
84800
85041
|
batch.map(async (file) => {
|
|
84801
|
-
const filePath =
|
|
84802
|
-
const stat3 =
|
|
85042
|
+
const filePath = join56(outputDir, "assets", file);
|
|
85043
|
+
const stat3 = statSync22(filePath);
|
|
84803
85044
|
if (stat3.size > 4e6) return { file, caption: "" };
|
|
84804
85045
|
const buffer = readFileSync39(filePath);
|
|
84805
85046
|
const base64 = buffer.toString("base64");
|
|
@@ -84847,12 +85088,12 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
84847
85088
|
const uncaptionedLines = [];
|
|
84848
85089
|
const svgLines = [];
|
|
84849
85090
|
const fontLines = [];
|
|
84850
|
-
const assetsPath =
|
|
85091
|
+
const assetsPath = join56(outputDir, "assets");
|
|
84851
85092
|
try {
|
|
84852
|
-
for (const file of
|
|
85093
|
+
for (const file of readdirSync19(assetsPath)) {
|
|
84853
85094
|
if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
|
|
84854
|
-
const filePath =
|
|
84855
|
-
const stat3 =
|
|
85095
|
+
const filePath = join56(assetsPath, file);
|
|
85096
|
+
const stat3 = statSync22(filePath);
|
|
84856
85097
|
if (!stat3.isFile()) continue;
|
|
84857
85098
|
const sizeKb = Math.round(stat3.size / 1024);
|
|
84858
85099
|
const catalogMatch = catalogedAssets.find(
|
|
@@ -84880,8 +85121,8 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
84880
85121
|
} catch {
|
|
84881
85122
|
}
|
|
84882
85123
|
try {
|
|
84883
|
-
const svgsPath =
|
|
84884
|
-
for (const file of
|
|
85124
|
+
const svgsPath = join56(assetsPath, "svgs");
|
|
85125
|
+
for (const file of readdirSync19(svgsPath)) {
|
|
84885
85126
|
if (!file.endsWith(".svg")) continue;
|
|
84886
85127
|
const svgMatch = tokens.svgs.find(
|
|
84887
85128
|
(s2) => s2.label && file.includes(
|
|
@@ -84895,8 +85136,8 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
84895
85136
|
} catch {
|
|
84896
85137
|
}
|
|
84897
85138
|
try {
|
|
84898
|
-
const fontsPath =
|
|
84899
|
-
for (const file of
|
|
85139
|
+
const fontsPath = join56(assetsPath, "fonts");
|
|
85140
|
+
for (const file of readdirSync19(fontsPath)) {
|
|
84900
85141
|
fontLines.push(`fonts/${file} \u2014 font file`);
|
|
84901
85142
|
}
|
|
84902
85143
|
} catch {
|
|
@@ -84915,12 +85156,12 @@ __export(agentPromptGenerator_exports, {
|
|
|
84915
85156
|
generateAgentPrompt: () => generateAgentPrompt
|
|
84916
85157
|
});
|
|
84917
85158
|
import { writeFileSync as writeFileSync24 } from "fs";
|
|
84918
|
-
import { join as
|
|
85159
|
+
import { join as join57 } from "path";
|
|
84919
85160
|
function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, detectedLibraries) {
|
|
84920
85161
|
const prompt = buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries);
|
|
84921
|
-
writeFileSync24(
|
|
84922
|
-
writeFileSync24(
|
|
84923
|
-
writeFileSync24(
|
|
85162
|
+
writeFileSync24(join57(outputDir, "AGENTS.md"), prompt, "utf-8");
|
|
85163
|
+
writeFileSync24(join57(outputDir, "CLAUDE.md"), prompt, "utf-8");
|
|
85164
|
+
writeFileSync24(join57(outputDir, ".cursorrules"), prompt, "utf-8");
|
|
84924
85165
|
}
|
|
84925
85166
|
function buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries) {
|
|
84926
85167
|
const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
|
|
@@ -84987,8 +85228,8 @@ var init_agentPromptGenerator = __esm({
|
|
|
84987
85228
|
});
|
|
84988
85229
|
|
|
84989
85230
|
// src/capture/scaffolding.ts
|
|
84990
|
-
import { existsSync as
|
|
84991
|
-
import { join as
|
|
85231
|
+
import { existsSync as existsSync54, writeFileSync as writeFileSync25, readFileSync as readFileSync40 } from "fs";
|
|
85232
|
+
import { join as join58, resolve as resolve37 } from "path";
|
|
84992
85233
|
function loadEnvFile(startDir) {
|
|
84993
85234
|
try {
|
|
84994
85235
|
let dir = resolve37(startDir);
|
|
@@ -85014,8 +85255,8 @@ function loadEnvFile(startDir) {
|
|
|
85014
85255
|
}
|
|
85015
85256
|
}
|
|
85016
85257
|
async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
|
|
85017
|
-
const metaPath =
|
|
85018
|
-
if (!
|
|
85258
|
+
const metaPath = join58(outputDir, "meta.json");
|
|
85259
|
+
if (!existsSync54(metaPath)) {
|
|
85019
85260
|
const hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
85020
85261
|
writeFileSync25(
|
|
85021
85262
|
metaPath,
|
|
@@ -85053,9 +85294,9 @@ __export(screenshotCapture_exports, {
|
|
|
85053
85294
|
captureScrollScreenshots: () => captureScrollScreenshots
|
|
85054
85295
|
});
|
|
85055
85296
|
import { writeFileSync as writeFileSync26, mkdirSync as mkdirSync30 } from "fs";
|
|
85056
|
-
import { join as
|
|
85297
|
+
import { join as join59 } from "path";
|
|
85057
85298
|
async function captureScrollScreenshots(page, outputDir) {
|
|
85058
|
-
const screenshotsDir =
|
|
85299
|
+
const screenshotsDir = join59(outputDir, "screenshots");
|
|
85059
85300
|
mkdirSync30(screenshotsDir, { recursive: true });
|
|
85060
85301
|
const MAX_SCREENSHOTS = 20;
|
|
85061
85302
|
const filePaths = [];
|
|
@@ -85089,7 +85330,7 @@ async function captureScrollScreenshots(page, outputDir) {
|
|
|
85089
85330
|
finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
|
|
85090
85331
|
);
|
|
85091
85332
|
const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
|
|
85092
|
-
const filePath =
|
|
85333
|
+
const filePath = join59(screenshotsDir, filename);
|
|
85093
85334
|
const buffer = await page.screenshot({ type: "png" });
|
|
85094
85335
|
writeFileSync26(filePath, buffer);
|
|
85095
85336
|
filePaths.push(`screenshots/${filename}`);
|
|
@@ -85402,8 +85643,8 @@ var capture_exports = {};
|
|
|
85402
85643
|
__export(capture_exports, {
|
|
85403
85644
|
captureWebsite: () => captureWebsite
|
|
85404
85645
|
});
|
|
85405
|
-
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27, existsSync as
|
|
85406
|
-
import { join as
|
|
85646
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27, existsSync as existsSync55 } from "fs";
|
|
85647
|
+
import { join as join60 } from "path";
|
|
85407
85648
|
async function captureWebsite(opts, onProgress) {
|
|
85408
85649
|
const {
|
|
85409
85650
|
url,
|
|
@@ -85420,9 +85661,9 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85420
85661
|
onProgress?.(stage, detail);
|
|
85421
85662
|
};
|
|
85422
85663
|
loadEnvFile(outputDir);
|
|
85423
|
-
mkdirSync31(
|
|
85424
|
-
mkdirSync31(
|
|
85425
|
-
mkdirSync31(
|
|
85664
|
+
mkdirSync31(join60(outputDir, "extracted"), { recursive: true });
|
|
85665
|
+
mkdirSync31(join60(outputDir, "screenshots"), { recursive: true });
|
|
85666
|
+
mkdirSync31(join60(outputDir, "assets"), { recursive: true });
|
|
85426
85667
|
progress("browser", "Launching headless Chrome...");
|
|
85427
85668
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
85428
85669
|
const browser = await ensureBrowser2();
|
|
@@ -85578,7 +85819,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85578
85819
|
} catch {
|
|
85579
85820
|
}
|
|
85580
85821
|
if (discoveredLotties.length > 0) {
|
|
85581
|
-
const lottieDir =
|
|
85822
|
+
const lottieDir = join60(outputDir, "assets", "lottie");
|
|
85582
85823
|
mkdirSync31(lottieDir, { recursive: true });
|
|
85583
85824
|
const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
|
|
85584
85825
|
if (savedCount > 0) {
|
|
@@ -85598,7 +85839,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85598
85839
|
});
|
|
85599
85840
|
capturedShaders = unique;
|
|
85600
85841
|
writeFileSync27(
|
|
85601
|
-
|
|
85842
|
+
join60(outputDir, "extracted", "shaders.json"),
|
|
85602
85843
|
JSON.stringify(unique, null, 2),
|
|
85603
85844
|
"utf-8"
|
|
85604
85845
|
);
|
|
@@ -85609,7 +85850,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85609
85850
|
progress("tokens", "Extracting design tokens...");
|
|
85610
85851
|
const tokens = await extractTokens(page1);
|
|
85611
85852
|
writeFileSync27(
|
|
85612
|
-
|
|
85853
|
+
join60(outputDir, "extracted", "tokens.json"),
|
|
85613
85854
|
JSON.stringify(tokens, null, 2),
|
|
85614
85855
|
"utf-8"
|
|
85615
85856
|
);
|
|
@@ -85683,7 +85924,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85683
85924
|
representativeAnimations: representativeAnims
|
|
85684
85925
|
};
|
|
85685
85926
|
writeFileSync27(
|
|
85686
|
-
|
|
85927
|
+
join60(outputDir, "extracted", "animations.json"),
|
|
85687
85928
|
JSON.stringify(leanCatalog, null, 2),
|
|
85688
85929
|
"utf-8"
|
|
85689
85930
|
);
|
|
@@ -85694,18 +85935,18 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85694
85935
|
assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
|
|
85695
85936
|
}
|
|
85696
85937
|
if (visibleTextContent) {
|
|
85697
|
-
writeFileSync27(
|
|
85938
|
+
writeFileSync27(join60(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
|
|
85698
85939
|
}
|
|
85699
85940
|
if (catalogedAssets.length > 0) {
|
|
85700
85941
|
writeFileSync27(
|
|
85701
|
-
|
|
85942
|
+
join60(outputDir, "extracted", "assets-catalog.json"),
|
|
85702
85943
|
JSON.stringify(catalogedAssets, null, 2),
|
|
85703
85944
|
"utf-8"
|
|
85704
85945
|
);
|
|
85705
85946
|
}
|
|
85706
85947
|
if (detectedLibraries.length > 0) {
|
|
85707
85948
|
writeFileSync27(
|
|
85708
|
-
|
|
85949
|
+
join60(outputDir, "extracted", "detected-libraries.json"),
|
|
85709
85950
|
JSON.stringify(detectedLibraries, null, 2),
|
|
85710
85951
|
"utf-8"
|
|
85711
85952
|
);
|
|
@@ -85716,7 +85957,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85716
85957
|
const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
|
|
85717
85958
|
if (lines.length > 0) {
|
|
85718
85959
|
writeFileSync27(
|
|
85719
|
-
|
|
85960
|
+
join60(outputDir, "extracted", "asset-descriptions.md"),
|
|
85720
85961
|
"# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
|
|
85721
85962
|
"utf-8"
|
|
85722
85963
|
);
|
|
@@ -85732,7 +85973,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
85732
85973
|
animationCatalog,
|
|
85733
85974
|
screenshots.length > 0,
|
|
85734
85975
|
discoveredLotties.length > 0,
|
|
85735
|
-
|
|
85976
|
+
existsSync55(join60(outputDir, "extracted", "shaders.json")),
|
|
85736
85977
|
catalogedAssets,
|
|
85737
85978
|
progress,
|
|
85738
85979
|
warnings,
|
|
@@ -86080,8 +86321,8 @@ __export(autoUpdate_exports, {
|
|
|
86080
86321
|
});
|
|
86081
86322
|
import { spawn as spawn13 } from "child_process";
|
|
86082
86323
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync32, openSync as openSync2 } from "fs";
|
|
86083
|
-
import { homedir as
|
|
86084
|
-
import { join as
|
|
86324
|
+
import { homedir as homedir11 } from "os";
|
|
86325
|
+
import { join as join61 } from "path";
|
|
86085
86326
|
import { compareVersions as compareVersions2 } from "compare-versions";
|
|
86086
86327
|
function isAutoInstallDisabled() {
|
|
86087
86328
|
if (isDevMode()) return true;
|
|
@@ -86104,7 +86345,7 @@ function log(line) {
|
|
|
86104
86345
|
}
|
|
86105
86346
|
function launchDetachedInstall(installCommand, version) {
|
|
86106
86347
|
mkdirSync32(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
86107
|
-
const configFile =
|
|
86348
|
+
const configFile = join61(CONFIG_DIR2, "config.json");
|
|
86108
86349
|
const nodeScript = `
|
|
86109
86350
|
const { exec } = require("node:child_process");
|
|
86110
86351
|
const { readFileSync, renameSync, writeFileSync } = require("node:fs");
|
|
@@ -86223,8 +86464,8 @@ var init_autoUpdate = __esm({
|
|
|
86223
86464
|
init_config();
|
|
86224
86465
|
init_env();
|
|
86225
86466
|
init_installerDetection();
|
|
86226
|
-
CONFIG_DIR2 =
|
|
86227
|
-
LOG_FILE =
|
|
86467
|
+
CONFIG_DIR2 = join61(homedir11(), ".hyperframes");
|
|
86468
|
+
LOG_FILE = join61(CONFIG_DIR2, "auto-update.log");
|
|
86228
86469
|
PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
86229
86470
|
}
|
|
86230
86471
|
});
|