hyperframes 0.4.28 → 0.4.30
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
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.4.
|
|
57
|
+
VERSION = true ? "0.4.30" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -9838,8 +9838,8 @@ function flushSync() {
|
|
|
9838
9838
|
eventQueue = [];
|
|
9839
9839
|
const payload = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
|
|
9840
9840
|
try {
|
|
9841
|
-
const { spawn:
|
|
9842
|
-
const child =
|
|
9841
|
+
const { spawn: spawn14 } = __require("child_process");
|
|
9842
|
+
const child = spawn14(
|
|
9843
9843
|
process.execPath,
|
|
9844
9844
|
[
|
|
9845
9845
|
"-e",
|
|
@@ -10491,9 +10491,9 @@ function findWavDataChunk(buf) {
|
|
|
10491
10491
|
return null;
|
|
10492
10492
|
}
|
|
10493
10493
|
function detectSpeechOnset(wavPath) {
|
|
10494
|
-
const
|
|
10494
|
+
const SAMPLE_RATE2 = 16e3;
|
|
10495
10495
|
const WINDOW_SECONDS = 0.5;
|
|
10496
|
-
const WINDOW_SAMPLES =
|
|
10496
|
+
const WINDOW_SAMPLES = SAMPLE_RATE2 * WINDOW_SECONDS;
|
|
10497
10497
|
const SUSTAINED_WINDOWS = 3;
|
|
10498
10498
|
const SILENCE_THRESHOLD_RATIO = 0.6;
|
|
10499
10499
|
const MIN_INTRO_SECONDS = 3;
|
|
@@ -11390,11 +11390,138 @@ var init_projects = __esm({
|
|
|
11390
11390
|
}
|
|
11391
11391
|
});
|
|
11392
11392
|
|
|
11393
|
+
// ../core/src/studio-api/helpers/mime.ts
|
|
11394
|
+
function getMimeType(path2) {
|
|
11395
|
+
const ext = path2.slice(path2.lastIndexOf(".")).toLowerCase();
|
|
11396
|
+
return MIME_TYPES[ext] || "application/octet-stream";
|
|
11397
|
+
}
|
|
11398
|
+
function isAudioFile2(name) {
|
|
11399
|
+
return (getMimeType(name) ?? "").startsWith("audio/");
|
|
11400
|
+
}
|
|
11401
|
+
var MIME_TYPES;
|
|
11402
|
+
var init_mime = __esm({
|
|
11403
|
+
"../core/src/studio-api/helpers/mime.ts"() {
|
|
11404
|
+
"use strict";
|
|
11405
|
+
MIME_TYPES = {
|
|
11406
|
+
".html": "text/html",
|
|
11407
|
+
".css": "text/css",
|
|
11408
|
+
".js": "text/javascript",
|
|
11409
|
+
".mjs": "text/javascript",
|
|
11410
|
+
".json": "application/json",
|
|
11411
|
+
".svg": "image/svg+xml",
|
|
11412
|
+
".png": "image/png",
|
|
11413
|
+
".jpg": "image/jpeg",
|
|
11414
|
+
".jpeg": "image/jpeg",
|
|
11415
|
+
".gif": "image/gif",
|
|
11416
|
+
".webp": "image/webp",
|
|
11417
|
+
".ico": "image/x-icon",
|
|
11418
|
+
".mp4": "video/mp4",
|
|
11419
|
+
".mov": "video/quicktime",
|
|
11420
|
+
".webm": "video/webm",
|
|
11421
|
+
".mp3": "audio/mpeg",
|
|
11422
|
+
".wav": "audio/wav",
|
|
11423
|
+
".ogg": "audio/ogg",
|
|
11424
|
+
".m4a": "audio/mp4",
|
|
11425
|
+
".aac": "audio/aac",
|
|
11426
|
+
".flac": "audio/flac",
|
|
11427
|
+
".opus": "audio/ogg",
|
|
11428
|
+
".woff": "font/woff",
|
|
11429
|
+
".woff2": "font/woff2",
|
|
11430
|
+
".ttf": "font/ttf",
|
|
11431
|
+
".otf": "font/otf",
|
|
11432
|
+
".txt": "text/plain",
|
|
11433
|
+
".md": "text/markdown"
|
|
11434
|
+
};
|
|
11435
|
+
}
|
|
11436
|
+
});
|
|
11437
|
+
|
|
11438
|
+
// ../core/src/studio-api/helpers/waveform.ts
|
|
11439
|
+
import { spawn as spawn2 } from "child_process";
|
|
11440
|
+
import { existsSync as existsSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
11441
|
+
import { join as join11 } from "path";
|
|
11442
|
+
function buildWaveformCacheKey(assetPath) {
|
|
11443
|
+
return `${WAVEFORM_CACHE_VERSION}_${assetPath.replace(/[/\\]/g, "_")}.json`;
|
|
11444
|
+
}
|
|
11445
|
+
function computePeaks(floats, count) {
|
|
11446
|
+
const step = floats.length / count;
|
|
11447
|
+
const peaks = [];
|
|
11448
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
11449
|
+
const start = Math.floor(i2 * step);
|
|
11450
|
+
const end = Math.min(Math.floor((i2 + 1) * step), floats.length);
|
|
11451
|
+
let max = 0;
|
|
11452
|
+
for (let j2 = start; j2 < end; j2++) {
|
|
11453
|
+
const abs = Math.abs(floats[j2] ?? 0);
|
|
11454
|
+
if (abs > max) max = abs;
|
|
11455
|
+
}
|
|
11456
|
+
peaks.push(max);
|
|
11457
|
+
}
|
|
11458
|
+
const maxPeak = Math.max(...peaks, 1e-3);
|
|
11459
|
+
return peaks.map((p) => p / maxPeak);
|
|
11460
|
+
}
|
|
11461
|
+
function decodeAudioPeaks(audioPath) {
|
|
11462
|
+
return new Promise((resolve39, reject) => {
|
|
11463
|
+
const proc = spawn2(
|
|
11464
|
+
"ffmpeg",
|
|
11465
|
+
[
|
|
11466
|
+
"-i",
|
|
11467
|
+
audioPath,
|
|
11468
|
+
"-af",
|
|
11469
|
+
"atrim=start_sample=1152",
|
|
11470
|
+
"-f",
|
|
11471
|
+
"f32le",
|
|
11472
|
+
"-ac",
|
|
11473
|
+
"1",
|
|
11474
|
+
"-ar",
|
|
11475
|
+
String(SAMPLE_RATE),
|
|
11476
|
+
"-vn",
|
|
11477
|
+
"pipe:1"
|
|
11478
|
+
],
|
|
11479
|
+
{ stdio: ["ignore", "pipe", "ignore"] }
|
|
11480
|
+
);
|
|
11481
|
+
const chunks = [];
|
|
11482
|
+
proc.stdout?.on("data", (chunk) => chunks.push(chunk));
|
|
11483
|
+
proc.on("close", (code) => {
|
|
11484
|
+
if (code !== 0 && chunks.length === 0) {
|
|
11485
|
+
reject(new Error(`ffmpeg exited with code ${code}`));
|
|
11486
|
+
return;
|
|
11487
|
+
}
|
|
11488
|
+
const buf = Buffer.concat(chunks);
|
|
11489
|
+
const numSamples = Math.floor(buf.length / 4);
|
|
11490
|
+
if (numSamples === 0) {
|
|
11491
|
+
reject(new Error("ffmpeg produced no audio samples"));
|
|
11492
|
+
return;
|
|
11493
|
+
}
|
|
11494
|
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);
|
|
11495
|
+
resolve39(computePeaks(new Float32Array(ab), PEAK_COUNT));
|
|
11496
|
+
});
|
|
11497
|
+
proc.on("error", reject);
|
|
11498
|
+
});
|
|
11499
|
+
}
|
|
11500
|
+
async function generateWaveformCache(projectDir, assetPath) {
|
|
11501
|
+
const audioPath = join11(projectDir, assetPath);
|
|
11502
|
+
if (!existsSync9(audioPath)) return;
|
|
11503
|
+
const cacheDir = join11(projectDir, ".waveform-cache");
|
|
11504
|
+
const cachePath2 = join11(cacheDir, buildWaveformCacheKey(assetPath));
|
|
11505
|
+
if (existsSync9(cachePath2)) return;
|
|
11506
|
+
const peaks = await decodeAudioPeaks(audioPath);
|
|
11507
|
+
mkdirSync5(cacheDir, { recursive: true });
|
|
11508
|
+
writeFileSync5(cachePath2, JSON.stringify(peaks));
|
|
11509
|
+
}
|
|
11510
|
+
var SAMPLE_RATE, PEAK_COUNT, WAVEFORM_CACHE_VERSION;
|
|
11511
|
+
var init_waveform = __esm({
|
|
11512
|
+
"../core/src/studio-api/helpers/waveform.ts"() {
|
|
11513
|
+
"use strict";
|
|
11514
|
+
SAMPLE_RATE = 4e3;
|
|
11515
|
+
PEAK_COUNT = 4e3;
|
|
11516
|
+
WAVEFORM_CACHE_VERSION = "v2";
|
|
11517
|
+
}
|
|
11518
|
+
});
|
|
11519
|
+
|
|
11393
11520
|
// ../core/src/studio-api/helpers/mediaValidation.ts
|
|
11394
11521
|
import { spawnSync } from "child_process";
|
|
11395
|
-
import { mkdtempSync, rmSync as rmSync2, writeFileSync as
|
|
11522
|
+
import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
11396
11523
|
import { tmpdir as tmpdir2 } from "os";
|
|
11397
|
-
import { basename, join as
|
|
11524
|
+
import { basename, join as join12 } from "path";
|
|
11398
11525
|
function validateUploadedMedia(filePath, runner = spawnSync) {
|
|
11399
11526
|
const isVideo2 = VIDEO_EXT.test(filePath);
|
|
11400
11527
|
const isAudio = AUDIO_EXT.test(filePath);
|
|
@@ -11433,10 +11560,10 @@ function validateUploadedMedia(filePath, runner = spawnSync) {
|
|
|
11433
11560
|
}
|
|
11434
11561
|
}
|
|
11435
11562
|
function validateUploadedMediaBuffer(fileName, buffer, runner = spawnSync) {
|
|
11436
|
-
const tempDir = mkdtempSync(
|
|
11437
|
-
const tempPath =
|
|
11563
|
+
const tempDir = mkdtempSync(join12(tmpdir2(), "hyperframes-upload-"));
|
|
11564
|
+
const tempPath = join12(tempDir, basename(fileName));
|
|
11438
11565
|
try {
|
|
11439
|
-
|
|
11566
|
+
writeFileSync6(tempPath, buffer);
|
|
11440
11567
|
return validateUploadedMedia(tempPath, runner);
|
|
11441
11568
|
} finally {
|
|
11442
11569
|
rmSync2(tempDir, { recursive: true, force: true });
|
|
@@ -23289,7 +23416,7 @@ var init_html_classes = __esm({
|
|
|
23289
23416
|
|
|
23290
23417
|
// ../../node_modules/.bun/linkedom@0.18.12/node_modules/linkedom/esm/shared/mime.js
|
|
23291
23418
|
var voidElements2, Mime;
|
|
23292
|
-
var
|
|
23419
|
+
var init_mime2 = __esm({
|
|
23293
23420
|
"../../node_modules/.bun/linkedom@0.18.12/node_modules/linkedom/esm/shared/mime.js"() {
|
|
23294
23421
|
"use strict";
|
|
23295
23422
|
voidElements2 = { test: () => true };
|
|
@@ -23554,7 +23681,7 @@ var init_document = __esm({
|
|
|
23554
23681
|
init_symbols();
|
|
23555
23682
|
init_facades();
|
|
23556
23683
|
init_html_classes();
|
|
23557
|
-
|
|
23684
|
+
init_mime2();
|
|
23558
23685
|
init_utils2();
|
|
23559
23686
|
init_object();
|
|
23560
23687
|
init_non_element_parent_node();
|
|
@@ -24093,17 +24220,17 @@ var init_sourceMutation = __esm({
|
|
|
24093
24220
|
// ../core/src/studio-api/routes/files.ts
|
|
24094
24221
|
import { bodyLimit } from "hono/body-limit";
|
|
24095
24222
|
import {
|
|
24096
|
-
existsSync as
|
|
24223
|
+
existsSync as existsSync10,
|
|
24097
24224
|
readFileSync as readFileSync9,
|
|
24098
|
-
writeFileSync as
|
|
24099
|
-
mkdirSync as
|
|
24225
|
+
writeFileSync as writeFileSync7,
|
|
24226
|
+
mkdirSync as mkdirSync6,
|
|
24100
24227
|
unlinkSync as unlinkSync3,
|
|
24101
24228
|
rmSync as rmSync3,
|
|
24102
24229
|
statSync,
|
|
24103
24230
|
renameSync as renameSync2,
|
|
24104
24231
|
readdirSync as readdirSync4
|
|
24105
24232
|
} from "fs";
|
|
24106
|
-
import { resolve as resolve9, dirname as dirname5, join as
|
|
24233
|
+
import { resolve as resolve9, dirname as dirname5, join as join13 } from "path";
|
|
24107
24234
|
async function resolveProjectFile(c2, adapter2, opts) {
|
|
24108
24235
|
const id = c2.req.param("id");
|
|
24109
24236
|
const project = await adapter2.resolveProject(id);
|
|
@@ -24118,14 +24245,14 @@ async function resolveProjectFile(c2, adapter2, opts) {
|
|
|
24118
24245
|
if (!isSafePath(project.dir, absPath)) {
|
|
24119
24246
|
return { error: c2.json({ error: "forbidden" }, 403) };
|
|
24120
24247
|
}
|
|
24121
|
-
if (opts?.mustExist && !
|
|
24248
|
+
if (opts?.mustExist && !existsSync10(absPath)) {
|
|
24122
24249
|
return { error: c2.json({ error: "not found" }, 404) };
|
|
24123
24250
|
}
|
|
24124
24251
|
return { project, filePath, absPath };
|
|
24125
24252
|
}
|
|
24126
24253
|
function ensureDir(filePath) {
|
|
24127
24254
|
const dir = dirname5(filePath);
|
|
24128
|
-
if (!
|
|
24255
|
+
if (!existsSync10(dir)) mkdirSync6(dir, { recursive: true });
|
|
24129
24256
|
}
|
|
24130
24257
|
function generateCopyPath(projectDir, originalPath) {
|
|
24131
24258
|
const ext = originalPath.includes(".") ? "." + originalPath.split(".").pop() : "";
|
|
@@ -24134,7 +24261,7 @@ function generateCopyPath(projectDir, originalPath) {
|
|
|
24134
24261
|
const cleanBase = copyMatch ? base.slice(0, -copyMatch[0].length) : base;
|
|
24135
24262
|
let num = copyMatch ? copyMatch[1] ? parseInt(copyMatch[1]) + 1 : 2 : 1;
|
|
24136
24263
|
let candidate = num === 1 ? `${cleanBase} (copy)${ext}` : `${cleanBase} (copy ${num})${ext}`;
|
|
24137
|
-
while (
|
|
24264
|
+
while (existsSync10(resolve9(projectDir, candidate))) {
|
|
24138
24265
|
num++;
|
|
24139
24266
|
candidate = `${cleanBase} (copy ${num})${ext}`;
|
|
24140
24267
|
}
|
|
@@ -24143,7 +24270,7 @@ function generateCopyPath(projectDir, originalPath) {
|
|
|
24143
24270
|
function walkFiles(dir, filter2) {
|
|
24144
24271
|
const results = [];
|
|
24145
24272
|
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
24146
|
-
const full =
|
|
24273
|
+
const full = join13(dir, entry.name);
|
|
24147
24274
|
if (entry.isDirectory()) {
|
|
24148
24275
|
if (entry.name === "node_modules" || entry.name === ".thumbnails" || entry.name === "renders")
|
|
24149
24276
|
continue;
|
|
@@ -24165,7 +24292,7 @@ function updateReferences(projectDir, oldPath, newPath) {
|
|
|
24165
24292
|
if (!content.includes(oldPath)) continue;
|
|
24166
24293
|
const updated = content.split(oldPath).join(newPath);
|
|
24167
24294
|
if (updated !== content) {
|
|
24168
|
-
|
|
24295
|
+
writeFileSync7(file, updated, "utf-8");
|
|
24169
24296
|
updatedCount++;
|
|
24170
24297
|
}
|
|
24171
24298
|
}
|
|
@@ -24183,18 +24310,18 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24183
24310
|
if ("error" in res) return res.error;
|
|
24184
24311
|
ensureDir(res.absPath);
|
|
24185
24312
|
const body = await c2.req.text();
|
|
24186
|
-
|
|
24313
|
+
writeFileSync7(res.absPath, body, "utf-8");
|
|
24187
24314
|
return c2.json({ ok: true });
|
|
24188
24315
|
});
|
|
24189
24316
|
api.post("/projects/:id/files/*", async (c2) => {
|
|
24190
24317
|
const res = await resolveProjectFile(c2, adapter2);
|
|
24191
24318
|
if ("error" in res) return res.error;
|
|
24192
|
-
if (
|
|
24319
|
+
if (existsSync10(res.absPath)) {
|
|
24193
24320
|
return c2.json({ error: "already exists" }, 409);
|
|
24194
24321
|
}
|
|
24195
24322
|
ensureDir(res.absPath);
|
|
24196
24323
|
const body = await c2.req.text().catch(() => "");
|
|
24197
|
-
|
|
24324
|
+
writeFileSync7(res.absPath, body, "utf-8");
|
|
24198
24325
|
return c2.json({ ok: true, path: res.filePath }, 201);
|
|
24199
24326
|
});
|
|
24200
24327
|
api.delete("/projects/:id/files/*", async (c2) => {
|
|
@@ -24222,7 +24349,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24222
24349
|
if (!isSafePath(project.dir, absPath)) {
|
|
24223
24350
|
return c2.json({ error: "forbidden" }, 403);
|
|
24224
24351
|
}
|
|
24225
|
-
if (!
|
|
24352
|
+
if (!existsSync10(absPath)) {
|
|
24226
24353
|
return c2.json({ error: "not found" }, 404);
|
|
24227
24354
|
}
|
|
24228
24355
|
const body = await c2.req.json().catch(() => null);
|
|
@@ -24234,7 +24361,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24234
24361
|
if (patchedContent === originalContent) {
|
|
24235
24362
|
return c2.json({ ok: true, changed: false, content: originalContent });
|
|
24236
24363
|
}
|
|
24237
|
-
|
|
24364
|
+
writeFileSync7(absPath, patchedContent, "utf-8");
|
|
24238
24365
|
return c2.json({ ok: true, changed: true, content: patchedContent });
|
|
24239
24366
|
});
|
|
24240
24367
|
api.patch("/projects/:id/files/*", async (c2) => {
|
|
@@ -24248,7 +24375,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24248
24375
|
if (!isSafePath(res.project.dir, newAbs)) {
|
|
24249
24376
|
return c2.json({ error: "forbidden" }, 403);
|
|
24250
24377
|
}
|
|
24251
|
-
if (
|
|
24378
|
+
if (existsSync10(newAbs)) {
|
|
24252
24379
|
return c2.json({ error: "already exists" }, 409);
|
|
24253
24380
|
}
|
|
24254
24381
|
ensureDir(newAbs);
|
|
@@ -24264,7 +24391,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24264
24391
|
return c2.json({ error: "path required" }, 400);
|
|
24265
24392
|
}
|
|
24266
24393
|
const srcAbs = resolve9(project.dir, body.path);
|
|
24267
|
-
if (!isSafePath(project.dir, srcAbs) || !
|
|
24394
|
+
if (!isSafePath(project.dir, srcAbs) || !existsSync10(srcAbs)) {
|
|
24268
24395
|
return c2.json({ error: "not found" }, 404);
|
|
24269
24396
|
}
|
|
24270
24397
|
const copyPath = generateCopyPath(project.dir, body.path);
|
|
@@ -24273,7 +24400,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24273
24400
|
return c2.json({ error: "forbidden" }, 403);
|
|
24274
24401
|
}
|
|
24275
24402
|
ensureDir(destAbs);
|
|
24276
|
-
|
|
24403
|
+
writeFileSync7(destAbs, readFileSync9(srcAbs));
|
|
24277
24404
|
return c2.json({ ok: true, path: copyPath }, 201);
|
|
24278
24405
|
});
|
|
24279
24406
|
const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
|
|
@@ -24289,7 +24416,7 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24289
24416
|
const subDir = c2.req.query("dir") ?? "";
|
|
24290
24417
|
const targetDir = subDir ? resolve9(project.dir, subDir) : project.dir;
|
|
24291
24418
|
if (!isSafePath(project.dir, targetDir)) return c2.json({ error: "forbidden" }, 403);
|
|
24292
|
-
if (subDir && !
|
|
24419
|
+
if (subDir && !existsSync10(targetDir)) mkdirSync6(targetDir, { recursive: true });
|
|
24293
24420
|
const formData = await c2.req.formData();
|
|
24294
24421
|
const uploaded = [];
|
|
24295
24422
|
const skipped = [];
|
|
@@ -24306,12 +24433,12 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24306
24433
|
if (!isSafePath(project.dir, destPath)) continue;
|
|
24307
24434
|
let finalPath = destPath;
|
|
24308
24435
|
let finalName = name;
|
|
24309
|
-
if (
|
|
24436
|
+
if (existsSync10(finalPath)) {
|
|
24310
24437
|
const dotIdx = name.indexOf(".", name.startsWith(".") ? 1 : 0);
|
|
24311
24438
|
const ext = dotIdx > 0 ? name.slice(dotIdx) : "";
|
|
24312
24439
|
const base = dotIdx > 0 ? name.slice(0, dotIdx) : name;
|
|
24313
24440
|
let n = 2;
|
|
24314
|
-
while (n < 1e4 &&
|
|
24441
|
+
while (n < 1e4 && existsSync10(resolve9(targetDir, `${base} (${n})${ext}`))) n++;
|
|
24315
24442
|
if (n >= 1e4) {
|
|
24316
24443
|
skipped.push(name);
|
|
24317
24444
|
continue;
|
|
@@ -24325,8 +24452,13 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24325
24452
|
invalid.push({ name: finalName, reason: validation.reason });
|
|
24326
24453
|
continue;
|
|
24327
24454
|
}
|
|
24328
|
-
|
|
24329
|
-
|
|
24455
|
+
writeFileSync7(finalPath, buffer);
|
|
24456
|
+
const relativePath = subDir ? join13(subDir, finalName) : finalName;
|
|
24457
|
+
uploaded.push(relativePath);
|
|
24458
|
+
if (isAudioFile2(finalName)) {
|
|
24459
|
+
generateWaveformCache(project.dir, relativePath).catch(() => {
|
|
24460
|
+
});
|
|
24461
|
+
}
|
|
24330
24462
|
}
|
|
24331
24463
|
return c2.json({ ok: true, files: uploaded, skipped, invalid }, 201);
|
|
24332
24464
|
}
|
|
@@ -24335,57 +24467,20 @@ function registerFileRoutes(api, adapter2) {
|
|
|
24335
24467
|
var init_files = __esm({
|
|
24336
24468
|
"../core/src/studio-api/routes/files.ts"() {
|
|
24337
24469
|
"use strict";
|
|
24470
|
+
init_mime();
|
|
24471
|
+
init_waveform();
|
|
24338
24472
|
init_mediaValidation();
|
|
24339
24473
|
init_safePath();
|
|
24340
24474
|
init_sourceMutation();
|
|
24341
24475
|
}
|
|
24342
24476
|
});
|
|
24343
24477
|
|
|
24344
|
-
// ../core/src/studio-api/helpers/mime.ts
|
|
24345
|
-
function getMimeType(path2) {
|
|
24346
|
-
const ext = path2.slice(path2.lastIndexOf(".")).toLowerCase();
|
|
24347
|
-
return MIME_TYPES[ext] || "application/octet-stream";
|
|
24348
|
-
}
|
|
24349
|
-
var MIME_TYPES;
|
|
24350
|
-
var init_mime2 = __esm({
|
|
24351
|
-
"../core/src/studio-api/helpers/mime.ts"() {
|
|
24352
|
-
"use strict";
|
|
24353
|
-
MIME_TYPES = {
|
|
24354
|
-
".html": "text/html",
|
|
24355
|
-
".css": "text/css",
|
|
24356
|
-
".js": "text/javascript",
|
|
24357
|
-
".mjs": "text/javascript",
|
|
24358
|
-
".json": "application/json",
|
|
24359
|
-
".svg": "image/svg+xml",
|
|
24360
|
-
".png": "image/png",
|
|
24361
|
-
".jpg": "image/jpeg",
|
|
24362
|
-
".jpeg": "image/jpeg",
|
|
24363
|
-
".gif": "image/gif",
|
|
24364
|
-
".webp": "image/webp",
|
|
24365
|
-
".ico": "image/x-icon",
|
|
24366
|
-
".mp4": "video/mp4",
|
|
24367
|
-
".mov": "video/quicktime",
|
|
24368
|
-
".webm": "video/webm",
|
|
24369
|
-
".mp3": "audio/mpeg",
|
|
24370
|
-
".wav": "audio/wav",
|
|
24371
|
-
".ogg": "audio/ogg",
|
|
24372
|
-
".m4a": "audio/mp4",
|
|
24373
|
-
".woff": "font/woff",
|
|
24374
|
-
".woff2": "font/woff2",
|
|
24375
|
-
".ttf": "font/ttf",
|
|
24376
|
-
".otf": "font/otf",
|
|
24377
|
-
".txt": "text/plain",
|
|
24378
|
-
".md": "text/markdown"
|
|
24379
|
-
};
|
|
24380
|
-
}
|
|
24381
|
-
});
|
|
24382
|
-
|
|
24383
24478
|
// ../core/src/studio-api/helpers/subComposition.ts
|
|
24384
|
-
import { existsSync as
|
|
24385
|
-
import { join as
|
|
24479
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
24480
|
+
import { join as join14 } from "path";
|
|
24386
24481
|
function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
|
|
24387
|
-
const compFile =
|
|
24388
|
-
if (!
|
|
24482
|
+
const compFile = join14(projectDir, compPath);
|
|
24483
|
+
if (!existsSync11(compFile)) return null;
|
|
24389
24484
|
const rawComp = readFileSync10(compFile, "utf-8");
|
|
24390
24485
|
const templateMatch = rawComp.match(/<template[^>]*>([\s\S]*)<\/template>/i);
|
|
24391
24486
|
const content = templateMatch?.[1] ?? rawComp;
|
|
@@ -24404,9 +24499,9 @@ function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
|
|
|
24404
24499
|
styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || "", compPath);
|
|
24405
24500
|
}
|
|
24406
24501
|
const rewrittenContent = contentDoc.body.innerHTML || content;
|
|
24407
|
-
const indexPath =
|
|
24502
|
+
const indexPath = join14(projectDir, "index.html");
|
|
24408
24503
|
let headContent = "";
|
|
24409
|
-
if (
|
|
24504
|
+
if (existsSync11(indexPath)) {
|
|
24410
24505
|
const indexHtml = readFileSync10(indexPath, "utf-8");
|
|
24411
24506
|
const headMatch = indexHtml.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
|
|
24412
24507
|
headContent = headMatch?.[1] ?? "";
|
|
@@ -24443,7 +24538,7 @@ var init_subComposition = __esm({
|
|
|
24443
24538
|
});
|
|
24444
24539
|
|
|
24445
24540
|
// ../core/src/studio-api/routes/preview.ts
|
|
24446
|
-
import { existsSync as
|
|
24541
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, statSync as statSync2 } from "fs";
|
|
24447
24542
|
import { resolve as resolve10 } from "path";
|
|
24448
24543
|
function registerPreviewRoutes(api, adapter2) {
|
|
24449
24544
|
api.get("/projects/:id/preview", async (c2) => {
|
|
@@ -24453,7 +24548,7 @@ function registerPreviewRoutes(api, adapter2) {
|
|
|
24453
24548
|
let bundled = await adapter2.bundle(project.dir);
|
|
24454
24549
|
if (!bundled) {
|
|
24455
24550
|
const indexPath = resolve10(project.dir, "index.html");
|
|
24456
|
-
if (!
|
|
24551
|
+
if (!existsSync12(indexPath)) return c2.text("not found", 404);
|
|
24457
24552
|
bundled = readFileSync11(indexPath, "utf-8");
|
|
24458
24553
|
}
|
|
24459
24554
|
if (!bundled.includes("hyperframe.runtime") && !bundled.includes("hyperframes-preview-runtime")) {
|
|
@@ -24469,7 +24564,7 @@ ${runtimeTag}`;
|
|
|
24469
24564
|
return c2.html(bundled);
|
|
24470
24565
|
} catch {
|
|
24471
24566
|
const file = resolve10(project.dir, "index.html");
|
|
24472
|
-
if (
|
|
24567
|
+
if (existsSync12(file)) return c2.html(readFileSync11(file, "utf-8"));
|
|
24473
24568
|
return c2.text("not found", 404);
|
|
24474
24569
|
}
|
|
24475
24570
|
});
|
|
@@ -24480,7 +24575,7 @@ ${runtimeTag}`;
|
|
|
24480
24575
|
c2.req.path.replace(`/projects/${project.id}/preview/comp/`, "").split("?")[0] ?? ""
|
|
24481
24576
|
);
|
|
24482
24577
|
const compFile = resolve10(project.dir, compPath);
|
|
24483
|
-
if (!isSafePath(project.dir, compFile) || !
|
|
24578
|
+
if (!isSafePath(project.dir, compFile) || !existsSync12(compFile) || !statSync2(compFile).isFile()) {
|
|
24484
24579
|
return c2.text("not found", 404);
|
|
24485
24580
|
}
|
|
24486
24581
|
const baseHref = `/api/projects/${project.id}/preview/`;
|
|
@@ -24495,7 +24590,7 @@ ${runtimeTag}`;
|
|
|
24495
24590
|
c2.req.path.replace(`/projects/${project.id}/preview/`, "").split("?")[0] ?? ""
|
|
24496
24591
|
);
|
|
24497
24592
|
const file = resolve10(project.dir, subPath);
|
|
24498
|
-
if (!isSafePath(project.dir, file) || !
|
|
24593
|
+
if (!isSafePath(project.dir, file) || !existsSync12(file) || !statSync2(file).isFile()) {
|
|
24499
24594
|
return c2.text("not found", 404);
|
|
24500
24595
|
}
|
|
24501
24596
|
const contentType = getMimeType(subPath);
|
|
@@ -24534,14 +24629,14 @@ var init_preview = __esm({
|
|
|
24534
24629
|
"../core/src/studio-api/routes/preview.ts"() {
|
|
24535
24630
|
"use strict";
|
|
24536
24631
|
init_safePath();
|
|
24537
|
-
|
|
24632
|
+
init_mime();
|
|
24538
24633
|
init_subComposition();
|
|
24539
24634
|
}
|
|
24540
24635
|
});
|
|
24541
24636
|
|
|
24542
24637
|
// ../core/src/studio-api/routes/lint.ts
|
|
24543
24638
|
import { readFileSync as readFileSync12 } from "fs";
|
|
24544
|
-
import { join as
|
|
24639
|
+
import { join as join15 } from "path";
|
|
24545
24640
|
function registerLintRoutes(api, adapter2) {
|
|
24546
24641
|
api.get("/projects/:id/lint", async (c2) => {
|
|
24547
24642
|
const project = await adapter2.resolveProject(c2.req.param("id"));
|
|
@@ -24550,7 +24645,7 @@ function registerLintRoutes(api, adapter2) {
|
|
|
24550
24645
|
const htmlFiles = walkDir(project.dir).filter((f3) => f3.endsWith(".html"));
|
|
24551
24646
|
const allFindings = [];
|
|
24552
24647
|
for (const file of htmlFiles) {
|
|
24553
|
-
const content = readFileSync12(
|
|
24648
|
+
const content = readFileSync12(join15(project.dir, file), "utf-8");
|
|
24554
24649
|
const result = await adapter2.lint(content, { filePath: file });
|
|
24555
24650
|
if (result?.findings) {
|
|
24556
24651
|
for (const f3 of result.findings) {
|
|
@@ -24574,8 +24669,8 @@ var init_lint2 = __esm({
|
|
|
24574
24669
|
|
|
24575
24670
|
// ../core/src/studio-api/routes/render.ts
|
|
24576
24671
|
import { streamSSE } from "hono/streaming";
|
|
24577
|
-
import { existsSync as
|
|
24578
|
-
import { join as
|
|
24672
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
24673
|
+
import { join as join16 } from "path";
|
|
24579
24674
|
function registerRenderRoutes(api, adapter2) {
|
|
24580
24675
|
const renderJobs = /* @__PURE__ */ new Map();
|
|
24581
24676
|
const TTL_MS = 3e5;
|
|
@@ -24612,9 +24707,9 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24612
24707
|
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
|
24613
24708
|
const jobId = `${project.id}_${datePart}_${timePart}`;
|
|
24614
24709
|
const rendersDir = adapter2.rendersDir(project);
|
|
24615
|
-
if (!
|
|
24710
|
+
if (!existsSync13(rendersDir)) mkdirSync7(rendersDir, { recursive: true });
|
|
24616
24711
|
const ext = FORMAT_EXT2[format] ?? ".mp4";
|
|
24617
|
-
const outputPath =
|
|
24712
|
+
const outputPath = join16(rendersDir, `${jobId}${ext}`);
|
|
24618
24713
|
const jobState = adapter2.startRender({
|
|
24619
24714
|
project,
|
|
24620
24715
|
outputPath,
|
|
@@ -24679,7 +24774,7 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24679
24774
|
api.get("/render/:jobId/view", (c2) => {
|
|
24680
24775
|
const { jobId } = c2.req.param();
|
|
24681
24776
|
const job = renderJobs.get(jobId);
|
|
24682
|
-
if (!job?.outputPath || !
|
|
24777
|
+
if (!job?.outputPath || !existsSync13(job.outputPath)) {
|
|
24683
24778
|
return c2.json({ error: "not found" }, 404);
|
|
24684
24779
|
}
|
|
24685
24780
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -24697,7 +24792,7 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24697
24792
|
api.get("/render/:jobId/download", (c2) => {
|
|
24698
24793
|
const { jobId } = c2.req.param();
|
|
24699
24794
|
const job = renderJobs.get(jobId);
|
|
24700
|
-
if (!job?.outputPath || !
|
|
24795
|
+
if (!job?.outputPath || !existsSync13(job.outputPath)) {
|
|
24701
24796
|
return c2.json({ error: "not found" }, 404);
|
|
24702
24797
|
}
|
|
24703
24798
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -24716,8 +24811,8 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24716
24811
|
if (state.id === jobId && state.outputPath) {
|
|
24717
24812
|
const dir = state.outputPath.replace(/\/[^/]+$/, "");
|
|
24718
24813
|
for (const ext of [".mp4", ".webm", ".mov", ".meta.json"]) {
|
|
24719
|
-
const fp =
|
|
24720
|
-
if (
|
|
24814
|
+
const fp = join16(dir, `${jobId}${ext}`);
|
|
24815
|
+
if (existsSync13(fp)) unlinkSync4(fp);
|
|
24721
24816
|
}
|
|
24722
24817
|
break;
|
|
24723
24818
|
}
|
|
@@ -24731,8 +24826,8 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24731
24826
|
const filename = c2.req.path.split("/renders/file/")[1];
|
|
24732
24827
|
if (!filename) return c2.json({ error: "missing filename" }, 400);
|
|
24733
24828
|
const rendersDir = adapter2.rendersDir(project);
|
|
24734
|
-
const fp =
|
|
24735
|
-
if (!
|
|
24829
|
+
const fp = join16(rendersDir, filename);
|
|
24830
|
+
if (!existsSync13(fp)) return c2.json({ error: "not found" }, 404);
|
|
24736
24831
|
const contentType = renderContentType(fp);
|
|
24737
24832
|
const content = readFileSync13(fp);
|
|
24738
24833
|
return new Response(content, {
|
|
@@ -24748,15 +24843,15 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24748
24843
|
const project = await adapter2.resolveProject(c2.req.param("id"));
|
|
24749
24844
|
if (!project) return c2.json({ error: "not found" }, 404);
|
|
24750
24845
|
const rendersDir = adapter2.rendersDir(project);
|
|
24751
|
-
if (!
|
|
24846
|
+
if (!existsSync13(rendersDir)) return c2.json({ renders: [] });
|
|
24752
24847
|
const files = readdirSync5(rendersDir).filter((f3) => f3.endsWith(".mp4") || f3.endsWith(".webm") || f3.endsWith(".mov")).map((f3) => {
|
|
24753
|
-
const fp =
|
|
24848
|
+
const fp = join16(rendersDir, f3);
|
|
24754
24849
|
const stat3 = statSync3(fp);
|
|
24755
24850
|
const rid = f3.replace(/\.(mp4|webm|mov)$/, "");
|
|
24756
|
-
const metaPath =
|
|
24851
|
+
const metaPath = join16(rendersDir, `${rid}.meta.json`);
|
|
24757
24852
|
let status = "complete";
|
|
24758
24853
|
let durationMs;
|
|
24759
|
-
if (
|
|
24854
|
+
if (existsSync13(metaPath)) {
|
|
24760
24855
|
try {
|
|
24761
24856
|
const meta = JSON.parse(readFileSync13(metaPath, "utf-8"));
|
|
24762
24857
|
if (meta.status === "failed") status = "failed";
|
|
@@ -24779,7 +24874,7 @@ function registerRenderRoutes(api, adapter2) {
|
|
|
24779
24874
|
id: file.id,
|
|
24780
24875
|
status: file.status,
|
|
24781
24876
|
progress: 100,
|
|
24782
|
-
outputPath:
|
|
24877
|
+
outputPath: join16(rendersDir, file.filename),
|
|
24783
24878
|
createdAt: file.createdAt
|
|
24784
24879
|
});
|
|
24785
24880
|
}
|
|
@@ -24794,8 +24889,8 @@ var init_render = __esm({
|
|
|
24794
24889
|
});
|
|
24795
24890
|
|
|
24796
24891
|
// ../core/src/studio-api/routes/thumbnail.ts
|
|
24797
|
-
import { existsSync as
|
|
24798
|
-
import { join as
|
|
24892
|
+
import { existsSync as existsSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
|
|
24893
|
+
import { join as join17 } from "path";
|
|
24799
24894
|
function registerThumbnailRoutes(api, adapter2) {
|
|
24800
24895
|
api.get("/projects/:id/thumbnail/*", async (c2) => {
|
|
24801
24896
|
if (!adapter2.generateThumbnail) {
|
|
@@ -24815,8 +24910,8 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
24815
24910
|
let compW = vpWidth || 1920;
|
|
24816
24911
|
let compH = vpHeight || 1080;
|
|
24817
24912
|
if (!vpWidth) {
|
|
24818
|
-
const htmlFile =
|
|
24819
|
-
if (
|
|
24913
|
+
const htmlFile = join17(project.dir, compPath);
|
|
24914
|
+
if (existsSync14(htmlFile)) {
|
|
24820
24915
|
const html = readFileSync14(htmlFile, "utf-8");
|
|
24821
24916
|
const wMatch = html.match(/data-width=["'](\d+)["']/);
|
|
24822
24917
|
const hMatch = html.match(/data-height=["'](\d+)["']/);
|
|
@@ -24825,11 +24920,11 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
24825
24920
|
}
|
|
24826
24921
|
}
|
|
24827
24922
|
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}`;
|
|
24828
|
-
const cacheDir =
|
|
24923
|
+
const cacheDir = join17(project.dir, ".thumbnails");
|
|
24829
24924
|
const selectorKey = selector ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 80)}` : "";
|
|
24830
24925
|
const cacheKey = `${THUMBNAIL_CACHE_VERSION}_${compPath.replace(/\//g, "_")}_${seekTime.toFixed(2)}${selectorKey}.jpg`;
|
|
24831
|
-
const cachePath2 =
|
|
24832
|
-
if (
|
|
24926
|
+
const cachePath2 = join17(cacheDir, cacheKey);
|
|
24927
|
+
if (existsSync14(cachePath2)) {
|
|
24833
24928
|
return new Response(new Uint8Array(readFileSync14(cachePath2)), {
|
|
24834
24929
|
headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
|
|
24835
24930
|
});
|
|
@@ -24847,8 +24942,8 @@ function registerThumbnailRoutes(api, adapter2) {
|
|
|
24847
24942
|
if (!buffer) {
|
|
24848
24943
|
return c2.json({ error: "Thumbnail generation returned null" }, 500);
|
|
24849
24944
|
}
|
|
24850
|
-
if (!
|
|
24851
|
-
|
|
24945
|
+
if (!existsSync14(cacheDir)) mkdirSync8(cacheDir, { recursive: true });
|
|
24946
|
+
writeFileSync8(cachePath2, buffer);
|
|
24852
24947
|
return new Response(new Uint8Array(buffer), {
|
|
24853
24948
|
headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
|
|
24854
24949
|
});
|
|
@@ -24866,6 +24961,50 @@ var init_thumbnail = __esm({
|
|
|
24866
24961
|
}
|
|
24867
24962
|
});
|
|
24868
24963
|
|
|
24964
|
+
// ../core/src/studio-api/routes/waveform.ts
|
|
24965
|
+
import { existsSync as existsSync15, readFileSync as readFileSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "fs";
|
|
24966
|
+
import { join as join18 } from "path";
|
|
24967
|
+
function registerWaveformRoutes(api, adapter2) {
|
|
24968
|
+
api.get("/projects/:id/waveform/*", async (c2) => {
|
|
24969
|
+
const project = await adapter2.resolveProject(c2.req.param("id"));
|
|
24970
|
+
if (!project) return c2.json({ error: "not found" }, 404);
|
|
24971
|
+
const assetPath = decodeURIComponent(
|
|
24972
|
+
c2.req.path.replace(`/projects/${project.id}/waveform/`, "").split("?")[0] ?? ""
|
|
24973
|
+
);
|
|
24974
|
+
const audioPath = join18(project.dir, assetPath);
|
|
24975
|
+
if (!existsSync15(audioPath)) return c2.json({ error: "file not found" }, 404);
|
|
24976
|
+
const cacheDir = join18(project.dir, ".waveform-cache");
|
|
24977
|
+
const cachePath2 = join18(cacheDir, buildWaveformCacheKey(assetPath));
|
|
24978
|
+
if (existsSync15(cachePath2)) {
|
|
24979
|
+
try {
|
|
24980
|
+
const peaks2 = JSON.parse(readFileSync15(cachePath2, "utf-8"));
|
|
24981
|
+
return c2.json({ peaks: peaks2 });
|
|
24982
|
+
} catch {
|
|
24983
|
+
}
|
|
24984
|
+
}
|
|
24985
|
+
let peaks;
|
|
24986
|
+
try {
|
|
24987
|
+
peaks = await decodeAudioPeaks(audioPath);
|
|
24988
|
+
} catch {
|
|
24989
|
+
return c2.json({ error: "failed to decode audio" }, 500);
|
|
24990
|
+
}
|
|
24991
|
+
try {
|
|
24992
|
+
mkdirSync9(cacheDir, { recursive: true });
|
|
24993
|
+
writeFileSync9(cachePath2, JSON.stringify(peaks));
|
|
24994
|
+
} catch {
|
|
24995
|
+
}
|
|
24996
|
+
return c2.json({ peaks });
|
|
24997
|
+
});
|
|
24998
|
+
}
|
|
24999
|
+
var init_waveform2 = __esm({
|
|
25000
|
+
"../core/src/studio-api/routes/waveform.ts"() {
|
|
25001
|
+
"use strict";
|
|
25002
|
+
init_waveform();
|
|
25003
|
+
init_mime();
|
|
25004
|
+
init_waveform();
|
|
25005
|
+
}
|
|
25006
|
+
});
|
|
25007
|
+
|
|
24869
25008
|
// ../core/src/studio-api/createStudioApi.ts
|
|
24870
25009
|
import { Hono } from "hono";
|
|
24871
25010
|
function createStudioApi(adapter2) {
|
|
@@ -24876,6 +25015,7 @@ function createStudioApi(adapter2) {
|
|
|
24876
25015
|
registerLintRoutes(api, adapter2);
|
|
24877
25016
|
registerRenderRoutes(api, adapter2);
|
|
24878
25017
|
registerThumbnailRoutes(api, adapter2);
|
|
25018
|
+
registerWaveformRoutes(api, adapter2);
|
|
24879
25019
|
return api;
|
|
24880
25020
|
}
|
|
24881
25021
|
var init_createStudioApi = __esm({
|
|
@@ -24887,6 +25027,7 @@ var init_createStudioApi = __esm({
|
|
|
24887
25027
|
init_lint2();
|
|
24888
25028
|
init_render();
|
|
24889
25029
|
init_thumbnail();
|
|
25030
|
+
init_waveform2();
|
|
24890
25031
|
}
|
|
24891
25032
|
});
|
|
24892
25033
|
|
|
@@ -24905,7 +25046,7 @@ var init_studio_api = __esm({
|
|
|
24905
25046
|
"use strict";
|
|
24906
25047
|
init_createStudioApi();
|
|
24907
25048
|
init_safePath();
|
|
24908
|
-
|
|
25049
|
+
init_mime();
|
|
24909
25050
|
init_subComposition();
|
|
24910
25051
|
}
|
|
24911
25052
|
});
|
|
@@ -24921,9 +25062,9 @@ __export(manager_exports2, {
|
|
|
24921
25062
|
setBrowserPath: () => setBrowserPath
|
|
24922
25063
|
});
|
|
24923
25064
|
import { execSync } from "child_process";
|
|
24924
|
-
import { existsSync as
|
|
25065
|
+
import { existsSync as existsSync16, rmSync as rmSync4 } from "fs";
|
|
24925
25066
|
import { homedir as homedir4 } from "os";
|
|
24926
|
-
import { join as
|
|
25067
|
+
import { join as join19 } from "path";
|
|
24927
25068
|
import { Browser, detectBrowserPlatform, getInstalledBrowsers, install } from "@puppeteer/browsers";
|
|
24928
25069
|
function setBrowserPath(path2) {
|
|
24929
25070
|
_browserPathOverride = path2;
|
|
@@ -24943,17 +25084,17 @@ function whichBinary2(name) {
|
|
|
24943
25084
|
}
|
|
24944
25085
|
}
|
|
24945
25086
|
function findFromEnv2() {
|
|
24946
|
-
if (_browserPathOverride &&
|
|
25087
|
+
if (_browserPathOverride && existsSync16(_browserPathOverride)) {
|
|
24947
25088
|
return { executablePath: _browserPathOverride, source: "env" };
|
|
24948
25089
|
}
|
|
24949
25090
|
const envPath = process.env["HYPERFRAMES_BROWSER_PATH"];
|
|
24950
|
-
if (envPath &&
|
|
25091
|
+
if (envPath && existsSync16(envPath)) {
|
|
24951
25092
|
return { executablePath: envPath, source: "env" };
|
|
24952
25093
|
}
|
|
24953
25094
|
return void 0;
|
|
24954
25095
|
}
|
|
24955
25096
|
async function findFromCache() {
|
|
24956
|
-
if (!
|
|
25097
|
+
if (!existsSync16(CACHE_DIR2)) {
|
|
24957
25098
|
return void 0;
|
|
24958
25099
|
}
|
|
24959
25100
|
const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
|
|
@@ -24965,7 +25106,7 @@ async function findFromCache() {
|
|
|
24965
25106
|
}
|
|
24966
25107
|
function findFromSystem2() {
|
|
24967
25108
|
for (const p of SYSTEM_CHROME_PATHS) {
|
|
24968
|
-
if (
|
|
25109
|
+
if (existsSync16(p)) {
|
|
24969
25110
|
return { executablePath: p, source: "system" };
|
|
24970
25111
|
}
|
|
24971
25112
|
}
|
|
@@ -24999,7 +25140,7 @@ async function ensureBrowser(options) {
|
|
|
24999
25140
|
return { executablePath: installed.executablePath, source: "download" };
|
|
25000
25141
|
}
|
|
25001
25142
|
function clearBrowser() {
|
|
25002
|
-
if (!
|
|
25143
|
+
if (!existsSync16(CACHE_DIR2)) {
|
|
25003
25144
|
return false;
|
|
25004
25145
|
}
|
|
25005
25146
|
rmSync4(CACHE_DIR2, { recursive: true, force: true });
|
|
@@ -25010,7 +25151,7 @@ var init_manager2 = __esm({
|
|
|
25010
25151
|
"src/browser/manager.ts"() {
|
|
25011
25152
|
"use strict";
|
|
25012
25153
|
CHROME_VERSION = "131.0.6778.85";
|
|
25013
|
-
CACHE_DIR2 =
|
|
25154
|
+
CACHE_DIR2 = join19(homedir4(), ".cache", "hyperframes", "chrome");
|
|
25014
25155
|
SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : [
|
|
25015
25156
|
"/usr/bin/google-chrome",
|
|
25016
25157
|
"/usr/bin/google-chrome-stable",
|
|
@@ -25137,8 +25278,8 @@ var init_config2 = __esm({
|
|
|
25137
25278
|
});
|
|
25138
25279
|
|
|
25139
25280
|
// ../engine/src/services/browserManager.ts
|
|
25140
|
-
import { existsSync as
|
|
25141
|
-
import { join as
|
|
25281
|
+
import { existsSync as existsSync17, readdirSync as readdirSync6 } from "fs";
|
|
25282
|
+
import { join as join20 } from "path";
|
|
25142
25283
|
import { homedir as homedir5 } from "os";
|
|
25143
25284
|
async function getPuppeteer() {
|
|
25144
25285
|
if (_puppeteer) return _puppeteer;
|
|
@@ -25159,19 +25300,19 @@ function resolveHeadlessShellPath(config) {
|
|
|
25159
25300
|
if (process.env.PRODUCER_HEADLESS_SHELL_PATH) {
|
|
25160
25301
|
return process.env.PRODUCER_HEADLESS_SHELL_PATH;
|
|
25161
25302
|
}
|
|
25162
|
-
const baseDir =
|
|
25163
|
-
if (!
|
|
25303
|
+
const baseDir = join20(homedir5(), ".cache", "puppeteer", "chrome-headless-shell");
|
|
25304
|
+
if (!existsSync17(baseDir)) return void 0;
|
|
25164
25305
|
try {
|
|
25165
25306
|
const versions = readdirSync6(baseDir).sort().reverse();
|
|
25166
25307
|
for (const version of versions) {
|
|
25167
25308
|
const candidates = [
|
|
25168
|
-
|
|
25169
|
-
|
|
25170
|
-
|
|
25171
|
-
|
|
25309
|
+
join20(baseDir, version, "chrome-headless-shell-linux64", "chrome-headless-shell"),
|
|
25310
|
+
join20(baseDir, version, "chrome-headless-shell-mac-arm64", "chrome-headless-shell"),
|
|
25311
|
+
join20(baseDir, version, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
|
|
25312
|
+
join20(baseDir, version, "chrome-headless-shell-win64", "chrome-headless-shell.exe")
|
|
25172
25313
|
];
|
|
25173
25314
|
for (const binary of candidates) {
|
|
25174
|
-
if (
|
|
25315
|
+
if (existsSync17(binary)) return binary;
|
|
25175
25316
|
}
|
|
25176
25317
|
}
|
|
25177
25318
|
} catch {
|
|
@@ -25634,10 +25775,10 @@ var init_screenshotService = __esm({
|
|
|
25634
25775
|
});
|
|
25635
25776
|
|
|
25636
25777
|
// ../engine/src/services/frameCapture.ts
|
|
25637
|
-
import { existsSync as
|
|
25638
|
-
import { join as
|
|
25778
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
25779
|
+
import { join as join21 } from "path";
|
|
25639
25780
|
async function createCaptureSession(serverUrl, outputDir, options, onBeforeCapture = null, config) {
|
|
25640
|
-
if (!
|
|
25781
|
+
if (!existsSync18(outputDir)) mkdirSync10(outputDir, { recursive: true });
|
|
25641
25782
|
const headlessShell = resolveHeadlessShellPath(config);
|
|
25642
25783
|
const isLinux = process.platform === "linux";
|
|
25643
25784
|
const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG2.forceScreenshot;
|
|
@@ -25841,13 +25982,13 @@ async function initializeSession(session) {
|
|
|
25841
25982
|
}
|
|
25842
25983
|
async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
|
|
25843
25984
|
try {
|
|
25844
|
-
const diagnosticsDir =
|
|
25845
|
-
if (!
|
|
25846
|
-
const base =
|
|
25985
|
+
const diagnosticsDir = join21(session.outputDir, "diagnostics");
|
|
25986
|
+
if (!existsSync18(diagnosticsDir)) mkdirSync10(diagnosticsDir, { recursive: true });
|
|
25987
|
+
const base = join21(diagnosticsDir, `frame-error-${frameIndex}`);
|
|
25847
25988
|
await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
|
|
25848
25989
|
const html = await session.page.content();
|
|
25849
|
-
|
|
25850
|
-
|
|
25990
|
+
writeFileSync10(`${base}.html`, html, "utf-8");
|
|
25991
|
+
writeFileSync10(
|
|
25851
25992
|
`${base}.json`,
|
|
25852
25993
|
JSON.stringify(
|
|
25853
25994
|
{
|
|
@@ -25941,8 +26082,8 @@ async function captureFrame(session, frameIndex, time) {
|
|
|
25941
26082
|
);
|
|
25942
26083
|
const ext = options.format === "png" ? "png" : "jpg";
|
|
25943
26084
|
const frameName = `frame_${String(frameIndex).padStart(6, "0")}.${ext}`;
|
|
25944
|
-
const framePath =
|
|
25945
|
-
|
|
26085
|
+
const framePath = join21(outputDir, frameName);
|
|
26086
|
+
writeFileSync10(framePath, buffer);
|
|
25946
26087
|
return { frameIndex, time: quantizedTime, path: framePath, captureTimeMs };
|
|
25947
26088
|
}
|
|
25948
26089
|
async function captureFrameToBuffer(session, frameIndex, time) {
|
|
@@ -25962,8 +26103,8 @@ async function closeCaptureSession(session) {
|
|
|
25962
26103
|
session.isInitialized = false;
|
|
25963
26104
|
}
|
|
25964
26105
|
function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
|
|
25965
|
-
if (!
|
|
25966
|
-
|
|
26106
|
+
if (!existsSync18(outputDir)) {
|
|
26107
|
+
mkdirSync10(outputDir, { recursive: true });
|
|
25967
26108
|
}
|
|
25968
26109
|
session.outputDir = outputDir;
|
|
25969
26110
|
session.onBeforeCapture = onBeforeCapture;
|
|
@@ -26006,10 +26147,10 @@ var init_frameCapture = __esm({
|
|
|
26006
26147
|
});
|
|
26007
26148
|
|
|
26008
26149
|
// ../engine/src/utils/gpuEncoder.ts
|
|
26009
|
-
import { spawn as
|
|
26150
|
+
import { spawn as spawn3 } from "child_process";
|
|
26010
26151
|
async function detectGpuEncoder() {
|
|
26011
26152
|
return new Promise((resolve39) => {
|
|
26012
|
-
const ffmpeg =
|
|
26153
|
+
const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
|
|
26013
26154
|
stdio: ["pipe", "pipe", "pipe"]
|
|
26014
26155
|
});
|
|
26015
26156
|
let stdout2 = "";
|
|
@@ -26129,7 +26270,7 @@ var init_hdr = __esm({
|
|
|
26129
26270
|
});
|
|
26130
26271
|
|
|
26131
26272
|
// ../engine/src/utils/runFfmpeg.ts
|
|
26132
|
-
import { spawn as
|
|
26273
|
+
import { spawn as spawn4 } from "child_process";
|
|
26133
26274
|
function formatFfmpegError(exitCode, stderr, tailLines = DEFAULT_STDERR_TAIL_LINES) {
|
|
26134
26275
|
const tail = (stderr ?? "").split(/\r?\n/).filter((line) => line.length > 0).slice(-tailLines).join("\n");
|
|
26135
26276
|
if (exitCode === null) {
|
|
@@ -26145,7 +26286,7 @@ async function runFfmpeg(args, opts) {
|
|
|
26145
26286
|
const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
|
|
26146
26287
|
const onStderr = opts?.onStderr;
|
|
26147
26288
|
return new Promise((resolve39) => {
|
|
26148
|
-
const ffmpeg =
|
|
26289
|
+
const ffmpeg = spawn4("ffmpeg", args);
|
|
26149
26290
|
let stderr = "";
|
|
26150
26291
|
const onAbort = () => {
|
|
26151
26292
|
ffmpeg.kill("SIGTERM");
|
|
@@ -26199,9 +26340,9 @@ var init_runFfmpeg = __esm({
|
|
|
26199
26340
|
});
|
|
26200
26341
|
|
|
26201
26342
|
// ../engine/src/services/chunkEncoder.ts
|
|
26202
|
-
import { spawn as
|
|
26203
|
-
import { copyFileSync, existsSync as
|
|
26204
|
-
import { join as
|
|
26343
|
+
import { spawn as spawn5 } from "child_process";
|
|
26344
|
+
import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readdirSync as readdirSync7, statSync as statSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
26345
|
+
import { join as join22, dirname as dirname6 } from "path";
|
|
26205
26346
|
function getEncoderPreset(quality, format = "mp4", hdr) {
|
|
26206
26347
|
const base = ENCODER_PRESETS[quality];
|
|
26207
26348
|
if (format === "webm") {
|
|
@@ -26352,7 +26493,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
26352
26493
|
async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config) {
|
|
26353
26494
|
const startTime = Date.now();
|
|
26354
26495
|
const outputDir = dirname6(outputPath);
|
|
26355
|
-
if (!
|
|
26496
|
+
if (!existsSync19(outputDir)) mkdirSync11(outputDir, { recursive: true });
|
|
26356
26497
|
const files = readdirSync7(framesDir).filter((f3) => f3.match(/\.(jpg|jpeg|png)$/i));
|
|
26357
26498
|
const frameCount = files.length;
|
|
26358
26499
|
if (frameCount === 0) {
|
|
@@ -26369,11 +26510,11 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26369
26510
|
if (options.useGpu) {
|
|
26370
26511
|
gpuEncoder = await getCachedGpuEncoder();
|
|
26371
26512
|
}
|
|
26372
|
-
const inputPath =
|
|
26513
|
+
const inputPath = join22(framesDir, framePattern);
|
|
26373
26514
|
const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
|
|
26374
26515
|
const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
|
|
26375
26516
|
return new Promise((resolve39) => {
|
|
26376
|
-
const ffmpeg =
|
|
26517
|
+
const ffmpeg = spawn5("ffmpeg", args);
|
|
26377
26518
|
let stderr = "";
|
|
26378
26519
|
const onAbort = () => {
|
|
26379
26520
|
ffmpeg.kill("SIGTERM");
|
|
@@ -26418,7 +26559,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26418
26559
|
});
|
|
26419
26560
|
return;
|
|
26420
26561
|
}
|
|
26421
|
-
const fileSize =
|
|
26562
|
+
const fileSize = existsSync19(outputPath) ? statSync4(outputPath).size : 0;
|
|
26422
26563
|
resolve39({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
|
|
26423
26564
|
});
|
|
26424
26565
|
ffmpeg.on("error", (err) => {
|
|
@@ -26450,8 +26591,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26450
26591
|
}
|
|
26451
26592
|
const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
|
|
26452
26593
|
const chunkCount = Math.ceil(files.length / chunkSize);
|
|
26453
|
-
const chunkDir =
|
|
26454
|
-
if (!
|
|
26594
|
+
const chunkDir = join22(dirname6(outputPath), "chunk-encode");
|
|
26595
|
+
if (!existsSync19(chunkDir)) mkdirSync11(chunkDir, { recursive: true });
|
|
26455
26596
|
const chunkPaths = [];
|
|
26456
26597
|
for (let i2 = 0; i2 < chunkCount; i2++) {
|
|
26457
26598
|
if (signal?.aborted) {
|
|
@@ -26467,8 +26608,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26467
26608
|
const startNumber = i2 * chunkSize;
|
|
26468
26609
|
const framesInChunk = Math.min(chunkSize, files.length - startNumber);
|
|
26469
26610
|
const ext = outputPath.endsWith(".webm") ? ".webm" : outputPath.endsWith(".mov") ? ".mov" : ".mp4";
|
|
26470
|
-
const chunkPath =
|
|
26471
|
-
const inputPath =
|
|
26611
|
+
const chunkPath = join22(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
|
|
26612
|
+
const inputPath = join22(framesDir, framePattern);
|
|
26472
26613
|
const inputArgs = [
|
|
26473
26614
|
"-framerate",
|
|
26474
26615
|
String(options.fps),
|
|
@@ -26483,7 +26624,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26483
26624
|
if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
|
|
26484
26625
|
const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
|
|
26485
26626
|
const chunkResult = await new Promise((resolve39) => {
|
|
26486
|
-
const ffmpeg =
|
|
26627
|
+
const ffmpeg = spawn5("ffmpeg", args);
|
|
26487
26628
|
let stderr = "";
|
|
26488
26629
|
ffmpeg.stderr.on("data", (d) => {
|
|
26489
26630
|
stderr += d.toString();
|
|
@@ -26508,9 +26649,9 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26508
26649
|
}
|
|
26509
26650
|
chunkPaths.push(chunkPath);
|
|
26510
26651
|
}
|
|
26511
|
-
const concatListPath =
|
|
26652
|
+
const concatListPath = join22(chunkDir, "concat-list.txt");
|
|
26512
26653
|
const concatInput = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
|
|
26513
|
-
|
|
26654
|
+
writeFileSync11(concatListPath, concatInput, "utf-8");
|
|
26514
26655
|
const concatArgs = [
|
|
26515
26656
|
"-f",
|
|
26516
26657
|
"concat",
|
|
@@ -26524,7 +26665,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26524
26665
|
outputPath
|
|
26525
26666
|
];
|
|
26526
26667
|
const concatResult = await new Promise((resolve39) => {
|
|
26527
|
-
const ffmpeg =
|
|
26668
|
+
const ffmpeg = spawn5("ffmpeg", concatArgs);
|
|
26528
26669
|
let stderr = "";
|
|
26529
26670
|
ffmpeg.stderr.on("data", (d) => {
|
|
26530
26671
|
stderr += d.toString();
|
|
@@ -26547,7 +26688,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26547
26688
|
error: concatResult.error
|
|
26548
26689
|
};
|
|
26549
26690
|
}
|
|
26550
|
-
const fileSize =
|
|
26691
|
+
const fileSize = existsSync19(outputPath) ? statSync4(outputPath).size : 0;
|
|
26551
26692
|
return {
|
|
26552
26693
|
success: true,
|
|
26553
26694
|
outputPath,
|
|
@@ -26558,7 +26699,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26558
26699
|
}
|
|
26559
26700
|
async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config) {
|
|
26560
26701
|
const outputDir = dirname6(outputPath);
|
|
26561
|
-
if (!
|
|
26702
|
+
if (!existsSync19(outputDir)) mkdirSync11(outputDir, { recursive: true });
|
|
26562
26703
|
const isWebm = outputPath.endsWith(".webm");
|
|
26563
26704
|
const isMov = outputPath.endsWith(".mov");
|
|
26564
26705
|
const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
|
|
@@ -26628,8 +26769,8 @@ var init_chunkEncoder = __esm({
|
|
|
26628
26769
|
});
|
|
26629
26770
|
|
|
26630
26771
|
// ../engine/src/services/streamingEncoder.ts
|
|
26631
|
-
import { spawn as
|
|
26632
|
-
import { existsSync as
|
|
26772
|
+
import { spawn as spawn6 } from "child_process";
|
|
26773
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync12, statSync as statSync5 } from "fs";
|
|
26633
26774
|
import { dirname as dirname7 } from "path";
|
|
26634
26775
|
function createFrameReorderBuffer(startFrame, endFrame) {
|
|
26635
26776
|
let cursor = startFrame;
|
|
@@ -26812,14 +26953,14 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
26812
26953
|
}
|
|
26813
26954
|
async function spawnStreamingEncoder(outputPath, options, signal, config) {
|
|
26814
26955
|
const outputDir = dirname7(outputPath);
|
|
26815
|
-
if (!
|
|
26956
|
+
if (!existsSync20(outputDir)) mkdirSync12(outputDir, { recursive: true });
|
|
26816
26957
|
let gpuEncoder = null;
|
|
26817
26958
|
if (options.useGpu) {
|
|
26818
26959
|
gpuEncoder = await getCachedGpuEncoder();
|
|
26819
26960
|
}
|
|
26820
26961
|
const args = buildStreamingArgs(options, outputPath, gpuEncoder);
|
|
26821
26962
|
const startTime = Date.now();
|
|
26822
|
-
const ffmpeg =
|
|
26963
|
+
const ffmpeg = spawn6("ffmpeg", args, {
|
|
26823
26964
|
stdio: ["pipe", "pipe", "pipe"]
|
|
26824
26965
|
});
|
|
26825
26966
|
let exitStatus = "running";
|
|
@@ -26894,7 +27035,7 @@ Process error: ${err.message}`;
|
|
|
26894
27035
|
error: formatFfmpegError(exitCode, stderr)
|
|
26895
27036
|
};
|
|
26896
27037
|
}
|
|
26897
|
-
const fileSize =
|
|
27038
|
+
const fileSize = existsSync20(outputPath) ? statSync5(outputPath).size : 0;
|
|
26898
27039
|
return { success: true, durationMs, fileSize };
|
|
26899
27040
|
},
|
|
26900
27041
|
getExitStatus: () => exitStatus
|
|
@@ -26912,12 +27053,12 @@ var init_streamingEncoder = __esm({
|
|
|
26912
27053
|
});
|
|
26913
27054
|
|
|
26914
27055
|
// ../engine/src/utils/ffprobe.ts
|
|
26915
|
-
import { spawn as
|
|
26916
|
-
import { readFileSync as
|
|
27056
|
+
import { spawn as spawn7 } from "child_process";
|
|
27057
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
26917
27058
|
import { extname as extname4 } from "path";
|
|
26918
27059
|
function runFfprobe(args) {
|
|
26919
27060
|
return new Promise((resolve39, reject) => {
|
|
26920
|
-
const proc =
|
|
27061
|
+
const proc = spawn7("ffprobe", args);
|
|
26921
27062
|
let stdout2 = "";
|
|
26922
27063
|
let stderr = "";
|
|
26923
27064
|
proc.stdout.on("data", (data) => {
|
|
@@ -27007,7 +27148,7 @@ function extractPngMetadataFromBuffer(buf) {
|
|
|
27007
27148
|
function extractStillImageMetadata(filePath) {
|
|
27008
27149
|
if (extname4(filePath).toLowerCase() !== ".png") return null;
|
|
27009
27150
|
try {
|
|
27010
|
-
return extractPngMetadataFromBuffer(
|
|
27151
|
+
return extractPngMetadataFromBuffer(readFileSync16(filePath));
|
|
27011
27152
|
} catch {
|
|
27012
27153
|
return null;
|
|
27013
27154
|
}
|
|
@@ -27186,9 +27327,9 @@ var init_ffprobe = __esm({
|
|
|
27186
27327
|
});
|
|
27187
27328
|
|
|
27188
27329
|
// ../engine/src/utils/urlDownloader.ts
|
|
27189
|
-
import { createWriteStream as createWriteStream2, existsSync as
|
|
27330
|
+
import { createWriteStream as createWriteStream2, existsSync as existsSync21, mkdirSync as mkdirSync13 } from "fs";
|
|
27190
27331
|
import { createHash } from "crypto";
|
|
27191
|
-
import { join as
|
|
27332
|
+
import { join as join23, extname as extname5 } from "path";
|
|
27192
27333
|
import { Readable } from "stream";
|
|
27193
27334
|
import { finished } from "stream/promises";
|
|
27194
27335
|
function getFilenameFromUrl(url) {
|
|
@@ -27199,19 +27340,19 @@ function getFilenameFromUrl(url) {
|
|
|
27199
27340
|
}
|
|
27200
27341
|
async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
|
|
27201
27342
|
const cachedPath = downloadPathCache.get(url);
|
|
27202
|
-
if (cachedPath &&
|
|
27343
|
+
if (cachedPath && existsSync21(cachedPath)) {
|
|
27203
27344
|
return cachedPath;
|
|
27204
27345
|
}
|
|
27205
27346
|
const inFlight = inFlightDownloads.get(url);
|
|
27206
27347
|
if (inFlight) {
|
|
27207
27348
|
return inFlight;
|
|
27208
27349
|
}
|
|
27209
|
-
if (!
|
|
27210
|
-
|
|
27350
|
+
if (!existsSync21(destDir)) {
|
|
27351
|
+
mkdirSync13(destDir, { recursive: true });
|
|
27211
27352
|
}
|
|
27212
27353
|
const filename = getFilenameFromUrl(url);
|
|
27213
|
-
const localPath =
|
|
27214
|
-
if (
|
|
27354
|
+
const localPath = join23(destDir, filename);
|
|
27355
|
+
if (existsSync21(localPath)) {
|
|
27215
27356
|
downloadPathCache.set(url, localPath);
|
|
27216
27357
|
return localPath;
|
|
27217
27358
|
}
|
|
@@ -27303,9 +27444,9 @@ var init_htmlTemplate = __esm({
|
|
|
27303
27444
|
|
|
27304
27445
|
// ../engine/src/services/extractionCache.ts
|
|
27305
27446
|
import { createHash as createHash2 } from "crypto";
|
|
27306
|
-
import { mkdirSync as
|
|
27307
|
-
import { existsSync as
|
|
27308
|
-
import { join as
|
|
27447
|
+
import { mkdirSync as mkdirSync14, readdirSync as readdirSync8, statSync as statSync6, writeFileSync as writeFileSync12 } from "fs";
|
|
27448
|
+
import { existsSync as existsSync22 } from "fs";
|
|
27449
|
+
import { join as join24 } from "path";
|
|
27309
27450
|
function readKeyStat(videoPath) {
|
|
27310
27451
|
try {
|
|
27311
27452
|
const stat3 = statSync6(videoPath);
|
|
@@ -27334,15 +27475,15 @@ function cacheEntryDirName(keyHash) {
|
|
|
27334
27475
|
}
|
|
27335
27476
|
function lookupCacheEntry(rootDir, input) {
|
|
27336
27477
|
const keyHash = computeCacheKey(input);
|
|
27337
|
-
const dir =
|
|
27338
|
-
const complete =
|
|
27478
|
+
const dir = join24(rootDir, cacheEntryDirName(keyHash));
|
|
27479
|
+
const complete = existsSync22(join24(dir, COMPLETE_SENTINEL));
|
|
27339
27480
|
return { entry: { dir, keyHash }, hit: complete };
|
|
27340
27481
|
}
|
|
27341
27482
|
function ensureCacheEntryDir(entry) {
|
|
27342
|
-
|
|
27483
|
+
mkdirSync14(entry.dir, { recursive: true });
|
|
27343
27484
|
}
|
|
27344
27485
|
function markCacheEntryComplete(entry) {
|
|
27345
|
-
|
|
27486
|
+
writeFileSync12(join24(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
|
|
27346
27487
|
}
|
|
27347
27488
|
function rehydrateCacheEntry(entry, options) {
|
|
27348
27489
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
|
|
@@ -27350,7 +27491,7 @@ function rehydrateCacheEntry(entry, options) {
|
|
|
27350
27491
|
const suffix = `.${options.format}`;
|
|
27351
27492
|
const files = readdirSync8(entry.dir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(suffix)).sort();
|
|
27352
27493
|
files.forEach((file, idx) => {
|
|
27353
|
-
framePaths.set(idx,
|
|
27494
|
+
framePaths.set(idx, join24(entry.dir, file));
|
|
27354
27495
|
});
|
|
27355
27496
|
return {
|
|
27356
27497
|
videoId: options.videoId,
|
|
@@ -27375,9 +27516,9 @@ var init_extractionCache = __esm({
|
|
|
27375
27516
|
});
|
|
27376
27517
|
|
|
27377
27518
|
// ../engine/src/services/videoFrameExtractor.ts
|
|
27378
|
-
import { spawn as
|
|
27379
|
-
import { existsSync as
|
|
27380
|
-
import { isAbsolute as isAbsolute2, join as
|
|
27519
|
+
import { spawn as spawn8 } from "child_process";
|
|
27520
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readdirSync as readdirSync9, rmSync as rmSync5 } from "fs";
|
|
27521
|
+
import { isAbsolute as isAbsolute2, join as join25 } from "path";
|
|
27381
27522
|
function parseVideoElements(html) {
|
|
27382
27523
|
const videos = [];
|
|
27383
27524
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
@@ -27447,12 +27588,12 @@ function parseImageElements(html) {
|
|
|
27447
27588
|
async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config, outputDirOverride) {
|
|
27448
27589
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
27449
27590
|
const { fps, outputDir, quality = 95 } = options;
|
|
27450
|
-
const videoOutputDir = outputDirOverride ??
|
|
27451
|
-
if (!
|
|
27591
|
+
const videoOutputDir = outputDirOverride ?? join25(outputDir, videoId);
|
|
27592
|
+
if (!existsSync23(videoOutputDir)) mkdirSync15(videoOutputDir, { recursive: true });
|
|
27452
27593
|
const metadata = await extractMediaMetadata(videoPath);
|
|
27453
27594
|
const format = resolveFrameFormat(metadata, options.format);
|
|
27454
27595
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
|
|
27455
|
-
const outputPattern =
|
|
27596
|
+
const outputPattern = join25(videoOutputDir, framePattern);
|
|
27456
27597
|
const isHdr = isHdrColorSpace(metadata.colorSpace);
|
|
27457
27598
|
const isMacOS = process.platform === "darwin";
|
|
27458
27599
|
const args = [];
|
|
@@ -27473,7 +27614,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
27473
27614
|
if (format === "png") args.push("-compression_level", "6");
|
|
27474
27615
|
args.push("-y", outputPattern);
|
|
27475
27616
|
return new Promise((resolve39, reject) => {
|
|
27476
|
-
const ffmpeg =
|
|
27617
|
+
const ffmpeg = spawn8("ffmpeg", args);
|
|
27477
27618
|
let stderr = "";
|
|
27478
27619
|
const onAbort = () => {
|
|
27479
27620
|
ffmpeg.kill("SIGTERM");
|
|
@@ -27505,7 +27646,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
27505
27646
|
const framePaths = /* @__PURE__ */ new Map();
|
|
27506
27647
|
const files = readdirSync9(videoOutputDir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(`.${format}`)).sort();
|
|
27507
27648
|
files.forEach((file, index) => {
|
|
27508
|
-
framePaths.set(index,
|
|
27649
|
+
framePaths.set(index, join25(videoOutputDir, file));
|
|
27509
27650
|
});
|
|
27510
27651
|
resolve39({
|
|
27511
27652
|
videoId,
|
|
@@ -27632,15 +27773,15 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
27632
27773
|
try {
|
|
27633
27774
|
let videoPath = video.src;
|
|
27634
27775
|
if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
|
|
27635
|
-
const fromCompiled = compiledDir ?
|
|
27636
|
-
videoPath = fromCompiled &&
|
|
27776
|
+
const fromCompiled = compiledDir ? join25(compiledDir, videoPath) : null;
|
|
27777
|
+
videoPath = fromCompiled && existsSync23(fromCompiled) ? fromCompiled : join25(baseDir, videoPath);
|
|
27637
27778
|
}
|
|
27638
27779
|
if (isHttpUrl(videoPath)) {
|
|
27639
|
-
const downloadDir =
|
|
27640
|
-
|
|
27780
|
+
const downloadDir = join25(options.outputDir, "_downloads");
|
|
27781
|
+
mkdirSync15(downloadDir, { recursive: true });
|
|
27641
27782
|
videoPath = await downloadToTemp(videoPath, downloadDir);
|
|
27642
27783
|
}
|
|
27643
|
-
if (!
|
|
27784
|
+
if (!existsSync23(videoPath)) {
|
|
27644
27785
|
errors.push({ videoId: video.id, error: `Video file not found: ${videoPath}` });
|
|
27645
27786
|
continue;
|
|
27646
27787
|
}
|
|
@@ -27673,8 +27814,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
27673
27814
|
const hdrSkippedIndices = /* @__PURE__ */ new Set();
|
|
27674
27815
|
if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
|
|
27675
27816
|
const targetTransfer = hdrInfo.dominantTransfer;
|
|
27676
|
-
const convertDir =
|
|
27677
|
-
|
|
27817
|
+
const convertDir = join25(options.outputDir, "_hdr_normalized");
|
|
27818
|
+
mkdirSync15(convertDir, { recursive: true });
|
|
27678
27819
|
for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
|
|
27679
27820
|
if (signal?.aborted) break;
|
|
27680
27821
|
const cs = videoColorSpaces[i2] ?? null;
|
|
@@ -27695,7 +27836,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
27695
27836
|
const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
|
|
27696
27837
|
segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
27697
27838
|
}
|
|
27698
|
-
const convertedPath =
|
|
27839
|
+
const convertedPath = join25(convertDir, `${entry.video.id}_hdr.mp4`);
|
|
27699
27840
|
try {
|
|
27700
27841
|
await convertSdrToHdr(
|
|
27701
27842
|
entry.videoPath,
|
|
@@ -27730,7 +27871,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
27730
27871
|
}
|
|
27731
27872
|
}
|
|
27732
27873
|
const vfrPreflightStart = Date.now();
|
|
27733
|
-
const vfrNormDir =
|
|
27874
|
+
const vfrNormDir = join25(options.outputDir, "_vfr_normalized");
|
|
27734
27875
|
for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
|
|
27735
27876
|
if (signal?.aborted) break;
|
|
27736
27877
|
const entry = resolvedVideos[i2];
|
|
@@ -27744,8 +27885,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
27744
27885
|
const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
|
|
27745
27886
|
segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
27746
27887
|
}
|
|
27747
|
-
|
|
27748
|
-
const normalizedPath =
|
|
27888
|
+
mkdirSync15(vfrNormDir, { recursive: true });
|
|
27889
|
+
const normalizedPath = join25(vfrNormDir, `${entry.video.id}_cfr.mp4`);
|
|
27749
27890
|
try {
|
|
27750
27891
|
await convertVfrToCfr(
|
|
27751
27892
|
entry.videoPath,
|
|
@@ -28001,7 +28142,7 @@ var init_videoFrameExtractor = __esm({
|
|
|
28001
28142
|
cleanup() {
|
|
28002
28143
|
for (const video of this.videos.values()) {
|
|
28003
28144
|
if (video.extracted.ownedByLookup) continue;
|
|
28004
|
-
if (
|
|
28145
|
+
if (existsSync23(video.extracted.outputDir)) {
|
|
28005
28146
|
rmSync5(video.extracted.outputDir, { recursive: true, force: true });
|
|
28006
28147
|
}
|
|
28007
28148
|
}
|
|
@@ -28309,8 +28450,8 @@ var init_videoFrameInjector = __esm({
|
|
|
28309
28450
|
});
|
|
28310
28451
|
|
|
28311
28452
|
// ../engine/src/services/audioMixer.ts
|
|
28312
|
-
import { existsSync as
|
|
28313
|
-
import { isAbsolute as isAbsolute3, join as
|
|
28453
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
|
|
28454
|
+
import { isAbsolute as isAbsolute3, join as join26, dirname as dirname8 } from "path";
|
|
28314
28455
|
function parseAudioElements(html) {
|
|
28315
28456
|
const elements = [];
|
|
28316
28457
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
@@ -28361,7 +28502,7 @@ function parseAudioElements(html) {
|
|
|
28361
28502
|
async function extractAudioFromVideo(videoPath, outputPath, options, signal, config) {
|
|
28362
28503
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28363
28504
|
const outputDir = dirname8(outputPath);
|
|
28364
|
-
if (!
|
|
28505
|
+
if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28365
28506
|
const args = ["-i", videoPath];
|
|
28366
28507
|
if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
|
|
28367
28508
|
if (options?.duration !== void 0) args.push("-t", String(options.duration));
|
|
@@ -28388,7 +28529,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
|
|
|
28388
28529
|
async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config) {
|
|
28389
28530
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28390
28531
|
const outputDir = dirname8(outputPath);
|
|
28391
|
-
if (!
|
|
28532
|
+
if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28392
28533
|
const args = [
|
|
28393
28534
|
"-ss",
|
|
28394
28535
|
String(mediaStart),
|
|
@@ -28424,7 +28565,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
|
|
|
28424
28565
|
async function generateSilence(outputPath, duration, signal, config) {
|
|
28425
28566
|
const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
|
|
28426
28567
|
const outputDir = dirname8(outputPath);
|
|
28427
|
-
if (!
|
|
28568
|
+
if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28428
28569
|
const args = [
|
|
28429
28570
|
"-f",
|
|
28430
28571
|
"lavfi",
|
|
@@ -28467,7 +28608,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
|
|
|
28467
28608
|
};
|
|
28468
28609
|
}
|
|
28469
28610
|
const outputDir = dirname8(outputPath);
|
|
28470
|
-
if (!
|
|
28611
|
+
if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
|
|
28471
28612
|
const inputs = [];
|
|
28472
28613
|
const filterParts = [];
|
|
28473
28614
|
tracks.forEach((track, i2) => {
|
|
@@ -28528,7 +28669,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28528
28669
|
const startMs = Date.now();
|
|
28529
28670
|
const tracks = [];
|
|
28530
28671
|
const errors = [];
|
|
28531
|
-
if (!
|
|
28672
|
+
if (!existsSync24(workDir)) mkdirSync16(workDir, { recursive: true });
|
|
28532
28673
|
await Promise.all(
|
|
28533
28674
|
elements.map(async (element) => {
|
|
28534
28675
|
if (signal?.aborted) {
|
|
@@ -28538,8 +28679,8 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28538
28679
|
try {
|
|
28539
28680
|
let srcPath = element.src;
|
|
28540
28681
|
if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
|
|
28541
|
-
const fromCompiled = compiledDir ?
|
|
28542
|
-
srcPath = fromCompiled &&
|
|
28682
|
+
const fromCompiled = compiledDir ? join26(compiledDir, srcPath) : null;
|
|
28683
|
+
srcPath = fromCompiled && existsSync24(fromCompiled) ? fromCompiled : join26(baseDir, srcPath);
|
|
28543
28684
|
}
|
|
28544
28685
|
if (isHttpUrl(srcPath)) {
|
|
28545
28686
|
try {
|
|
@@ -28551,7 +28692,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28551
28692
|
return;
|
|
28552
28693
|
}
|
|
28553
28694
|
}
|
|
28554
|
-
if (!
|
|
28695
|
+
if (!existsSync24(srcPath)) {
|
|
28555
28696
|
errors.push(`Source not found: ${element.id} (${element.src})`);
|
|
28556
28697
|
return;
|
|
28557
28698
|
}
|
|
@@ -28562,7 +28703,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28562
28703
|
}
|
|
28563
28704
|
let audioSrcPath = srcPath;
|
|
28564
28705
|
if (element.type === "video") {
|
|
28565
|
-
const extractedPath =
|
|
28706
|
+
const extractedPath = join26(workDir, `${element.id}-extracted.wav`);
|
|
28566
28707
|
const extractResult = await extractAudioFromVideo(
|
|
28567
28708
|
srcPath,
|
|
28568
28709
|
extractedPath,
|
|
@@ -28579,7 +28720,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
28579
28720
|
}
|
|
28580
28721
|
audioSrcPath = extractedPath;
|
|
28581
28722
|
} else {
|
|
28582
|
-
const trimmedPath =
|
|
28723
|
+
const trimmedPath = join26(workDir, `${element.id}-trimmed.wav`);
|
|
28583
28724
|
const prepResult = await prepareAudioTrack(
|
|
28584
28725
|
srcPath,
|
|
28585
28726
|
trimmedPath,
|
|
@@ -28633,9 +28774,9 @@ var init_audioMixer = __esm({
|
|
|
28633
28774
|
|
|
28634
28775
|
// ../engine/src/services/parallelCoordinator.ts
|
|
28635
28776
|
import { cpus as cpus2, freemem, totalmem as totalmem2 } from "os";
|
|
28636
|
-
import { existsSync as
|
|
28777
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync17, readdirSync as readdirSync10 } from "fs";
|
|
28637
28778
|
import { copyFile, rename } from "fs/promises";
|
|
28638
|
-
import { join as
|
|
28779
|
+
import { join as join27 } from "path";
|
|
28639
28780
|
function calculateOptimalWorkers(totalFrames, requested, config) {
|
|
28640
28781
|
const effectiveMaxWorkers = (() => {
|
|
28641
28782
|
const concurrency = config?.concurrency ?? DEFAULT_CONFIG2.concurrency;
|
|
@@ -28678,7 +28819,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
|
|
|
28678
28819
|
workerId: i2,
|
|
28679
28820
|
startFrame,
|
|
28680
28821
|
endFrame,
|
|
28681
|
-
outputDir:
|
|
28822
|
+
outputDir: join27(workDir, `worker-${i2}`)
|
|
28682
28823
|
});
|
|
28683
28824
|
}
|
|
28684
28825
|
return tasks;
|
|
@@ -28686,7 +28827,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
|
|
|
28686
28827
|
async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config) {
|
|
28687
28828
|
const startTime = Date.now();
|
|
28688
28829
|
let framesCaptured = 0;
|
|
28689
|
-
if (!
|
|
28830
|
+
if (!existsSync25(task.outputDir)) mkdirSync17(task.outputDir, { recursive: true });
|
|
28690
28831
|
let session = null;
|
|
28691
28832
|
let perf;
|
|
28692
28833
|
try {
|
|
@@ -28776,17 +28917,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
|
|
|
28776
28917
|
return results;
|
|
28777
28918
|
}
|
|
28778
28919
|
async function mergeWorkerFrames(workDir, tasks, outputDir) {
|
|
28779
|
-
if (!
|
|
28920
|
+
if (!existsSync25(outputDir)) mkdirSync17(outputDir, { recursive: true });
|
|
28780
28921
|
let totalFrames = 0;
|
|
28781
28922
|
const sortedTasks = [...tasks].sort((a, b) => a.startFrame - b.startFrame);
|
|
28782
28923
|
for (const task of sortedTasks) {
|
|
28783
|
-
if (!
|
|
28924
|
+
if (!existsSync25(task.outputDir)) {
|
|
28784
28925
|
continue;
|
|
28785
28926
|
}
|
|
28786
28927
|
const files = readdirSync10(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
|
|
28787
28928
|
const copyTasks = files.map(async (file) => {
|
|
28788
|
-
const sourcePath =
|
|
28789
|
-
const targetPath =
|
|
28929
|
+
const sourcePath = join27(task.outputDir, file);
|
|
28930
|
+
const targetPath = join27(outputDir, file);
|
|
28790
28931
|
try {
|
|
28791
28932
|
await rename(sourcePath, targetPath);
|
|
28792
28933
|
} catch {
|
|
@@ -28823,8 +28964,8 @@ var init_parallelCoordinator = __esm({
|
|
|
28823
28964
|
// ../engine/src/services/fileServer.ts
|
|
28824
28965
|
import { Hono as Hono2 } from "hono";
|
|
28825
28966
|
import { serve } from "@hono/node-server";
|
|
28826
|
-
import { readFileSync as
|
|
28827
|
-
import { join as
|
|
28967
|
+
import { readFileSync as readFileSync17, existsSync as existsSync26, statSync as statSync7 } from "fs";
|
|
28968
|
+
import { join as join28, extname as extname6 } from "path";
|
|
28828
28969
|
function stripEmbeddedRuntimeScripts(html) {
|
|
28829
28970
|
if (!html) return html;
|
|
28830
28971
|
const scriptRe = /<script\b[^>]*>[\s\S]*?<\/script>/gi;
|
|
@@ -28893,22 +29034,22 @@ function createFileServer(options) {
|
|
|
28893
29034
|
let requestPath = c2.req.path;
|
|
28894
29035
|
if (requestPath === "/") requestPath = "/index.html";
|
|
28895
29036
|
const relativePath = requestPath.replace(/^\//, "");
|
|
28896
|
-
const compiledPath = compiledDir ?
|
|
29037
|
+
const compiledPath = compiledDir ? join28(compiledDir, relativePath) : null;
|
|
28897
29038
|
const hasCompiledFile = Boolean(
|
|
28898
|
-
compiledPath &&
|
|
29039
|
+
compiledPath && existsSync26(compiledPath) && statSync7(compiledPath).isFile()
|
|
28899
29040
|
);
|
|
28900
|
-
const filePath = hasCompiledFile ? compiledPath :
|
|
28901
|
-
if (!
|
|
29041
|
+
const filePath = hasCompiledFile ? compiledPath : join28(projectDir, relativePath);
|
|
29042
|
+
if (!existsSync26(filePath) || !statSync7(filePath).isFile()) {
|
|
28902
29043
|
return c2.text("Not found", 404);
|
|
28903
29044
|
}
|
|
28904
29045
|
const ext = extname6(filePath).toLowerCase();
|
|
28905
29046
|
const contentType = MIME_TYPES2[ext] || "application/octet-stream";
|
|
28906
29047
|
if (ext === ".html") {
|
|
28907
|
-
const rawHtml =
|
|
29048
|
+
const rawHtml = readFileSync17(filePath, "utf-8");
|
|
28908
29049
|
const html = relativePath === "index.html" ? injectScriptsIntoHtml(rawHtml, headScripts, bodyScripts, stripEmbeddedRuntime) : rawHtml;
|
|
28909
29050
|
return c2.text(html, 200, { "Content-Type": contentType });
|
|
28910
29051
|
}
|
|
28911
|
-
const content =
|
|
29052
|
+
const content = readFileSync17(filePath);
|
|
28912
29053
|
return new Response(content, {
|
|
28913
29054
|
status: 200,
|
|
28914
29055
|
headers: { "Content-Type": contentType }
|
|
@@ -30176,8 +30317,8 @@ var init_shaderTransitions = __esm({
|
|
|
30176
30317
|
});
|
|
30177
30318
|
|
|
30178
30319
|
// ../engine/src/services/hdrCapture.ts
|
|
30179
|
-
import { existsSync as
|
|
30180
|
-
import { join as
|
|
30320
|
+
import { existsSync as existsSync27, readdirSync as readdirSync11 } from "fs";
|
|
30321
|
+
import { join as join29 } from "path";
|
|
30181
30322
|
import { homedir as homedir6 } from "os";
|
|
30182
30323
|
function linearToPQ(L2) {
|
|
30183
30324
|
const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
|
|
@@ -30293,12 +30434,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
|
|
|
30293
30434
|
return output;
|
|
30294
30435
|
}
|
|
30295
30436
|
function resolveHeadedChromePath() {
|
|
30296
|
-
const baseDir =
|
|
30297
|
-
if (!
|
|
30437
|
+
const baseDir = join29(homedir6(), ".cache", "puppeteer", "chrome");
|
|
30438
|
+
if (!existsSync27(baseDir)) return void 0;
|
|
30298
30439
|
const versions = readdirSync11(baseDir).sort().reverse();
|
|
30299
30440
|
for (const version of versions) {
|
|
30300
30441
|
const candidates = [
|
|
30301
|
-
|
|
30442
|
+
join29(
|
|
30302
30443
|
baseDir,
|
|
30303
30444
|
version,
|
|
30304
30445
|
"chrome-mac-arm64",
|
|
@@ -30307,7 +30448,7 @@ function resolveHeadedChromePath() {
|
|
|
30307
30448
|
"MacOS",
|
|
30308
30449
|
"Google Chrome for Testing"
|
|
30309
30450
|
),
|
|
30310
|
-
|
|
30451
|
+
join29(
|
|
30311
30452
|
baseDir,
|
|
30312
30453
|
version,
|
|
30313
30454
|
"chrome-mac-x64",
|
|
@@ -30316,11 +30457,11 @@ function resolveHeadedChromePath() {
|
|
|
30316
30457
|
"MacOS",
|
|
30317
30458
|
"Google Chrome for Testing"
|
|
30318
30459
|
),
|
|
30319
|
-
|
|
30320
|
-
|
|
30460
|
+
join29(baseDir, version, "chrome-linux64", "chrome"),
|
|
30461
|
+
join29(baseDir, version, "chrome-win64", "chrome.exe")
|
|
30321
30462
|
];
|
|
30322
30463
|
for (const binary of candidates) {
|
|
30323
|
-
if (
|
|
30464
|
+
if (existsSync27(binary)) return binary;
|
|
30324
30465
|
}
|
|
30325
30466
|
}
|
|
30326
30467
|
return void 0;
|
|
@@ -30592,8 +30733,8 @@ var init_staticGuard = __esm({
|
|
|
30592
30733
|
});
|
|
30593
30734
|
|
|
30594
30735
|
// ../core/src/compiler/htmlBundler.ts
|
|
30595
|
-
import { readFileSync as
|
|
30596
|
-
import { join as
|
|
30736
|
+
import { readFileSync as readFileSync18, existsSync as existsSync28 } from "fs";
|
|
30737
|
+
import { join as join30, resolve as resolve12, isAbsolute as isAbsolute4, sep as sep2 } from "path";
|
|
30597
30738
|
import { transformSync } from "esbuild";
|
|
30598
30739
|
function parseHTMLContent2(html) {
|
|
30599
30740
|
const trimmed = html.trimStart().toLowerCase();
|
|
@@ -30661,17 +30802,17 @@ function isRelativeUrl(url) {
|
|
|
30661
30802
|
return !url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("//") && !url.startsWith("data:") && !isAbsolute4(url);
|
|
30662
30803
|
}
|
|
30663
30804
|
function safeReadFile(filePath) {
|
|
30664
|
-
if (!
|
|
30805
|
+
if (!existsSync28(filePath)) return null;
|
|
30665
30806
|
try {
|
|
30666
|
-
return
|
|
30807
|
+
return readFileSync18(filePath, "utf-8");
|
|
30667
30808
|
} catch {
|
|
30668
30809
|
return null;
|
|
30669
30810
|
}
|
|
30670
30811
|
}
|
|
30671
30812
|
function safeReadFileBuffer(filePath) {
|
|
30672
|
-
if (!
|
|
30813
|
+
if (!existsSync28(filePath)) return null;
|
|
30673
30814
|
try {
|
|
30674
|
-
return
|
|
30815
|
+
return readFileSync18(filePath);
|
|
30675
30816
|
} catch {
|
|
30676
30817
|
return null;
|
|
30677
30818
|
}
|
|
@@ -30862,9 +31003,9 @@ function stripJsCommentsParserSafe(source) {
|
|
|
30862
31003
|
}
|
|
30863
31004
|
}
|
|
30864
31005
|
async function bundleToSingleHtml(projectDir, options) {
|
|
30865
|
-
const indexPath =
|
|
30866
|
-
if (!
|
|
30867
|
-
const rawHtml =
|
|
31006
|
+
const indexPath = join30(projectDir, "index.html");
|
|
31007
|
+
if (!existsSync28(indexPath)) throw new Error("index.html not found in project directory");
|
|
31008
|
+
const rawHtml = readFileSync18(indexPath, "utf-8");
|
|
30868
31009
|
const compiled = await compileHtml(rawHtml, projectDir, options?.probeMediaDuration);
|
|
30869
31010
|
const staticGuard = validateHyperframeHtmlContract(compiled);
|
|
30870
31011
|
if (!staticGuard.isValid) {
|
|
@@ -31139,7 +31280,7 @@ var init_compiler = __esm({
|
|
|
31139
31280
|
|
|
31140
31281
|
// ../producer/src/services/hyperframeRuntimeLoader.ts
|
|
31141
31282
|
import { createHash as createHash3 } from "crypto";
|
|
31142
|
-
import { existsSync as
|
|
31283
|
+
import { existsSync as existsSync29, readFileSync as readFileSync19 } from "fs";
|
|
31143
31284
|
import { dirname as dirname9, resolve as resolve13 } from "path";
|
|
31144
31285
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31145
31286
|
function resolveHyperframeManifestPath() {
|
|
@@ -31152,7 +31293,7 @@ function resolveHyperframeManifestPath() {
|
|
|
31152
31293
|
MODULE_RELATIVE_MANIFEST_PATH
|
|
31153
31294
|
];
|
|
31154
31295
|
for (const candidate of candidates) {
|
|
31155
|
-
if (
|
|
31296
|
+
if (existsSync29(candidate)) {
|
|
31156
31297
|
return candidate;
|
|
31157
31298
|
}
|
|
31158
31299
|
}
|
|
@@ -31163,12 +31304,12 @@ function getVerifiedHyperframeRuntimeSource() {
|
|
|
31163
31304
|
}
|
|
31164
31305
|
function resolveVerifiedHyperframeRuntime() {
|
|
31165
31306
|
const manifestPath = resolveHyperframeManifestPath();
|
|
31166
|
-
if (!
|
|
31307
|
+
if (!existsSync29(manifestPath)) {
|
|
31167
31308
|
throw new Error(
|
|
31168
31309
|
`[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
|
|
31169
31310
|
);
|
|
31170
31311
|
}
|
|
31171
|
-
const manifestRaw =
|
|
31312
|
+
const manifestRaw = readFileSync19(manifestPath, "utf8");
|
|
31172
31313
|
const manifest = JSON.parse(manifestRaw);
|
|
31173
31314
|
const runtimeFileName = manifest.artifacts?.iife;
|
|
31174
31315
|
if (!runtimeFileName || !manifest.sha256) {
|
|
@@ -31177,10 +31318,10 @@ function resolveVerifiedHyperframeRuntime() {
|
|
|
31177
31318
|
);
|
|
31178
31319
|
}
|
|
31179
31320
|
const runtimePath = resolve13(dirname9(manifestPath), runtimeFileName);
|
|
31180
|
-
if (!
|
|
31321
|
+
if (!existsSync29(runtimePath)) {
|
|
31181
31322
|
throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
|
|
31182
31323
|
}
|
|
31183
|
-
const runtimeSource =
|
|
31324
|
+
const runtimeSource = readFileSync19(runtimePath, "utf8");
|
|
31184
31325
|
const runtimeSha = createHash3("sha256").update(runtimeSource, "utf8").digest("hex");
|
|
31185
31326
|
if (runtimeSha !== manifest.sha256) {
|
|
31186
31327
|
throw new Error(
|
|
@@ -31219,16 +31360,16 @@ var init_hyperframeRuntimeLoader = __esm({
|
|
|
31219
31360
|
// ../producer/src/services/fileServer.ts
|
|
31220
31361
|
import { Hono as Hono3 } from "hono";
|
|
31221
31362
|
import { serve as serve2 } from "@hono/node-server";
|
|
31222
|
-
import { readFileSync as
|
|
31223
|
-
import { join as
|
|
31363
|
+
import { readFileSync as readFileSync20, existsSync as existsSync30, realpathSync, statSync as statSync8 } from "fs";
|
|
31364
|
+
import { join as join31, extname as extname7, resolve as resolve14, sep as sep3 } from "path";
|
|
31224
31365
|
function isPathInside(child, parent, options = {}) {
|
|
31225
31366
|
const { resolveSymlinks = false, pathModule } = options;
|
|
31226
31367
|
const resolveFn = pathModule?.resolve ?? resolve14;
|
|
31227
31368
|
const separator = pathModule?.sep ?? sep3;
|
|
31228
31369
|
const resolvedChild = resolveFn(child);
|
|
31229
31370
|
const resolvedParent = resolveFn(parent);
|
|
31230
|
-
const normalizedChild = resolveSymlinks &&
|
|
31231
|
-
const normalizedParent = resolveSymlinks &&
|
|
31371
|
+
const normalizedChild = resolveSymlinks && existsSync30(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
|
|
31372
|
+
const normalizedParent = resolveSymlinks && existsSync30(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
|
|
31232
31373
|
if (normalizedChild === normalizedParent) return true;
|
|
31233
31374
|
const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
|
|
31234
31375
|
return normalizedChild.startsWith(parentWithSep);
|
|
@@ -31317,14 +31458,14 @@ function createFileServer2(options) {
|
|
|
31317
31458
|
const relativePath = requestPath.replace(/^\//, "");
|
|
31318
31459
|
let filePath = null;
|
|
31319
31460
|
if (compiledDir) {
|
|
31320
|
-
const candidate =
|
|
31321
|
-
if (
|
|
31461
|
+
const candidate = join31(compiledDir, relativePath);
|
|
31462
|
+
if (existsSync30(candidate) && isPathInside(candidate, compiledDir) && statSync8(candidate).isFile()) {
|
|
31322
31463
|
filePath = candidate;
|
|
31323
31464
|
}
|
|
31324
31465
|
}
|
|
31325
31466
|
if (!filePath) {
|
|
31326
|
-
const candidate =
|
|
31327
|
-
if (
|
|
31467
|
+
const candidate = join31(projectDir, relativePath);
|
|
31468
|
+
if (existsSync30(candidate) && isPathInside(candidate, projectDir) && statSync8(candidate).isFile()) {
|
|
31328
31469
|
filePath = candidate;
|
|
31329
31470
|
}
|
|
31330
31471
|
}
|
|
@@ -31337,7 +31478,7 @@ function createFileServer2(options) {
|
|
|
31337
31478
|
const ext = extname7(filePath).toLowerCase();
|
|
31338
31479
|
const contentType = MIME_TYPES3[ext] || "application/octet-stream";
|
|
31339
31480
|
if (ext === ".html") {
|
|
31340
|
-
const rawHtml =
|
|
31481
|
+
const rawHtml = readFileSync20(filePath, "utf-8");
|
|
31341
31482
|
const isIndex = relativePath === "index.html";
|
|
31342
31483
|
let html = rawHtml;
|
|
31343
31484
|
if (preHeadScripts.length > 0) {
|
|
@@ -31346,7 +31487,7 @@ function createFileServer2(options) {
|
|
|
31346
31487
|
html = isIndex ? injectScriptsIntoHtml2(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
|
|
31347
31488
|
return c2.text(html, 200, { "Content-Type": contentType });
|
|
31348
31489
|
}
|
|
31349
|
-
const content =
|
|
31490
|
+
const content = readFileSync20(filePath);
|
|
31350
31491
|
return new Response(content, {
|
|
31351
31492
|
status: 200,
|
|
31352
31493
|
headers: { "Content-Type": contentType }
|
|
@@ -31698,7 +31839,7 @@ var init_ffprobe2 = __esm({
|
|
|
31698
31839
|
});
|
|
31699
31840
|
|
|
31700
31841
|
// ../producer/src/utils/paths.ts
|
|
31701
|
-
import { resolve as resolve15, basename as basename2, join as
|
|
31842
|
+
import { resolve as resolve15, basename as basename2, join as join32, relative as relative2, isAbsolute as isAbsolute5 } from "path";
|
|
31702
31843
|
function isPathInside2(childPath, parentPath) {
|
|
31703
31844
|
const absChild = resolve15(childPath);
|
|
31704
31845
|
const absParent = resolve15(parentPath);
|
|
@@ -31719,7 +31860,7 @@ function toExternalAssetKey(absPath) {
|
|
|
31719
31860
|
function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
|
|
31720
31861
|
const absoluteProjectDir = resolve15(projectDir);
|
|
31721
31862
|
const projectName = basename2(absoluteProjectDir);
|
|
31722
|
-
const resolvedOutputPath = outputPath ??
|
|
31863
|
+
const resolvedOutputPath = outputPath ?? join32(rendersDir, `${projectName}.mp4`);
|
|
31723
31864
|
const absoluteOutputPath = resolve15(resolvedOutputPath);
|
|
31724
31865
|
return { absoluteProjectDir, absoluteOutputPath };
|
|
31725
31866
|
}
|
|
@@ -31792,9 +31933,9 @@ var init_fontData_generated = __esm({
|
|
|
31792
31933
|
});
|
|
31793
31934
|
|
|
31794
31935
|
// ../producer/src/services/deterministicFonts.ts
|
|
31795
|
-
import { existsSync as
|
|
31936
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
31796
31937
|
import { homedir as homedir7 } from "os";
|
|
31797
|
-
import { join as
|
|
31938
|
+
import { join as join33 } from "path";
|
|
31798
31939
|
function normalizeFamilyName(family) {
|
|
31799
31940
|
return family.trim().replace(/^['"]|['"]$/g, "").trim().toLowerCase();
|
|
31800
31941
|
}
|
|
@@ -31905,14 +32046,14 @@ function fontSlug(familyName) {
|
|
|
31905
32046
|
return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
31906
32047
|
}
|
|
31907
32048
|
function fontCacheDir(slug) {
|
|
31908
|
-
const dir =
|
|
31909
|
-
if (!
|
|
31910
|
-
|
|
32049
|
+
const dir = join33(GOOGLE_FONTS_CACHE_DIR, slug);
|
|
32050
|
+
if (!existsSync31(dir)) {
|
|
32051
|
+
mkdirSync18(dir, { recursive: true });
|
|
31911
32052
|
}
|
|
31912
32053
|
return dir;
|
|
31913
32054
|
}
|
|
31914
32055
|
function cachedWoff2Path(slug, weight, style) {
|
|
31915
|
-
return
|
|
32056
|
+
return join33(fontCacheDir(slug), `${weight}-${style}.woff2`);
|
|
31916
32057
|
}
|
|
31917
32058
|
async function fetchGoogleFont(familyName) {
|
|
31918
32059
|
const slug = fontSlug(familyName);
|
|
@@ -31938,17 +32079,17 @@ async function fetchGoogleFont(familyName) {
|
|
|
31938
32079
|
const woff2Url = match[3] || "";
|
|
31939
32080
|
if (!woff2Url) continue;
|
|
31940
32081
|
const cachePath2 = cachedWoff2Path(slug, weight, style);
|
|
31941
|
-
if (!
|
|
32082
|
+
if (!existsSync31(cachePath2)) {
|
|
31942
32083
|
try {
|
|
31943
32084
|
const fontRes = await fetch(woff2Url);
|
|
31944
32085
|
if (!fontRes.ok) continue;
|
|
31945
32086
|
const buffer = Buffer.from(await fontRes.arrayBuffer());
|
|
31946
|
-
|
|
32087
|
+
writeFileSync13(cachePath2, buffer);
|
|
31947
32088
|
} catch {
|
|
31948
32089
|
continue;
|
|
31949
32090
|
}
|
|
31950
32091
|
}
|
|
31951
|
-
const fontBytes =
|
|
32092
|
+
const fontBytes = readFileSync21(cachePath2);
|
|
31952
32093
|
const dataUri = `data:font/woff2;base64,${fontBytes.toString("base64")}`;
|
|
31953
32094
|
faces.push({ weight, style, dataUri });
|
|
31954
32095
|
}
|
|
@@ -32124,14 +32265,14 @@ var init_deterministicFonts = __esm({
|
|
|
32124
32265
|
poppins: "poppins",
|
|
32125
32266
|
"segoe ui": "roboto"
|
|
32126
32267
|
};
|
|
32127
|
-
GOOGLE_FONTS_CACHE_DIR =
|
|
32268
|
+
GOOGLE_FONTS_CACHE_DIR = join33(homedir7(), ".cache", "hyperframes", "fonts");
|
|
32128
32269
|
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";
|
|
32129
32270
|
}
|
|
32130
32271
|
});
|
|
32131
32272
|
|
|
32132
32273
|
// ../producer/src/services/htmlCompiler.ts
|
|
32133
|
-
import { readFileSync as
|
|
32134
|
-
import { join as
|
|
32274
|
+
import { readFileSync as readFileSync22, existsSync as existsSync32, mkdirSync as mkdirSync19 } from "fs";
|
|
32275
|
+
import { join as join34, dirname as dirname10, resolve as resolve16 } from "path";
|
|
32135
32276
|
import postcss from "postcss";
|
|
32136
32277
|
function dedupeElementsById(elements) {
|
|
32137
32278
|
const deduped = /* @__PURE__ */ new Map();
|
|
@@ -32182,16 +32323,16 @@ function detectRenderModeHints(html) {
|
|
|
32182
32323
|
async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
|
|
32183
32324
|
let filePath = src;
|
|
32184
32325
|
if (isHttpUrl(src)) {
|
|
32185
|
-
if (!
|
|
32326
|
+
if (!existsSync32(downloadDir)) mkdirSync19(downloadDir, { recursive: true });
|
|
32186
32327
|
try {
|
|
32187
32328
|
filePath = await downloadToTemp(src, downloadDir);
|
|
32188
32329
|
} catch {
|
|
32189
32330
|
return { duration: 0, resolvedPath: src };
|
|
32190
32331
|
}
|
|
32191
32332
|
} else if (!filePath.startsWith("/")) {
|
|
32192
|
-
filePath =
|
|
32333
|
+
filePath = join34(baseDir, filePath);
|
|
32193
32334
|
}
|
|
32194
|
-
if (!
|
|
32335
|
+
if (!existsSync32(filePath)) {
|
|
32195
32336
|
return { duration: 0, resolvedPath: filePath };
|
|
32196
32337
|
}
|
|
32197
32338
|
const metadata = tagName19 === "video" ? await extractMediaMetadata(filePath) : await extractAudioMetadata(filePath);
|
|
@@ -32260,10 +32401,10 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
|
|
|
32260
32401
|
if (visited.has(filePath)) {
|
|
32261
32402
|
continue;
|
|
32262
32403
|
}
|
|
32263
|
-
if (!
|
|
32404
|
+
if (!existsSync32(filePath)) {
|
|
32264
32405
|
continue;
|
|
32265
32406
|
}
|
|
32266
|
-
const rawSubHtml =
|
|
32407
|
+
const rawSubHtml = readFileSync22(filePath, "utf-8");
|
|
32267
32408
|
const nestedVisited = new Set(visited);
|
|
32268
32409
|
nestedVisited.add(filePath);
|
|
32269
32410
|
workItems.push({ srcPath, absoluteStart, absoluteEnd, filePath, rawSubHtml, nestedVisited });
|
|
@@ -32470,8 +32611,8 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
|
|
|
32470
32611
|
let compHtml = subCompositions.get(srcPath) || null;
|
|
32471
32612
|
if (!compHtml) {
|
|
32472
32613
|
const filePath = resolve16(projectDir, srcPath);
|
|
32473
|
-
if (
|
|
32474
|
-
compHtml =
|
|
32614
|
+
if (existsSync32(filePath)) {
|
|
32615
|
+
compHtml = readFileSync22(filePath, "utf-8");
|
|
32475
32616
|
}
|
|
32476
32617
|
}
|
|
32477
32618
|
if (!compHtml) {
|
|
@@ -32698,7 +32839,7 @@ function collectExternalAssets(html, projectDir) {
|
|
|
32698
32839
|
if (isPathInside2(absPath, absProjectDir)) {
|
|
32699
32840
|
return null;
|
|
32700
32841
|
}
|
|
32701
|
-
if (!
|
|
32842
|
+
if (!existsSync32(absPath)) return null;
|
|
32702
32843
|
const safeKey = toExternalAssetKey(absPath);
|
|
32703
32844
|
externalAssets.set(safeKey, absPath);
|
|
32704
32845
|
return safeKey;
|
|
@@ -32743,7 +32884,7 @@ function collectExternalAssets(html, projectDir) {
|
|
|
32743
32884
|
};
|
|
32744
32885
|
}
|
|
32745
32886
|
async function compileForRender(projectDir, htmlPath, downloadDir) {
|
|
32746
|
-
const rawHtml =
|
|
32887
|
+
const rawHtml = readFileSync22(htmlPath, "utf-8");
|
|
32747
32888
|
const { html: compiledHtml, unresolvedCompositions } = await compileHtmlFile(
|
|
32748
32889
|
rawHtml,
|
|
32749
32890
|
projectDir,
|
|
@@ -33083,17 +33224,17 @@ var init_hdrImageTransferCache = __esm({
|
|
|
33083
33224
|
|
|
33084
33225
|
// ../producer/src/services/renderOrchestrator.ts
|
|
33085
33226
|
import {
|
|
33086
|
-
existsSync as
|
|
33087
|
-
mkdirSync as
|
|
33227
|
+
existsSync as existsSync33,
|
|
33228
|
+
mkdirSync as mkdirSync20,
|
|
33088
33229
|
rmSync as rmSync7,
|
|
33089
|
-
readFileSync as
|
|
33230
|
+
readFileSync as readFileSync23,
|
|
33090
33231
|
readdirSync as readdirSync13,
|
|
33091
33232
|
statSync as statSync9,
|
|
33092
|
-
writeFileSync as
|
|
33233
|
+
writeFileSync as writeFileSync14,
|
|
33093
33234
|
copyFileSync as copyFileSync2,
|
|
33094
33235
|
appendFileSync
|
|
33095
33236
|
} from "fs";
|
|
33096
|
-
import { join as
|
|
33237
|
+
import { join as join35, dirname as dirname11, resolve as resolve17 } from "path";
|
|
33097
33238
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
33098
33239
|
import { freemem as freemem2 } from "os";
|
|
33099
33240
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -33119,7 +33260,7 @@ function sampleDirectoryBytes(dir) {
|
|
|
33119
33260
|
continue;
|
|
33120
33261
|
}
|
|
33121
33262
|
for (const name of entries2) {
|
|
33122
|
-
const full =
|
|
33263
|
+
const full = join35(current, name);
|
|
33123
33264
|
try {
|
|
33124
33265
|
const st2 = statSync9(full);
|
|
33125
33266
|
if (st2.isDirectory()) {
|
|
@@ -33194,21 +33335,21 @@ function installDebugLogger(logPath, log2 = defaultLogger) {
|
|
|
33194
33335
|
};
|
|
33195
33336
|
}
|
|
33196
33337
|
function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
33197
|
-
const compileDir =
|
|
33198
|
-
|
|
33199
|
-
|
|
33338
|
+
const compileDir = join35(workDir, "compiled");
|
|
33339
|
+
mkdirSync20(compileDir, { recursive: true });
|
|
33340
|
+
writeFileSync14(join35(compileDir, "index.html"), compiled.html, "utf-8");
|
|
33200
33341
|
for (const [srcPath, html] of compiled.subCompositions) {
|
|
33201
|
-
const outPath =
|
|
33202
|
-
|
|
33203
|
-
|
|
33342
|
+
const outPath = join35(compileDir, srcPath);
|
|
33343
|
+
mkdirSync20(dirname11(outPath), { recursive: true });
|
|
33344
|
+
writeFileSync14(outPath, html, "utf-8");
|
|
33204
33345
|
}
|
|
33205
33346
|
for (const [relativePath, absolutePath] of compiled.externalAssets) {
|
|
33206
|
-
const outPath = resolve17(
|
|
33347
|
+
const outPath = resolve17(join35(compileDir, relativePath));
|
|
33207
33348
|
if (!isPathInside2(outPath, compileDir)) {
|
|
33208
33349
|
console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
|
|
33209
33350
|
continue;
|
|
33210
33351
|
}
|
|
33211
|
-
|
|
33352
|
+
mkdirSync20(dirname11(outPath), { recursive: true });
|
|
33212
33353
|
copyFileSync2(absolutePath, outPath);
|
|
33213
33354
|
}
|
|
33214
33355
|
if (includeSummary) {
|
|
@@ -33233,7 +33374,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
33233
33374
|
subCompositions: Array.from(compiled.subCompositions.keys()),
|
|
33234
33375
|
renderModeHints: compiled.renderModeHints
|
|
33235
33376
|
};
|
|
33236
|
-
|
|
33377
|
+
writeFileSync14(join35(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
|
|
33237
33378
|
}
|
|
33238
33379
|
}
|
|
33239
33380
|
function applyRenderModeHints(cfg, compiled, log2 = defaultLogger) {
|
|
@@ -33254,12 +33395,12 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
|
|
|
33254
33395
|
if (videoFrameIndex < 1) return;
|
|
33255
33396
|
const maxIndex = getMaxFrameIndex(frameDir);
|
|
33256
33397
|
const effectiveIndex = maxIndex > 0 ? Math.min(videoFrameIndex, maxIndex) : videoFrameIndex;
|
|
33257
|
-
const framePath =
|
|
33258
|
-
if (!
|
|
33398
|
+
const framePath = join35(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
|
|
33399
|
+
if (!existsSync33(framePath)) {
|
|
33259
33400
|
return;
|
|
33260
33401
|
}
|
|
33261
33402
|
try {
|
|
33262
|
-
const { data: hdrRgb, width: srcW, height: srcH } = decodePngToRgb48le(
|
|
33403
|
+
const { data: hdrRgb, width: srcW, height: srcH } = decodePngToRgb48le(readFileSync23(framePath));
|
|
33263
33404
|
if (sourceTransfer && targetTransfer && sourceTransfer !== targetTransfer) {
|
|
33264
33405
|
convertTransfer(hdrRgb, sourceTransfer, targetTransfer);
|
|
33265
33406
|
}
|
|
@@ -33438,7 +33579,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
|
|
|
33438
33579
|
const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
|
|
33439
33580
|
const localTime = time - startTime;
|
|
33440
33581
|
const frameNum = Math.floor(localTime * fps) + 1;
|
|
33441
|
-
const expectedFrame = frameDir ?
|
|
33582
|
+
const expectedFrame = frameDir ? join35(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
|
|
33442
33583
|
log2.info("[diag] hdr layer blit", {
|
|
33443
33584
|
frame: debugFrameIndex,
|
|
33444
33585
|
layerIdx,
|
|
@@ -33450,7 +33591,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
|
|
|
33450
33591
|
localTime: localTime.toFixed(3),
|
|
33451
33592
|
hdrFrameNum: frameNum,
|
|
33452
33593
|
expectedFrame,
|
|
33453
|
-
expectedFrameExists: expectedFrame ?
|
|
33594
|
+
expectedFrameExists: expectedFrame ? existsSync33(expectedFrame) : false
|
|
33454
33595
|
});
|
|
33455
33596
|
}
|
|
33456
33597
|
}
|
|
@@ -33475,8 +33616,8 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
|
|
|
33475
33616
|
if (shouldLog && debugDumpDir) {
|
|
33476
33617
|
const after2 = countNonZeroRgb48(canvas);
|
|
33477
33618
|
const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
|
|
33478
|
-
const dumpPath =
|
|
33479
|
-
|
|
33619
|
+
const dumpPath = join35(debugDumpDir, dumpName);
|
|
33620
|
+
writeFileSync14(dumpPath, domPng);
|
|
33480
33621
|
log2.info("[diag] dom layer blit", {
|
|
33481
33622
|
frame: debugFrameIndex,
|
|
33482
33623
|
layerIdx,
|
|
@@ -33549,8 +33690,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
|
|
|
33549
33690
|
async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
|
|
33550
33691
|
const moduleDir = dirname11(fileURLToPath3(import.meta.url));
|
|
33551
33692
|
const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve17(process.env.PRODUCER_RENDERS_DIR, "..") : resolve17(moduleDir, "../..");
|
|
33552
|
-
const debugDir =
|
|
33553
|
-
const workDir = job.config.debug ?
|
|
33693
|
+
const debugDir = join35(producerRoot, ".debug");
|
|
33694
|
+
const workDir = job.config.debug ? join35(debugDir, job.id) : join35(dirname11(outputPath), `work-${job.id}`);
|
|
33554
33695
|
const pipelineStart = Date.now();
|
|
33555
33696
|
const log2 = job.config.logger ?? defaultLogger;
|
|
33556
33697
|
let fileServer = null;
|
|
@@ -33562,7 +33703,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33562
33703
|
videoExtractionFailures: 0,
|
|
33563
33704
|
imageDecodeFailures: 0
|
|
33564
33705
|
};
|
|
33565
|
-
const perfOutputPath =
|
|
33706
|
+
const perfOutputPath = join35(workDir, "perf-summary.json");
|
|
33566
33707
|
const cfg = { ...job.config.producerConfig ?? resolveConfig() };
|
|
33567
33708
|
const outputFormat = job.config.format ?? "mp4";
|
|
33568
33709
|
const isWebm = outputFormat === "webm";
|
|
@@ -33595,28 +33736,28 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33595
33736
|
};
|
|
33596
33737
|
job.startedAt = /* @__PURE__ */ new Date();
|
|
33597
33738
|
assertNotAborted();
|
|
33598
|
-
if (!
|
|
33739
|
+
if (!existsSync33(workDir)) mkdirSync20(workDir, { recursive: true });
|
|
33599
33740
|
if (job.config.debug) {
|
|
33600
|
-
const logPath =
|
|
33741
|
+
const logPath = join35(workDir, "render.log");
|
|
33601
33742
|
restoreLogger = installDebugLogger(logPath, log2);
|
|
33602
33743
|
}
|
|
33603
33744
|
const entryFile = job.config.entryFile || "index.html";
|
|
33604
|
-
let htmlPath =
|
|
33605
|
-
if (!
|
|
33745
|
+
let htmlPath = join35(projectDir, entryFile);
|
|
33746
|
+
if (!existsSync33(htmlPath)) {
|
|
33606
33747
|
throw new Error(`Entry file not found: ${htmlPath}`);
|
|
33607
33748
|
}
|
|
33608
33749
|
assertNotAborted();
|
|
33609
|
-
const rawEntry =
|
|
33750
|
+
const rawEntry = readFileSync23(htmlPath, "utf-8");
|
|
33610
33751
|
if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
|
|
33611
|
-
const wrapperPath =
|
|
33612
|
-
const projectIndexPath =
|
|
33613
|
-
if (!
|
|
33752
|
+
const wrapperPath = join35(workDir, "standalone-entry.html");
|
|
33753
|
+
const projectIndexPath = join35(projectDir, "index.html");
|
|
33754
|
+
if (!existsSync33(projectIndexPath)) {
|
|
33614
33755
|
throw new Error(
|
|
33615
33756
|
`Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
|
|
33616
33757
|
);
|
|
33617
33758
|
}
|
|
33618
33759
|
const standaloneHtml = extractStandaloneEntryFromIndex(
|
|
33619
|
-
|
|
33760
|
+
readFileSync23(projectIndexPath, "utf-8"),
|
|
33620
33761
|
entryFile
|
|
33621
33762
|
);
|
|
33622
33763
|
if (!standaloneHtml) {
|
|
@@ -33624,7 +33765,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33624
33765
|
`Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
|
|
33625
33766
|
);
|
|
33626
33767
|
}
|
|
33627
|
-
|
|
33768
|
+
writeFileSync14(wrapperPath, standaloneHtml, "utf-8");
|
|
33628
33769
|
htmlPath = wrapperPath;
|
|
33629
33770
|
log2.info("Extracted standalone entry from index.html host context", {
|
|
33630
33771
|
entryFile
|
|
@@ -33633,7 +33774,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33633
33774
|
const stage1Start = Date.now();
|
|
33634
33775
|
updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
|
|
33635
33776
|
const compileStart = Date.now();
|
|
33636
|
-
let compiled = await compileForRender(projectDir, htmlPath,
|
|
33777
|
+
let compiled = await compileForRender(projectDir, htmlPath, join35(workDir, "downloads"));
|
|
33637
33778
|
assertNotAborted();
|
|
33638
33779
|
perfStages.compileOnlyMs = Date.now() - compileStart;
|
|
33639
33780
|
applyRenderModeHints(cfg, compiled, log2);
|
|
@@ -33665,7 +33806,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33665
33806
|
reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
|
|
33666
33807
|
fileServer = await createFileServer2({
|
|
33667
33808
|
projectDir,
|
|
33668
|
-
compiledDir:
|
|
33809
|
+
compiledDir: join35(workDir, "compiled"),
|
|
33669
33810
|
port: 0,
|
|
33670
33811
|
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
33671
33812
|
});
|
|
@@ -33679,7 +33820,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33679
33820
|
};
|
|
33680
33821
|
probeSession = await createCaptureSession(
|
|
33681
33822
|
fileServer.url,
|
|
33682
|
-
|
|
33823
|
+
join35(workDir, "probe"),
|
|
33683
33824
|
captureOpts,
|
|
33684
33825
|
null,
|
|
33685
33826
|
cfg
|
|
@@ -33711,7 +33852,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33711
33852
|
compiled,
|
|
33712
33853
|
resolutions,
|
|
33713
33854
|
projectDir,
|
|
33714
|
-
|
|
33855
|
+
join35(workDir, "downloads")
|
|
33715
33856
|
);
|
|
33716
33857
|
assertNotAborted();
|
|
33717
33858
|
composition.videos = compiled.videos;
|
|
@@ -33865,7 +34006,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33865
34006
|
const stage2Start = Date.now();
|
|
33866
34007
|
updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
|
|
33867
34008
|
let frameLookup = null;
|
|
33868
|
-
const compiledDir =
|
|
34009
|
+
const compiledDir = join35(workDir, "compiled");
|
|
33869
34010
|
let extractionResult = null;
|
|
33870
34011
|
const nativeHdrVideoIds = /* @__PURE__ */ new Set();
|
|
33871
34012
|
const videoTransfers = /* @__PURE__ */ new Map();
|
|
@@ -33874,10 +34015,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33874
34015
|
composition.videos.map(async (v) => {
|
|
33875
34016
|
let videoPath = v.src;
|
|
33876
34017
|
if (!videoPath.startsWith("/")) {
|
|
33877
|
-
const fromCompiled =
|
|
34018
|
+
const fromCompiled = existsSync33(join35(compiledDir, videoPath)) ? join35(compiledDir, videoPath) : join35(projectDir, videoPath);
|
|
33878
34019
|
videoPath = fromCompiled;
|
|
33879
34020
|
}
|
|
33880
|
-
if (!
|
|
34021
|
+
if (!existsSync33(videoPath)) return;
|
|
33881
34022
|
const meta = await extractMediaMetadata(videoPath);
|
|
33882
34023
|
if (isHdrColorSpace(meta.colorSpace)) {
|
|
33883
34024
|
nativeHdrVideoIds.add(v.id);
|
|
@@ -33895,10 +34036,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33895
34036
|
composition.images.map(async (img) => {
|
|
33896
34037
|
let imgPath = img.src;
|
|
33897
34038
|
if (!imgPath.startsWith("/")) {
|
|
33898
|
-
const fromCompiled =
|
|
34039
|
+
const fromCompiled = existsSync33(join35(compiledDir, imgPath)) ? join35(compiledDir, imgPath) : join35(projectDir, imgPath);
|
|
33899
34040
|
imgPath = fromCompiled;
|
|
33900
34041
|
}
|
|
33901
|
-
if (!
|
|
34042
|
+
if (!existsSync33(imgPath)) return null;
|
|
33902
34043
|
const meta = await extractMediaMetadata(imgPath);
|
|
33903
34044
|
if (isHdrColorSpace(meta.colorSpace)) {
|
|
33904
34045
|
nativeHdrImageIds.add(img.id);
|
|
@@ -33914,7 +34055,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33914
34055
|
extractionResult = await extractAllVideoFrames(
|
|
33915
34056
|
composition.videos,
|
|
33916
34057
|
projectDir,
|
|
33917
|
-
{ fps: job.config.fps, outputDir:
|
|
34058
|
+
{ fps: job.config.fps, outputDir: join35(workDir, "video-frames") },
|
|
33918
34059
|
abortSignal,
|
|
33919
34060
|
{ extractCacheDir: cfg.extractCacheDir },
|
|
33920
34061
|
compiledDir
|
|
@@ -33972,13 +34113,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33972
34113
|
}
|
|
33973
34114
|
const stage3Start = Date.now();
|
|
33974
34115
|
updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
|
|
33975
|
-
const audioOutputPath =
|
|
34116
|
+
const audioOutputPath = join35(workDir, "audio.aac");
|
|
33976
34117
|
let hasAudio = false;
|
|
33977
34118
|
if (composition.audios.length > 0) {
|
|
33978
34119
|
const audioResult = await processCompositionAudio(
|
|
33979
34120
|
composition.audios,
|
|
33980
34121
|
projectDir,
|
|
33981
|
-
|
|
34122
|
+
join35(workDir, "audio-work"),
|
|
33982
34123
|
audioOutputPath,
|
|
33983
34124
|
job.duration,
|
|
33984
34125
|
abortSignal,
|
|
@@ -33996,14 +34137,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33996
34137
|
if (!fileServer) {
|
|
33997
34138
|
fileServer = await createFileServer2({
|
|
33998
34139
|
projectDir,
|
|
33999
|
-
compiledDir:
|
|
34140
|
+
compiledDir: join35(workDir, "compiled"),
|
|
34000
34141
|
port: 0,
|
|
34001
34142
|
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
34002
34143
|
});
|
|
34003
34144
|
assertNotAborted();
|
|
34004
34145
|
}
|
|
34005
|
-
const framesDir =
|
|
34006
|
-
if (!
|
|
34146
|
+
const framesDir = join35(workDir, "captured-frames");
|
|
34147
|
+
if (!existsSync33(framesDir)) mkdirSync20(framesDir, { recursive: true });
|
|
34007
34148
|
const captureOptions = {
|
|
34008
34149
|
width,
|
|
34009
34150
|
height,
|
|
@@ -34018,7 +34159,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34018
34159
|
const workerCount = calculateOptimalWorkers(totalFrames, job.config.workers, cfg);
|
|
34019
34160
|
const FORMAT_EXT2 = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
|
|
34020
34161
|
const videoExt = FORMAT_EXT2[outputFormat] ?? ".mp4";
|
|
34021
|
-
const videoOnlyPath =
|
|
34162
|
+
const videoOnlyPath = join35(workDir, `video-only${videoExt}`);
|
|
34022
34163
|
const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
|
|
34023
34164
|
const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
|
|
34024
34165
|
const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
|
|
@@ -34040,8 +34181,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34040
34181
|
if (!hdrVideoIds.includes(v.id)) continue;
|
|
34041
34182
|
let srcPath = v.src;
|
|
34042
34183
|
if (!srcPath.startsWith("/")) {
|
|
34043
|
-
const fromCompiled =
|
|
34044
|
-
srcPath =
|
|
34184
|
+
const fromCompiled = join35(compiledDir, srcPath);
|
|
34185
|
+
srcPath = existsSync33(fromCompiled) ? fromCompiled : join35(projectDir, srcPath);
|
|
34045
34186
|
}
|
|
34046
34187
|
hdrVideoSrcPaths.set(v.id, srcPath);
|
|
34047
34188
|
}
|
|
@@ -34171,8 +34312,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34171
34312
|
for (const [videoId, srcPath] of hdrVideoSrcPaths) {
|
|
34172
34313
|
const video = composition.videos.find((v) => v.id === videoId);
|
|
34173
34314
|
if (!video) continue;
|
|
34174
|
-
const frameDir =
|
|
34175
|
-
|
|
34315
|
+
const frameDir = join35(framesDir, `hdr_${videoId}`);
|
|
34316
|
+
mkdirSync20(frameDir, { recursive: true });
|
|
34176
34317
|
const duration = video.end - video.start;
|
|
34177
34318
|
const dims = hdrExtractionDims.get(videoId) ?? { width, height };
|
|
34178
34319
|
const ffmpegArgs = [
|
|
@@ -34191,7 +34332,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34191
34332
|
"-c:v",
|
|
34192
34333
|
"png",
|
|
34193
34334
|
"-y",
|
|
34194
|
-
|
|
34335
|
+
join35(frameDir, "frame_%04d.png")
|
|
34195
34336
|
];
|
|
34196
34337
|
const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
|
|
34197
34338
|
if (!result.success) {
|
|
@@ -34210,7 +34351,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34210
34351
|
const hdrImageBuffers = /* @__PURE__ */ new Map();
|
|
34211
34352
|
for (const [imageId, srcPath] of hdrImageSrcPaths) {
|
|
34212
34353
|
try {
|
|
34213
|
-
const decoded = decodePngToRgb48le(
|
|
34354
|
+
const decoded = decodePngToRgb48le(readFileSync23(srcPath));
|
|
34214
34355
|
const layout2 = hdrExtractionDims.get(imageId);
|
|
34215
34356
|
const fitInfo = hdrImageFitInfo.get(imageId);
|
|
34216
34357
|
if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
|
|
@@ -34259,9 +34400,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34259
34400
|
}
|
|
34260
34401
|
}
|
|
34261
34402
|
const debugDumpEnabled = process.env.KEEP_TEMP === "1";
|
|
34262
|
-
const debugDumpDir = debugDumpEnabled ?
|
|
34263
|
-
if (debugDumpDir && !
|
|
34264
|
-
|
|
34403
|
+
const debugDumpDir = debugDumpEnabled ? join35(framesDir, "debug-composite") : null;
|
|
34404
|
+
if (debugDumpDir && !existsSync33(debugDumpDir)) {
|
|
34405
|
+
mkdirSync20(debugDumpDir, { recursive: true });
|
|
34265
34406
|
}
|
|
34266
34407
|
if (!effectiveHdr) {
|
|
34267
34408
|
throw new Error(
|
|
@@ -34407,11 +34548,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34407
34548
|
i2
|
|
34408
34549
|
);
|
|
34409
34550
|
if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
|
|
34410
|
-
const previewPath =
|
|
34551
|
+
const previewPath = join35(
|
|
34411
34552
|
debugDumpDir,
|
|
34412
34553
|
`frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`
|
|
34413
34554
|
);
|
|
34414
|
-
|
|
34555
|
+
writeFileSync14(previewPath, normalCanvas);
|
|
34415
34556
|
}
|
|
34416
34557
|
hdrEncoder.writeFrame(normalCanvas);
|
|
34417
34558
|
}
|
|
@@ -34754,7 +34895,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34754
34895
|
updateJobStatus(job, "complete", "Render complete", 100, onProgress);
|
|
34755
34896
|
const totalElapsed = Date.now() - pipelineStart;
|
|
34756
34897
|
sampleMemory();
|
|
34757
|
-
const tmpPeakBytes =
|
|
34898
|
+
const tmpPeakBytes = existsSync33(workDir) ? sampleDirectoryBytes(workDir) : 0;
|
|
34758
34899
|
const perfSummary = {
|
|
34759
34900
|
renderId: job.id,
|
|
34760
34901
|
totalElapsedMs: totalElapsed,
|
|
@@ -34779,7 +34920,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34779
34920
|
job.perfSummary = perfSummary;
|
|
34780
34921
|
if (job.config.debug) {
|
|
34781
34922
|
try {
|
|
34782
|
-
|
|
34923
|
+
writeFileSync14(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
|
|
34783
34924
|
} catch (err) {
|
|
34784
34925
|
log2.debug("Failed to write perf summary", {
|
|
34785
34926
|
perfOutputPath,
|
|
@@ -34788,8 +34929,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34788
34929
|
}
|
|
34789
34930
|
}
|
|
34790
34931
|
if (job.config.debug) {
|
|
34791
|
-
if (
|
|
34792
|
-
const debugOutput =
|
|
34932
|
+
if (existsSync33(outputPath)) {
|
|
34933
|
+
const debugOutput = join35(workDir, `output${videoExt}`);
|
|
34793
34934
|
copyFileSync2(outputPath, debugOutput);
|
|
34794
34935
|
}
|
|
34795
34936
|
} else if (process.env.KEEP_TEMP === "1") {
|
|
@@ -34875,7 +35016,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
34875
35016
|
await safeCleanup(
|
|
34876
35017
|
"remove workDir (error)",
|
|
34877
35018
|
() => {
|
|
34878
|
-
if (
|
|
35019
|
+
if (existsSync33(workDir)) rmSync7(workDir, { recursive: true, force: true });
|
|
34879
35020
|
},
|
|
34880
35021
|
log2
|
|
34881
35022
|
);
|
|
@@ -34935,8 +35076,8 @@ var init_config3 = __esm({
|
|
|
34935
35076
|
});
|
|
34936
35077
|
|
|
34937
35078
|
// ../producer/src/services/hyperframeLint.ts
|
|
34938
|
-
import { existsSync as
|
|
34939
|
-
import { resolve as resolve18, join as
|
|
35079
|
+
import { existsSync as existsSync34, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
|
|
35080
|
+
import { resolve as resolve18, join as join36 } from "path";
|
|
34940
35081
|
function isStringRecord(value) {
|
|
34941
35082
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34942
35083
|
return false;
|
|
@@ -34964,7 +35105,7 @@ function pickEntryFile(files, preferredEntryFile) {
|
|
|
34964
35105
|
}
|
|
34965
35106
|
function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
34966
35107
|
const absProjectDir = resolve18(projectDir);
|
|
34967
|
-
if (!
|
|
35108
|
+
if (!existsSync34(absProjectDir) || !statSync10(absProjectDir).isDirectory()) {
|
|
34968
35109
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
34969
35110
|
}
|
|
34970
35111
|
const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
|
|
@@ -34975,16 +35116,16 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
|
34975
35116
|
if (!absoluteEntryPath.startsWith(absProjectDir)) {
|
|
34976
35117
|
return { error: `Entry file must stay inside project directory: ${entryFile}` };
|
|
34977
35118
|
}
|
|
34978
|
-
if (
|
|
35119
|
+
if (existsSync34(absoluteEntryPath) && statSync10(absoluteEntryPath).isFile()) {
|
|
34979
35120
|
return {
|
|
34980
35121
|
entryFile,
|
|
34981
|
-
html:
|
|
35122
|
+
html: readFileSync24(absoluteEntryPath, "utf-8"),
|
|
34982
35123
|
source: "projectDir"
|
|
34983
35124
|
};
|
|
34984
35125
|
}
|
|
34985
35126
|
}
|
|
34986
35127
|
return {
|
|
34987
|
-
error: `No HTML entry file found in project directory: ${
|
|
35128
|
+
error: `No HTML entry file found in project directory: ${join36(absProjectDir, preferredEntryFile || "index.html")}`
|
|
34988
35129
|
};
|
|
34989
35130
|
}
|
|
34990
35131
|
function prepareHyperframeLintBody(body) {
|
|
@@ -35072,15 +35213,15 @@ var init_semaphore = __esm({
|
|
|
35072
35213
|
|
|
35073
35214
|
// ../producer/src/server.ts
|
|
35074
35215
|
import {
|
|
35075
|
-
existsSync as
|
|
35076
|
-
mkdirSync as
|
|
35216
|
+
existsSync as existsSync35,
|
|
35217
|
+
mkdirSync as mkdirSync21,
|
|
35077
35218
|
statSync as statSync11,
|
|
35078
35219
|
mkdtempSync as mkdtempSync2,
|
|
35079
|
-
writeFileSync as
|
|
35220
|
+
writeFileSync as writeFileSync15,
|
|
35080
35221
|
rmSync as rmSync8,
|
|
35081
35222
|
createReadStream
|
|
35082
35223
|
} from "fs";
|
|
35083
|
-
import { resolve as resolve19, dirname as dirname12, join as
|
|
35224
|
+
import { resolve as resolve19, dirname as dirname12, join as join37 } from "path";
|
|
35084
35225
|
import { tmpdir as tmpdir3 } from "os";
|
|
35085
35226
|
import { parseArgs as parseArgs2 } from "util";
|
|
35086
35227
|
import crypto2 from "crypto";
|
|
@@ -35103,11 +35244,11 @@ async function prepareRenderBody(body) {
|
|
|
35103
35244
|
const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
|
|
35104
35245
|
if (projectDir) {
|
|
35105
35246
|
const absProjectDir = resolve19(projectDir);
|
|
35106
|
-
if (!
|
|
35247
|
+
if (!existsSync35(absProjectDir) || !statSync11(absProjectDir).isDirectory()) {
|
|
35107
35248
|
return { error: `Project directory not found: ${absProjectDir}` };
|
|
35108
35249
|
}
|
|
35109
35250
|
const entry = options.entryFile || "index.html";
|
|
35110
|
-
if (!
|
|
35251
|
+
if (!existsSync35(resolve19(absProjectDir, entry))) {
|
|
35111
35252
|
return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
|
|
35112
35253
|
}
|
|
35113
35254
|
return { prepared: { input: { projectDir: absProjectDir, ...options } } };
|
|
@@ -35132,8 +35273,8 @@ async function prepareRenderBody(body) {
|
|
|
35132
35273
|
}
|
|
35133
35274
|
}
|
|
35134
35275
|
const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir3();
|
|
35135
|
-
const tempProjectDir = mkdtempSync2(
|
|
35136
|
-
|
|
35276
|
+
const tempProjectDir = mkdtempSync2(join37(tempRoot, "producer-project-"));
|
|
35277
|
+
writeFileSync15(join37(tempProjectDir, "index.html"), htmlContent, "utf-8");
|
|
35137
35278
|
return {
|
|
35138
35279
|
prepared: {
|
|
35139
35280
|
input: {
|
|
@@ -35256,7 +35397,7 @@ function createRenderHandlers(options = {}) {
|
|
|
35256
35397
|
log2
|
|
35257
35398
|
);
|
|
35258
35399
|
const outputDir = dirname12(absoluteOutputPath);
|
|
35259
|
-
if (!
|
|
35400
|
+
if (!existsSync35(outputDir)) mkdirSync21(outputDir, { recursive: true });
|
|
35260
35401
|
const release2 = await renderSemaphore.acquire();
|
|
35261
35402
|
log2.info("render started", {
|
|
35262
35403
|
requestId,
|
|
@@ -35283,7 +35424,7 @@ function createRenderHandlers(options = {}) {
|
|
|
35283
35424
|
log2.info(`render progress ${pct}%`, { requestId, stage: j2.currentStage, message });
|
|
35284
35425
|
}
|
|
35285
35426
|
});
|
|
35286
|
-
const fileSize =
|
|
35427
|
+
const fileSize = existsSync35(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
|
|
35287
35428
|
const durationMs = Date.now() - t0;
|
|
35288
35429
|
const outputToken = store.register(absoluteOutputPath);
|
|
35289
35430
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
@@ -35367,7 +35508,7 @@ function createRenderHandlers(options = {}) {
|
|
|
35367
35508
|
log2
|
|
35368
35509
|
);
|
|
35369
35510
|
const outputDir = dirname12(absoluteOutputPath);
|
|
35370
|
-
if (!
|
|
35511
|
+
if (!existsSync35(outputDir)) mkdirSync21(outputDir, { recursive: true });
|
|
35371
35512
|
log2.info("render-stream started", { requestId, projectDir: input.projectDir });
|
|
35372
35513
|
const job = createRenderJob({
|
|
35373
35514
|
fps: input.fps,
|
|
@@ -35412,7 +35553,7 @@ function createRenderHandlers(options = {}) {
|
|
|
35412
35553
|
},
|
|
35413
35554
|
abortController.signal
|
|
35414
35555
|
);
|
|
35415
|
-
const fileSize =
|
|
35556
|
+
const fileSize = existsSync35(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
|
|
35416
35557
|
const outputToken = store.register(absoluteOutputPath);
|
|
35417
35558
|
const outputUrl = `${outputUrlPrefix}/${outputToken}`;
|
|
35418
35559
|
log2.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
|
|
@@ -35471,7 +35612,7 @@ function createRenderHandlers(options = {}) {
|
|
|
35471
35612
|
if (!artifact) {
|
|
35472
35613
|
return c2.json({ success: false, error: "Output artifact not found or expired" }, 404);
|
|
35473
35614
|
}
|
|
35474
|
-
if (!
|
|
35615
|
+
if (!existsSync35(artifact.path)) {
|
|
35475
35616
|
store.delete(token);
|
|
35476
35617
|
return c2.json({ success: false, error: "Output artifact file missing" }, 404);
|
|
35477
35618
|
}
|
|
@@ -35609,20 +35750,20 @@ __export(studioServer_exports, {
|
|
|
35609
35750
|
});
|
|
35610
35751
|
import { Hono as Hono5 } from "hono";
|
|
35611
35752
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
35612
|
-
import { existsSync as
|
|
35613
|
-
import { resolve as resolve20, join as
|
|
35753
|
+
import { existsSync as existsSync36, readFileSync as readFileSync25, writeFileSync as writeFileSync16, statSync as statSync12 } from "fs";
|
|
35754
|
+
import { resolve as resolve20, join as join38, basename as basename3 } from "path";
|
|
35614
35755
|
function resolveDistDir() {
|
|
35615
35756
|
return resolveStudioBundle().dir;
|
|
35616
35757
|
}
|
|
35617
35758
|
function resolveStudioBundle() {
|
|
35618
35759
|
const builtPath = resolve20(__dirname, "studio");
|
|
35619
35760
|
const builtIndex = resolve20(builtPath, "index.html");
|
|
35620
|
-
if (
|
|
35761
|
+
if (existsSync36(builtIndex)) {
|
|
35621
35762
|
return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
|
|
35622
35763
|
}
|
|
35623
35764
|
const devPath = resolve20(__dirname, "..", "..", "..", "studio", "dist");
|
|
35624
35765
|
const devIndex = resolve20(devPath, "index.html");
|
|
35625
|
-
if (
|
|
35766
|
+
if (existsSync36(devIndex)) {
|
|
35626
35767
|
return {
|
|
35627
35768
|
dir: devPath,
|
|
35628
35769
|
indexPath: devIndex,
|
|
@@ -35639,9 +35780,9 @@ function resolveStudioBundle() {
|
|
|
35639
35780
|
}
|
|
35640
35781
|
function resolveRuntimePath() {
|
|
35641
35782
|
const builtPath = resolve20(__dirname, "hyperframe-runtime.js");
|
|
35642
|
-
if (
|
|
35783
|
+
if (existsSync36(builtPath)) return builtPath;
|
|
35643
35784
|
const iifePath = resolve20(__dirname, "hyperframe.runtime.iife.js");
|
|
35644
|
-
if (
|
|
35785
|
+
if (existsSync36(iifePath)) return iifePath;
|
|
35645
35786
|
const devPath = resolve20(
|
|
35646
35787
|
__dirname,
|
|
35647
35788
|
"..",
|
|
@@ -35651,7 +35792,7 @@ function resolveRuntimePath() {
|
|
|
35651
35792
|
"dist",
|
|
35652
35793
|
"hyperframe.runtime.iife.js"
|
|
35653
35794
|
);
|
|
35654
|
-
if (
|
|
35795
|
+
if (existsSync36(devPath)) return devPath;
|
|
35655
35796
|
return builtPath;
|
|
35656
35797
|
}
|
|
35657
35798
|
async function getThumbnailBrowser() {
|
|
@@ -35713,7 +35854,7 @@ function createStudioServer(options) {
|
|
|
35713
35854
|
return lintHyperframeHtml2(html, opts);
|
|
35714
35855
|
},
|
|
35715
35856
|
runtimeUrl: "/api/runtime.js",
|
|
35716
|
-
rendersDir: () =>
|
|
35857
|
+
rendersDir: () => join38(projectDir, "renders"),
|
|
35717
35858
|
startRender(opts) {
|
|
35718
35859
|
const state = {
|
|
35719
35860
|
id: opts.jobId,
|
|
@@ -35746,7 +35887,7 @@ function createStudioServer(options) {
|
|
|
35746
35887
|
state.status = "complete";
|
|
35747
35888
|
state.progress = 100;
|
|
35748
35889
|
const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
|
|
35749
|
-
|
|
35890
|
+
writeFileSync16(
|
|
35750
35891
|
metaPath,
|
|
35751
35892
|
JSON.stringify({ status: "complete", durationMs: Date.now() - startTime })
|
|
35752
35893
|
);
|
|
@@ -35755,7 +35896,7 @@ function createStudioServer(options) {
|
|
|
35755
35896
|
state.error = err instanceof Error ? err.message : String(err);
|
|
35756
35897
|
try {
|
|
35757
35898
|
const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
|
|
35758
|
-
|
|
35899
|
+
writeFileSync16(metaPath, JSON.stringify({ status: "failed" }));
|
|
35759
35900
|
} catch {
|
|
35760
35901
|
}
|
|
35761
35902
|
}
|
|
@@ -35828,7 +35969,7 @@ function createStudioServer(options) {
|
|
|
35828
35969
|
});
|
|
35829
35970
|
app.get("/api/runtime.js", (c2) => {
|
|
35830
35971
|
const serve4 = async () => {
|
|
35831
|
-
const runtimeSource = await loadRuntimeSource() ?? (
|
|
35972
|
+
const runtimeSource = await loadRuntimeSource() ?? (existsSync36(runtimePath) ? readFileSync25(runtimePath, "utf-8") : null);
|
|
35832
35973
|
if (!runtimeSource) return c2.text("runtime not available", 404);
|
|
35833
35974
|
return c2.body(runtimeSource, 200, {
|
|
35834
35975
|
"Content-Type": "text/javascript",
|
|
@@ -35864,23 +36005,23 @@ function createStudioServer(options) {
|
|
|
35864
36005
|
});
|
|
35865
36006
|
app.get("/assets/*", (c2) => {
|
|
35866
36007
|
const filePath = resolve20(studioDir, c2.req.path.slice(1));
|
|
35867
|
-
if (!
|
|
35868
|
-
const content =
|
|
36008
|
+
if (!existsSync36(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
|
|
36009
|
+
const content = readFileSync25(filePath);
|
|
35869
36010
|
return new Response(content, {
|
|
35870
36011
|
headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
|
|
35871
36012
|
});
|
|
35872
36013
|
});
|
|
35873
36014
|
app.get("/icons/*", (c2) => {
|
|
35874
36015
|
const filePath = resolve20(studioDir, c2.req.path.slice(1));
|
|
35875
|
-
if (!
|
|
35876
|
-
const content =
|
|
36016
|
+
if (!existsSync36(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
|
|
36017
|
+
const content = readFileSync25(filePath);
|
|
35877
36018
|
return new Response(content, {
|
|
35878
36019
|
headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
|
|
35879
36020
|
});
|
|
35880
36021
|
});
|
|
35881
36022
|
app.get("*", (c2) => {
|
|
35882
36023
|
const indexPath = resolve20(studioDir, "index.html");
|
|
35883
|
-
if (!
|
|
36024
|
+
if (!existsSync36(indexPath)) {
|
|
35884
36025
|
return c2.html(
|
|
35885
36026
|
`<!doctype html>
|
|
35886
36027
|
<html>
|
|
@@ -35936,7 +36077,7 @@ function createStudioServer(options) {
|
|
|
35936
36077
|
500
|
|
35937
36078
|
);
|
|
35938
36079
|
}
|
|
35939
|
-
return c2.html(
|
|
36080
|
+
return c2.html(readFileSync25(indexPath, "utf-8"));
|
|
35940
36081
|
});
|
|
35941
36082
|
return { app, watcher };
|
|
35942
36083
|
}
|
|
@@ -35959,21 +36100,21 @@ __export(preview_exports, {
|
|
|
35959
36100
|
default: () => preview_default,
|
|
35960
36101
|
examples: () => examples
|
|
35961
36102
|
});
|
|
35962
|
-
import { spawn as
|
|
35963
|
-
import { existsSync as
|
|
35964
|
-
import { resolve as resolve21, dirname as dirname13, basename as basename4, join as
|
|
36103
|
+
import { spawn as spawn9 } from "child_process";
|
|
36104
|
+
import { existsSync as existsSync37, lstatSync, symlinkSync, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync22 } from "fs";
|
|
36105
|
+
import { resolve as resolve21, dirname as dirname13, basename as basename4, join as join39 } from "path";
|
|
35965
36106
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
35966
36107
|
import { createRequire } from "module";
|
|
35967
36108
|
async function runDevMode(dir, projectName) {
|
|
35968
36109
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
35969
36110
|
const repoRoot = resolve21(dirname13(thisFile), "..", "..", "..", "..");
|
|
35970
|
-
const projectsDir =
|
|
36111
|
+
const projectsDir = join39(repoRoot, "packages", "studio", "data", "projects");
|
|
35971
36112
|
const pName = projectName ?? basename4(dir);
|
|
35972
|
-
const symlinkPath =
|
|
35973
|
-
|
|
36113
|
+
const symlinkPath = join39(projectsDir, pName);
|
|
36114
|
+
mkdirSync22(projectsDir, { recursive: true });
|
|
35974
36115
|
let createdSymlink = false;
|
|
35975
36116
|
if (dir !== symlinkPath) {
|
|
35976
|
-
if (
|
|
36117
|
+
if (existsSync37(symlinkPath)) {
|
|
35977
36118
|
try {
|
|
35978
36119
|
const stat3 = lstatSync(symlinkPath);
|
|
35979
36120
|
if (stat3.isSymbolicLink()) {
|
|
@@ -35985,7 +36126,7 @@ async function runDevMode(dir, projectName) {
|
|
|
35985
36126
|
} catch {
|
|
35986
36127
|
}
|
|
35987
36128
|
}
|
|
35988
|
-
if (!
|
|
36129
|
+
if (!existsSync37(symlinkPath)) {
|
|
35989
36130
|
symlinkSync(dir, symlinkPath, "dir");
|
|
35990
36131
|
createdSymlink = true;
|
|
35991
36132
|
}
|
|
@@ -35993,8 +36134,8 @@ async function runDevMode(dir, projectName) {
|
|
|
35993
36134
|
Wt2(c.bold("hyperframes preview"));
|
|
35994
36135
|
const s2 = be();
|
|
35995
36136
|
s2.start("Starting studio...");
|
|
35996
|
-
const studioPkgDir =
|
|
35997
|
-
const child =
|
|
36137
|
+
const studioPkgDir = join39(repoRoot, "packages", "studio");
|
|
36138
|
+
const child = spawn9("pnpm", ["exec", "vite"], {
|
|
35998
36139
|
cwd: studioPkgDir,
|
|
35999
36140
|
stdio: ["ignore", "pipe", "pipe"]
|
|
36000
36141
|
});
|
|
@@ -36027,7 +36168,7 @@ async function runDevMode(dir, projectName) {
|
|
|
36027
36168
|
if (createdSymlink) {
|
|
36028
36169
|
process.on("exit", () => {
|
|
36029
36170
|
try {
|
|
36030
|
-
if (
|
|
36171
|
+
if (existsSync37(symlinkPath)) unlinkSync5(symlinkPath);
|
|
36031
36172
|
} catch {
|
|
36032
36173
|
}
|
|
36033
36174
|
});
|
|
@@ -36038,7 +36179,7 @@ async function runDevMode(dir, projectName) {
|
|
|
36038
36179
|
}
|
|
36039
36180
|
function hasLocalStudio(dir) {
|
|
36040
36181
|
try {
|
|
36041
|
-
const req = createRequire(
|
|
36182
|
+
const req = createRequire(join39(dir, "package.json"));
|
|
36042
36183
|
req.resolve("@hyperframes/studio/package.json");
|
|
36043
36184
|
return true;
|
|
36044
36185
|
} catch {
|
|
@@ -36046,20 +36187,20 @@ function hasLocalStudio(dir) {
|
|
|
36046
36187
|
}
|
|
36047
36188
|
}
|
|
36048
36189
|
async function runLocalStudioMode(dir, projectName) {
|
|
36049
|
-
const req = createRequire(
|
|
36190
|
+
const req = createRequire(join39(dir, "package.json"));
|
|
36050
36191
|
const studioPkgPath = dirname13(req.resolve("@hyperframes/studio/package.json"));
|
|
36051
36192
|
const pName = projectName ?? basename4(dir);
|
|
36052
|
-
const projectsDir =
|
|
36053
|
-
const symlinkPath =
|
|
36054
|
-
|
|
36193
|
+
const projectsDir = join39(studioPkgPath, "data", "projects");
|
|
36194
|
+
const symlinkPath = join39(projectsDir, pName);
|
|
36195
|
+
mkdirSync22(projectsDir, { recursive: true });
|
|
36055
36196
|
let createdSymlink = false;
|
|
36056
36197
|
if (dir !== symlinkPath) {
|
|
36057
|
-
if (
|
|
36198
|
+
if (existsSync37(symlinkPath) && lstatSync(symlinkPath).isSymbolicLink()) {
|
|
36058
36199
|
if (resolve21(readlinkSync(symlinkPath)) !== resolve21(dir)) {
|
|
36059
36200
|
unlinkSync5(symlinkPath);
|
|
36060
36201
|
}
|
|
36061
36202
|
}
|
|
36062
|
-
if (!
|
|
36203
|
+
if (!existsSync37(symlinkPath)) {
|
|
36063
36204
|
symlinkSync(dir, symlinkPath, "dir");
|
|
36064
36205
|
createdSymlink = true;
|
|
36065
36206
|
}
|
|
@@ -36067,7 +36208,7 @@ async function runLocalStudioMode(dir, projectName) {
|
|
|
36067
36208
|
Wt2(c.bold("hyperframes preview") + c.dim(" (local studio)"));
|
|
36068
36209
|
const s2 = be();
|
|
36069
36210
|
s2.start("Starting studio...");
|
|
36070
|
-
const child =
|
|
36211
|
+
const child = spawn9("npx", ["vite"], {
|
|
36071
36212
|
cwd: studioPkgPath,
|
|
36072
36213
|
stdio: ["ignore", "pipe", "pipe"]
|
|
36073
36214
|
});
|
|
@@ -36098,7 +36239,7 @@ async function runLocalStudioMode(dir, projectName) {
|
|
|
36098
36239
|
if (createdSymlink) {
|
|
36099
36240
|
process.on("exit", () => {
|
|
36100
36241
|
try {
|
|
36101
|
-
if (
|
|
36242
|
+
if (existsSync37(symlinkPath)) unlinkSync5(symlinkPath);
|
|
36102
36243
|
} catch {
|
|
36103
36244
|
}
|
|
36104
36245
|
});
|
|
@@ -36274,8 +36415,8 @@ var init_preview2 = __esm({
|
|
|
36274
36415
|
const dir = resolve21(rawArg ?? ".");
|
|
36275
36416
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
36276
36417
|
const projectName = isImplicitCwd ? basename4(process.env.PWD ?? dir) : basename4(dir);
|
|
36277
|
-
const indexPath =
|
|
36278
|
-
if (
|
|
36418
|
+
const indexPath = join39(dir, "index.html");
|
|
36419
|
+
if (existsSync37(indexPath)) {
|
|
36279
36420
|
const project = { dir, name: projectName, indexPath };
|
|
36280
36421
|
const lintResult = lintProject(project);
|
|
36281
36422
|
if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
|
|
@@ -36304,17 +36445,17 @@ __export(init_exports, {
|
|
|
36304
36445
|
examples: () => examples2
|
|
36305
36446
|
});
|
|
36306
36447
|
import {
|
|
36307
|
-
existsSync as
|
|
36308
|
-
mkdirSync as
|
|
36448
|
+
existsSync as existsSync38,
|
|
36449
|
+
mkdirSync as mkdirSync23,
|
|
36309
36450
|
copyFileSync as copyFileSync3,
|
|
36310
36451
|
cpSync,
|
|
36311
|
-
writeFileSync as
|
|
36312
|
-
readFileSync as
|
|
36452
|
+
writeFileSync as writeFileSync17,
|
|
36453
|
+
readFileSync as readFileSync26,
|
|
36313
36454
|
readdirSync as readdirSync14
|
|
36314
36455
|
} from "fs";
|
|
36315
|
-
import { resolve as resolve22, basename as basename5, join as
|
|
36456
|
+
import { resolve as resolve22, basename as basename5, join as join40, dirname as dirname14 } from "path";
|
|
36316
36457
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
36317
|
-
import { execFileSync as execFileSync4, spawn as
|
|
36458
|
+
import { execFileSync as execFileSync4, spawn as spawn10 } from "child_process";
|
|
36318
36459
|
function probeVideo(filePath) {
|
|
36319
36460
|
try {
|
|
36320
36461
|
const raw = execFileSync4(
|
|
@@ -36356,7 +36497,7 @@ function isWebCompatible(codec) {
|
|
|
36356
36497
|
}
|
|
36357
36498
|
function transcodeToMp4(inputPath, outputPath) {
|
|
36358
36499
|
return new Promise((resolvePromise) => {
|
|
36359
|
-
const child =
|
|
36500
|
+
const child = spawn10(
|
|
36360
36501
|
"ffmpeg",
|
|
36361
36502
|
[
|
|
36362
36503
|
"-i",
|
|
@@ -36384,7 +36525,7 @@ function resolveAssetDir(devSegments, builtSegments) {
|
|
|
36384
36525
|
const base = dirname14(fileURLToPath5(import.meta.url));
|
|
36385
36526
|
const devPath = resolve22(base, ...devSegments);
|
|
36386
36527
|
const builtPath = resolve22(base, ...builtSegments);
|
|
36387
|
-
return
|
|
36528
|
+
return existsSync38(devPath) ? devPath : builtPath;
|
|
36388
36529
|
}
|
|
36389
36530
|
function getStaticTemplateDir(templateId) {
|
|
36390
36531
|
return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
|
|
@@ -36393,9 +36534,9 @@ function getSharedTemplateDir() {
|
|
|
36393
36534
|
return resolveAssetDir(["..", "templates", "_shared"], ["templates", "_shared"]);
|
|
36394
36535
|
}
|
|
36395
36536
|
function patchVideoSrc(dir, videoFilename, durationSeconds) {
|
|
36396
|
-
const htmlFiles = readdirSync14(dir, { withFileTypes: true, recursive: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".html")).map((e2) =>
|
|
36537
|
+
const htmlFiles = readdirSync14(dir, { withFileTypes: true, recursive: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".html")).map((e2) => join40(e2.parentPath ?? e2.path, e2.name));
|
|
36397
36538
|
for (const file of htmlFiles) {
|
|
36398
|
-
let content =
|
|
36539
|
+
let content = readFileSync26(file, "utf-8");
|
|
36399
36540
|
if (videoFilename) {
|
|
36400
36541
|
content = content.replaceAll("__VIDEO_SRC__", videoFilename);
|
|
36401
36542
|
} else {
|
|
@@ -36406,7 +36547,7 @@ function patchVideoSrc(dir, videoFilename, durationSeconds) {
|
|
|
36406
36547
|
}
|
|
36407
36548
|
const dur = durationSeconds ? String(Math.round(durationSeconds * 100) / 100) : "10";
|
|
36408
36549
|
content = content.replaceAll("__VIDEO_DURATION__", dur);
|
|
36409
|
-
|
|
36550
|
+
writeFileSync17(file, content, "utf-8");
|
|
36410
36551
|
}
|
|
36411
36552
|
}
|
|
36412
36553
|
async function patchTranscript(dir, transcriptPath) {
|
|
@@ -36498,15 +36639,15 @@ async function handleVideoFile(videoPath, destDir, interactive) {
|
|
|
36498
36639
|
return { meta, localVideoName };
|
|
36499
36640
|
}
|
|
36500
36641
|
async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds) {
|
|
36501
|
-
|
|
36642
|
+
mkdirSync23(destDir, { recursive: true });
|
|
36502
36643
|
const templateDir = getStaticTemplateDir(templateId);
|
|
36503
|
-
if (
|
|
36644
|
+
if (existsSync38(templateDir)) {
|
|
36504
36645
|
cpSync(templateDir, destDir, { recursive: true });
|
|
36505
36646
|
} else {
|
|
36506
36647
|
await fetchRemoteTemplate(templateId, destDir);
|
|
36507
36648
|
}
|
|
36508
36649
|
patchVideoSrc(destDir, localVideoName, durationSeconds);
|
|
36509
|
-
|
|
36650
|
+
writeFileSync17(
|
|
36510
36651
|
resolve22(destDir, "meta.json"),
|
|
36511
36652
|
JSON.stringify(
|
|
36512
36653
|
{
|
|
@@ -36519,14 +36660,14 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
|
|
|
36519
36660
|
),
|
|
36520
36661
|
"utf-8"
|
|
36521
36662
|
);
|
|
36522
|
-
if (!
|
|
36663
|
+
if (!existsSync38(resolve22(destDir, "hyperframes.json"))) {
|
|
36523
36664
|
const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
|
|
36524
36665
|
writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
|
|
36525
36666
|
}
|
|
36526
36667
|
const sharedDir = getSharedTemplateDir();
|
|
36527
|
-
if (
|
|
36668
|
+
if (existsSync38(sharedDir)) {
|
|
36528
36669
|
for (const entry of readdirSync14(sharedDir, { withFileTypes: true })) {
|
|
36529
|
-
const src =
|
|
36670
|
+
const src = join40(sharedDir, entry.name);
|
|
36530
36671
|
const dest = resolve22(destDir, entry.name);
|
|
36531
36672
|
if (entry.isFile() || entry.isSymbolicLink()) {
|
|
36532
36673
|
copyFileSync3(src, dest);
|
|
@@ -36640,11 +36781,11 @@ var init_init = __esm({
|
|
|
36640
36781
|
const templateId2 = exampleFlag ?? "blank";
|
|
36641
36782
|
const name2 = args.name ?? "my-video";
|
|
36642
36783
|
const destDir2 = resolve22(name2);
|
|
36643
|
-
if (
|
|
36784
|
+
if (existsSync38(destDir2) && readdirSync14(destDir2).length > 0) {
|
|
36644
36785
|
console.error(c.error(`Directory already exists and is not empty: ${name2}`));
|
|
36645
36786
|
process.exit(1);
|
|
36646
36787
|
}
|
|
36647
|
-
|
|
36788
|
+
mkdirSync23(destDir2, { recursive: true });
|
|
36648
36789
|
let localVideoName2;
|
|
36649
36790
|
let videoDuration2;
|
|
36650
36791
|
let sourceFilePath2;
|
|
@@ -36654,7 +36795,7 @@ var init_init = __esm({
|
|
|
36654
36795
|
}
|
|
36655
36796
|
if (videoFlag) {
|
|
36656
36797
|
const videoPath = resolve22(videoFlag);
|
|
36657
|
-
if (!
|
|
36798
|
+
if (!existsSync38(videoPath)) {
|
|
36658
36799
|
console.error(c.error(`Video file not found: ${videoFlag}`));
|
|
36659
36800
|
process.exit(1);
|
|
36660
36801
|
}
|
|
@@ -36668,7 +36809,7 @@ var init_init = __esm({
|
|
|
36668
36809
|
}
|
|
36669
36810
|
if (audioFlag) {
|
|
36670
36811
|
const audioPath = resolve22(audioFlag);
|
|
36671
|
-
if (!
|
|
36812
|
+
if (!existsSync38(audioPath)) {
|
|
36672
36813
|
console.error(c.error(`Audio file not found: ${audioFlag}`));
|
|
36673
36814
|
process.exit(1);
|
|
36674
36815
|
}
|
|
@@ -36714,7 +36855,7 @@ var init_init = __esm({
|
|
|
36714
36855
|
}
|
|
36715
36856
|
trackInitTemplate(templateId2);
|
|
36716
36857
|
const transcriptFile2 = resolve22(destDir2, "transcript.json");
|
|
36717
|
-
if (
|
|
36858
|
+
if (existsSync38(transcriptFile2)) {
|
|
36718
36859
|
await patchTranscript(destDir2, transcriptFile2);
|
|
36719
36860
|
}
|
|
36720
36861
|
console.log(c.success(`Created ${c.accent(name2 + "/")}`));
|
|
@@ -36766,7 +36907,7 @@ var init_init = __esm({
|
|
|
36766
36907
|
name = nameResult;
|
|
36767
36908
|
}
|
|
36768
36909
|
const destDir = resolve22(name);
|
|
36769
|
-
if (
|
|
36910
|
+
if (existsSync38(destDir) && readdirSync14(destDir).length > 0) {
|
|
36770
36911
|
const overwrite = await Rt({
|
|
36771
36912
|
message: `Directory ${c.accent(name)} already exists and is not empty. Overwrite?`,
|
|
36772
36913
|
initialValue: false
|
|
@@ -36781,24 +36922,24 @@ var init_init = __esm({
|
|
|
36781
36922
|
let videoDuration;
|
|
36782
36923
|
if (videoFlag) {
|
|
36783
36924
|
const videoPath = resolve22(videoFlag);
|
|
36784
|
-
if (!
|
|
36925
|
+
if (!existsSync38(videoPath)) {
|
|
36785
36926
|
R2.error(`File not found: ${videoFlag}`);
|
|
36786
36927
|
Nt("Setup cancelled.");
|
|
36787
36928
|
process.exit(1);
|
|
36788
36929
|
}
|
|
36789
|
-
|
|
36930
|
+
mkdirSync23(destDir, { recursive: true });
|
|
36790
36931
|
sourceFilePath = videoPath;
|
|
36791
36932
|
const result = await handleVideoFile(videoPath, destDir, true);
|
|
36792
36933
|
localVideoName = result.localVideoName;
|
|
36793
36934
|
videoDuration = result.meta.durationSeconds;
|
|
36794
36935
|
} else if (audioFlag) {
|
|
36795
36936
|
const audioPath = resolve22(audioFlag);
|
|
36796
|
-
if (!
|
|
36937
|
+
if (!existsSync38(audioPath)) {
|
|
36797
36938
|
R2.error(`File not found: ${audioFlag}`);
|
|
36798
36939
|
Nt("Setup cancelled.");
|
|
36799
36940
|
process.exit(1);
|
|
36800
36941
|
}
|
|
36801
|
-
|
|
36942
|
+
mkdirSync23(destDir, { recursive: true });
|
|
36802
36943
|
sourceFilePath = audioPath;
|
|
36803
36944
|
copyFileSync3(audioPath, resolve22(destDir, basename5(audioPath)));
|
|
36804
36945
|
R2.info(`Audio copied to ${c.accent(basename5(audioPath))}`);
|
|
@@ -36886,7 +37027,7 @@ ${c.dim("Use --example blank for offline use.")}`
|
|
|
36886
37027
|
}
|
|
36887
37028
|
trackInitTemplate(templateId);
|
|
36888
37029
|
const transcriptFile = resolve22(destDir, "transcript.json");
|
|
36889
|
-
if (
|
|
37030
|
+
if (existsSync38(transcriptFile)) {
|
|
36890
37031
|
await patchTranscript(destDir, transcriptFile);
|
|
36891
37032
|
}
|
|
36892
37033
|
const files = readdirSync14(destDir);
|
|
@@ -36972,7 +37113,7 @@ __export(add_exports, {
|
|
|
36972
37113
|
remapTarget: () => remapTarget,
|
|
36973
37114
|
runAdd: () => runAdd
|
|
36974
37115
|
});
|
|
36975
|
-
import { existsSync as
|
|
37116
|
+
import { existsSync as existsSync39 } from "fs";
|
|
36976
37117
|
import { resolve as resolve23, relative as relative3 } from "path";
|
|
36977
37118
|
function remapTarget(item, originalTarget, paths) {
|
|
36978
37119
|
if (item.type === "hyperframes:block") {
|
|
@@ -36998,8 +37139,8 @@ function buildSnippet(item, relativeTarget) {
|
|
|
36998
37139
|
async function runAdd(opts) {
|
|
36999
37140
|
const projectDir = resolve23(opts.projectDir);
|
|
37000
37141
|
let config = loadProjectConfig(projectDir);
|
|
37001
|
-
const hasConfig =
|
|
37002
|
-
if (!hasConfig &&
|
|
37142
|
+
const hasConfig = existsSync39(projectConfigPath(projectDir));
|
|
37143
|
+
if (!hasConfig && existsSync39(resolve23(projectDir, "index.html"))) {
|
|
37003
37144
|
writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
|
|
37004
37145
|
config = DEFAULT_PROJECT_CONFIG;
|
|
37005
37146
|
}
|
|
@@ -37098,10 +37239,10 @@ var init_add = __esm({
|
|
|
37098
37239
|
const projectDir = resolve23(args.dir ?? process.cwd());
|
|
37099
37240
|
const json = args.json === true;
|
|
37100
37241
|
const skipClipboard = args["no-clipboard"] === true;
|
|
37101
|
-
const hasConfigBefore =
|
|
37242
|
+
const hasConfigBefore = existsSync39(projectConfigPath(projectDir));
|
|
37102
37243
|
try {
|
|
37103
37244
|
const result = await runAdd({ name: args.name, projectDir, skipClipboard });
|
|
37104
|
-
const wroteConfig = !hasConfigBefore &&
|
|
37245
|
+
const wroteConfig = !hasConfigBefore && existsSync39(projectConfigPath(projectDir));
|
|
37105
37246
|
if (json) {
|
|
37106
37247
|
console.log(JSON.stringify(result));
|
|
37107
37248
|
return;
|
|
@@ -37311,17 +37452,17 @@ var init_format = __esm({
|
|
|
37311
37452
|
});
|
|
37312
37453
|
|
|
37313
37454
|
// src/utils/project.ts
|
|
37314
|
-
import { existsSync as
|
|
37455
|
+
import { existsSync as existsSync40, statSync as statSync13 } from "fs";
|
|
37315
37456
|
import { resolve as resolve25, basename as basename6 } from "path";
|
|
37316
37457
|
function resolveProject(dirArg) {
|
|
37317
37458
|
const dir = resolve25(dirArg ?? ".");
|
|
37318
37459
|
const name = basename6(dir);
|
|
37319
37460
|
const indexPath = resolve25(dir, "index.html");
|
|
37320
|
-
if (!
|
|
37461
|
+
if (!existsSync40(dir) || !statSync13(dir).isDirectory()) {
|
|
37321
37462
|
errorBox("Not a directory: " + dir);
|
|
37322
37463
|
process.exit(1);
|
|
37323
37464
|
}
|
|
37324
|
-
if (!
|
|
37465
|
+
if (!existsSync40(indexPath)) {
|
|
37325
37466
|
errorBox(
|
|
37326
37467
|
"No composition found in " + dir,
|
|
37327
37468
|
"No index.html file found.",
|
|
@@ -37344,7 +37485,7 @@ __export(play_exports, {
|
|
|
37344
37485
|
default: () => play_default,
|
|
37345
37486
|
examples: () => examples5
|
|
37346
37487
|
});
|
|
37347
|
-
import { existsSync as
|
|
37488
|
+
import { existsSync as existsSync41, readFileSync as readFileSync27 } from "fs";
|
|
37348
37489
|
import { resolve as resolve26, dirname as dirname15 } from "path";
|
|
37349
37490
|
function commandDir() {
|
|
37350
37491
|
return dirname15(new URL(import.meta.url).pathname);
|
|
@@ -37359,7 +37500,7 @@ function resolveRuntimePath2() {
|
|
|
37359
37500
|
resolve26(d, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
|
|
37360
37501
|
];
|
|
37361
37502
|
for (const p of candidates) {
|
|
37362
|
-
if (
|
|
37503
|
+
if (existsSync41(p)) return p;
|
|
37363
37504
|
}
|
|
37364
37505
|
return null;
|
|
37365
37506
|
}
|
|
@@ -37373,7 +37514,7 @@ function resolvePlayerPath() {
|
|
|
37373
37514
|
resolve26(d, "..", "hyperframes-player.global.js")
|
|
37374
37515
|
];
|
|
37375
37516
|
for (const p of candidates) {
|
|
37376
|
-
if (
|
|
37517
|
+
if (existsSync41(p)) return p;
|
|
37377
37518
|
}
|
|
37378
37519
|
return null;
|
|
37379
37520
|
}
|
|
@@ -37460,13 +37601,13 @@ var init_play = __esm({
|
|
|
37460
37601
|
const { createAdaptorServer } = await import("@hono/node-server");
|
|
37461
37602
|
const app = new Hono6();
|
|
37462
37603
|
app.get("/player.js", (ctx) => {
|
|
37463
|
-
return ctx.body(
|
|
37604
|
+
return ctx.body(readFileSync27(playerPath, "utf-8"), 200, {
|
|
37464
37605
|
"Content-Type": "application/javascript",
|
|
37465
37606
|
"Cache-Control": "no-cache"
|
|
37466
37607
|
});
|
|
37467
37608
|
});
|
|
37468
37609
|
app.get("/runtime.js", (ctx) => {
|
|
37469
|
-
return ctx.body(
|
|
37610
|
+
return ctx.body(readFileSync27(runtimePath, "utf-8"), 200, {
|
|
37470
37611
|
"Content-Type": "application/javascript",
|
|
37471
37612
|
"Cache-Control": "no-cache"
|
|
37472
37613
|
});
|
|
@@ -37475,8 +37616,8 @@ var init_play = __esm({
|
|
|
37475
37616
|
const reqPath = ctx.req.path.replace("/composition/", "");
|
|
37476
37617
|
const filePath = resolve26(project.dir, reqPath);
|
|
37477
37618
|
if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
|
|
37478
|
-
if (!
|
|
37479
|
-
const content =
|
|
37619
|
+
if (!existsSync41(filePath)) return ctx.text("Not found", 404);
|
|
37620
|
+
const content = readFileSync27(filePath, "utf-8");
|
|
37480
37621
|
if (filePath.endsWith(".html")) {
|
|
37481
37622
|
const injected = injectRuntime(content);
|
|
37482
37623
|
return ctx.html(injected);
|
|
@@ -37495,7 +37636,7 @@ var init_play = __esm({
|
|
|
37495
37636
|
mp3: "audio/mpeg",
|
|
37496
37637
|
wav: "audio/wav"
|
|
37497
37638
|
};
|
|
37498
|
-
return ctx.body(
|
|
37639
|
+
return ctx.body(readFileSync27(filePath), 200, {
|
|
37499
37640
|
"Content-Type": types3[ext] ?? "application/octet-stream"
|
|
37500
37641
|
});
|
|
37501
37642
|
});
|
|
@@ -37551,8 +37692,8 @@ var init_play = __esm({
|
|
|
37551
37692
|
});
|
|
37552
37693
|
|
|
37553
37694
|
// src/utils/publishProject.ts
|
|
37554
|
-
import { basename as basename7, join as
|
|
37555
|
-
import { readdirSync as readdirSync15, readFileSync as
|
|
37695
|
+
import { basename as basename7, join as join41, relative as relative4 } from "path";
|
|
37696
|
+
import { readdirSync as readdirSync15, readFileSync as readFileSync28, statSync as statSync14 } from "fs";
|
|
37556
37697
|
import AdmZip from "adm-zip";
|
|
37557
37698
|
function isRecord(value) {
|
|
37558
37699
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -37643,7 +37784,7 @@ function shouldIgnoreSegment(segment) {
|
|
|
37643
37784
|
function collectProjectFiles(rootDir, currentDir, paths) {
|
|
37644
37785
|
for (const entry of readdirSync15(currentDir, { withFileTypes: true })) {
|
|
37645
37786
|
if (shouldIgnoreSegment(entry.name)) continue;
|
|
37646
|
-
const absolutePath =
|
|
37787
|
+
const absolutePath = join41(currentDir, entry.name);
|
|
37647
37788
|
const relativePath = relative4(rootDir, absolutePath).replaceAll("\\", "/");
|
|
37648
37789
|
if (!relativePath) continue;
|
|
37649
37790
|
if (entry.isDirectory()) {
|
|
@@ -37662,7 +37803,7 @@ function createPublishArchive(projectDir) {
|
|
|
37662
37803
|
}
|
|
37663
37804
|
const archive = new AdmZip();
|
|
37664
37805
|
for (const filePath of filePaths) {
|
|
37665
|
-
archive.addFile(filePath,
|
|
37806
|
+
archive.addFile(filePath, readFileSync28(join41(projectDir, filePath)));
|
|
37666
37807
|
}
|
|
37667
37808
|
return {
|
|
37668
37809
|
buffer: archive.toBuffer(),
|
|
@@ -37778,8 +37919,8 @@ __export(publish_exports, {
|
|
|
37778
37919
|
examples: () => examples6
|
|
37779
37920
|
});
|
|
37780
37921
|
import { basename as basename8, resolve as resolve27 } from "path";
|
|
37781
|
-
import { existsSync as
|
|
37782
|
-
import { join as
|
|
37922
|
+
import { existsSync as existsSync42 } from "fs";
|
|
37923
|
+
import { join as join42 } from "path";
|
|
37783
37924
|
var examples6, publish_default;
|
|
37784
37925
|
var init_publish = __esm({
|
|
37785
37926
|
"src/commands/publish.ts"() {
|
|
@@ -37814,8 +37955,8 @@ var init_publish = __esm({
|
|
|
37814
37955
|
const dir = resolve27(rawArg ?? ".");
|
|
37815
37956
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
37816
37957
|
const projectName = isImplicitCwd ? basename8(process.env["PWD"] ?? dir) : basename8(dir);
|
|
37817
|
-
const indexPath =
|
|
37818
|
-
if (
|
|
37958
|
+
const indexPath = join42(dir, "index.html");
|
|
37959
|
+
if (existsSync42(indexPath)) {
|
|
37819
37960
|
const lintResult = lintProject({ dir, name: projectName, indexPath });
|
|
37820
37961
|
if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
|
|
37821
37962
|
console.log();
|
|
@@ -37986,10 +38127,10 @@ __export(render_exports, {
|
|
|
37986
38127
|
default: () => render_default,
|
|
37987
38128
|
examples: () => examples7
|
|
37988
38129
|
});
|
|
37989
|
-
import { mkdirSync as
|
|
38130
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync29, statSync as statSync15, writeFileSync as writeFileSync18, rmSync as rmSync9 } from "fs";
|
|
37990
38131
|
import { cpus as cpus3, freemem as freemem3, tmpdir as tmpdir4 } from "os";
|
|
37991
|
-
import { resolve as resolve28, dirname as dirname16, join as
|
|
37992
|
-
import { execFileSync as execFileSync5, spawn as
|
|
38132
|
+
import { resolve as resolve28, dirname as dirname16, join as join43, basename as basename9 } from "path";
|
|
38133
|
+
import { execFileSync as execFileSync5, spawn as spawn11 } from "child_process";
|
|
37993
38134
|
function defaultWorkerCount() {
|
|
37994
38135
|
return Math.max(1, Math.min(Math.floor(CPU_CORE_COUNT * 3 / 4), 8));
|
|
37995
38136
|
}
|
|
@@ -38025,9 +38166,9 @@ function ensureDockerImage(version, quiet) {
|
|
|
38025
38166
|
}
|
|
38026
38167
|
if (!quiet) console.log(c.dim(` Building Docker image: ${tag}...`));
|
|
38027
38168
|
const dockerfilePath = resolveDockerfilePath();
|
|
38028
|
-
const tmpDir =
|
|
38029
|
-
|
|
38030
|
-
|
|
38169
|
+
const tmpDir = join43(tmpdir4(), `hyperframes-docker-${Date.now()}`);
|
|
38170
|
+
mkdirSync24(tmpDir, { recursive: true });
|
|
38171
|
+
writeFileSync18(join43(tmpDir, "Dockerfile"), readFileSync29(dockerfilePath));
|
|
38031
38172
|
try {
|
|
38032
38173
|
execFileSync5(
|
|
38033
38174
|
"docker",
|
|
@@ -38096,7 +38237,7 @@ async function renderDocker(projectDir, outputPath, options) {
|
|
|
38096
38237
|
}
|
|
38097
38238
|
try {
|
|
38098
38239
|
await new Promise((resolvePromise, reject) => {
|
|
38099
|
-
const child =
|
|
38240
|
+
const child = spawn11("docker", dockerArgs, {
|
|
38100
38241
|
// When quiet, still show stderr so container errors surface
|
|
38101
38242
|
stdio: options.quiet ? ["pipe", "pipe", "inherit"] : "inherit"
|
|
38102
38243
|
});
|
|
@@ -38375,8 +38516,8 @@ var init_render2 = __esm({
|
|
|
38375
38516
|
const now = /* @__PURE__ */ new Date();
|
|
38376
38517
|
const datePart = now.toISOString().slice(0, 10);
|
|
38377
38518
|
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
|
38378
|
-
const outputPath = args.output ? resolve28(args.output) :
|
|
38379
|
-
|
|
38519
|
+
const outputPath = args.output ? resolve28(args.output) : join43(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
|
|
38520
|
+
mkdirSync24(dirname16(outputPath), { recursive: true });
|
|
38380
38521
|
const useDocker = args.docker ?? false;
|
|
38381
38522
|
const useGpu = args.gpu ?? false;
|
|
38382
38523
|
const quiet = args.quiet ?? false;
|
|
@@ -38851,8 +38992,8 @@ __export(layout_exports, {
|
|
|
38851
38992
|
examples: () => examples9
|
|
38852
38993
|
});
|
|
38853
38994
|
import { createServer } from "http";
|
|
38854
|
-
import { existsSync as
|
|
38855
|
-
import { dirname as dirname17, isAbsolute as isAbsolute6, join as
|
|
38995
|
+
import { existsSync as existsSync43, readFileSync as readFileSync30 } from "fs";
|
|
38996
|
+
import { dirname as dirname17, isAbsolute as isAbsolute6, join as join44, relative as relative5, resolve as resolve29 } from "path";
|
|
38856
38997
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
38857
38998
|
async function getCompositionDuration2(page) {
|
|
38858
38999
|
return page.evaluate(() => {
|
|
@@ -38922,8 +39063,8 @@ async function bundleProjectHtml(projectDir) {
|
|
|
38922
39063
|
"dist",
|
|
38923
39064
|
"hyperframe.runtime.iife.js"
|
|
38924
39065
|
);
|
|
38925
|
-
if (
|
|
38926
|
-
const runtimeSource =
|
|
39066
|
+
if (existsSync43(runtimePath)) {
|
|
39067
|
+
const runtimeSource = readFileSync30(runtimePath, "utf-8");
|
|
38927
39068
|
html = html.replace(
|
|
38928
39069
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
38929
39070
|
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
@@ -38947,9 +39088,9 @@ async function serveProject(projectDir, html) {
|
|
|
38947
39088
|
res.end();
|
|
38948
39089
|
return;
|
|
38949
39090
|
}
|
|
38950
|
-
if (
|
|
39091
|
+
if (existsSync43(filePath)) {
|
|
38951
39092
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
38952
|
-
res.end(
|
|
39093
|
+
res.end(readFileSync30(filePath));
|
|
38953
39094
|
return;
|
|
38954
39095
|
}
|
|
38955
39096
|
res.writeHead(404);
|
|
@@ -39051,11 +39192,11 @@ async function runLayoutAudit(projectDir, opts) {
|
|
|
39051
39192
|
}
|
|
39052
39193
|
function loadLayoutAuditScript() {
|
|
39053
39194
|
const candidates = [
|
|
39054
|
-
|
|
39055
|
-
|
|
39195
|
+
join44(__dirname2, "layout-audit.browser.js"),
|
|
39196
|
+
join44(__dirname2, "commands", "layout-audit.browser.js")
|
|
39056
39197
|
];
|
|
39057
39198
|
for (const candidate of candidates) {
|
|
39058
|
-
if (
|
|
39199
|
+
if (existsSync43(candidate)) return readFileSync30(candidate, "utf-8");
|
|
39059
39200
|
}
|
|
39060
39201
|
throw new Error("Missing layout audit browser script");
|
|
39061
39202
|
}
|
|
@@ -39275,12 +39416,12 @@ __export(info_exports, {
|
|
|
39275
39416
|
default: () => info_default,
|
|
39276
39417
|
examples: () => examples11
|
|
39277
39418
|
});
|
|
39278
|
-
import { readFileSync as
|
|
39279
|
-
import { join as
|
|
39419
|
+
import { readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
|
|
39420
|
+
import { join as join45 } from "path";
|
|
39280
39421
|
function totalSize(dir) {
|
|
39281
39422
|
let total = 0;
|
|
39282
39423
|
for (const entry of readdirSync16(dir, { withFileTypes: true })) {
|
|
39283
|
-
const path2 =
|
|
39424
|
+
const path2 = join45(dir, entry.name);
|
|
39284
39425
|
if (entry.isDirectory()) {
|
|
39285
39426
|
total += totalSize(path2);
|
|
39286
39427
|
} else {
|
|
@@ -39312,7 +39453,7 @@ var init_info = __esm({
|
|
|
39312
39453
|
},
|
|
39313
39454
|
async run({ args }) {
|
|
39314
39455
|
const project = resolveProject(args.dir);
|
|
39315
|
-
const html =
|
|
39456
|
+
const html = readFileSync31(project.indexPath, "utf-8");
|
|
39316
39457
|
ensureDOMParser();
|
|
39317
39458
|
const parsed = parseHtml(html);
|
|
39318
39459
|
const tracks = new Set(parsed.elements.map((el) => el.zIndex));
|
|
@@ -39368,7 +39509,7 @@ __export(compositions_exports, {
|
|
|
39368
39509
|
default: () => compositions_default,
|
|
39369
39510
|
examples: () => examples12
|
|
39370
39511
|
});
|
|
39371
|
-
import { existsSync as
|
|
39512
|
+
import { existsSync as existsSync44, readFileSync as readFileSync32 } from "fs";
|
|
39372
39513
|
import { resolve as resolve30, dirname as dirname18 } from "path";
|
|
39373
39514
|
function parseCompositions(html, baseDir) {
|
|
39374
39515
|
const parser = new DOMParser();
|
|
@@ -39382,8 +39523,8 @@ function parseCompositions(html, baseDir) {
|
|
|
39382
39523
|
const compositionSrc = div.getAttribute("data-composition-src");
|
|
39383
39524
|
if (compositionSrc) {
|
|
39384
39525
|
const subPath = resolve30(baseDir, compositionSrc);
|
|
39385
|
-
if (
|
|
39386
|
-
const subHtml =
|
|
39526
|
+
if (existsSync44(subPath)) {
|
|
39527
|
+
const subHtml = readFileSync32(subPath, "utf-8");
|
|
39387
39528
|
const subInfo = parseSubComposition(subHtml, id, width, height);
|
|
39388
39529
|
compositions.push({ ...subInfo, source: compositionSrc });
|
|
39389
39530
|
return;
|
|
@@ -39477,7 +39618,7 @@ var init_compositions = __esm({
|
|
|
39477
39618
|
},
|
|
39478
39619
|
async run({ args }) {
|
|
39479
39620
|
const project = resolveProject(args.dir);
|
|
39480
|
-
const html =
|
|
39621
|
+
const html = readFileSync32(project.indexPath, "utf-8");
|
|
39481
39622
|
ensureDOMParser();
|
|
39482
39623
|
const compositions = parseCompositions(html, dirname18(project.indexPath));
|
|
39483
39624
|
if (compositions.length === 0) {
|
|
@@ -39515,8 +39656,8 @@ __export(benchmark_exports, {
|
|
|
39515
39656
|
default: () => benchmark_default,
|
|
39516
39657
|
examples: () => examples13
|
|
39517
39658
|
});
|
|
39518
|
-
import { existsSync as
|
|
39519
|
-
import { resolve as resolve31, join as
|
|
39659
|
+
import { existsSync as existsSync45, statSync as statSync17 } from "fs";
|
|
39660
|
+
import { resolve as resolve31, join as join46 } from "path";
|
|
39520
39661
|
var examples13, DEFAULT_CONFIGS, benchmark_default;
|
|
39521
39662
|
var init_benchmark = __esm({
|
|
39522
39663
|
"src/commands/benchmark.ts"() {
|
|
@@ -39591,7 +39732,7 @@ var init_benchmark = __esm({
|
|
|
39591
39732
|
s2?.start(`Benchmarking ${config.label}...`);
|
|
39592
39733
|
for (let i2 = 0; i2 < runsPerConfig; i2++) {
|
|
39593
39734
|
s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
|
|
39594
|
-
const outputPath =
|
|
39735
|
+
const outputPath = join46(
|
|
39595
39736
|
benchDir,
|
|
39596
39737
|
`${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
|
|
39597
39738
|
);
|
|
@@ -39605,7 +39746,7 @@ var init_benchmark = __esm({
|
|
|
39605
39746
|
await producer.executeRenderJob(job, project.dir, outputPath);
|
|
39606
39747
|
const elapsedMs = Date.now() - startTime;
|
|
39607
39748
|
let fileSize = null;
|
|
39608
|
-
if (
|
|
39749
|
+
if (existsSync45(outputPath)) {
|
|
39609
39750
|
const stat3 = statSync17(outputPath);
|
|
39610
39751
|
fileSize = stat3.size;
|
|
39611
39752
|
}
|
|
@@ -39821,8 +39962,8 @@ __export(transcribe_exports2, {
|
|
|
39821
39962
|
default: () => transcribe_default,
|
|
39822
39963
|
examples: () => examples15
|
|
39823
39964
|
});
|
|
39824
|
-
import { existsSync as
|
|
39825
|
-
import { resolve as resolve32, join as
|
|
39965
|
+
import { existsSync as existsSync46, writeFileSync as writeFileSync19 } from "fs";
|
|
39966
|
+
import { resolve as resolve32, join as join47, extname as extname8 } from "path";
|
|
39826
39967
|
async function importTranscript(inputPath, dir, json) {
|
|
39827
39968
|
const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
|
|
39828
39969
|
const { words, format } = loadTranscript2(inputPath);
|
|
@@ -39830,8 +39971,8 @@ async function importTranscript(inputPath, dir, json) {
|
|
|
39830
39971
|
console.error(c.error("No words found in transcript."));
|
|
39831
39972
|
process.exit(1);
|
|
39832
39973
|
}
|
|
39833
|
-
const outPath =
|
|
39834
|
-
|
|
39974
|
+
const outPath = join47(dir, "transcript.json");
|
|
39975
|
+
writeFileSync19(outPath, JSON.stringify(words, null, 2));
|
|
39835
39976
|
patchCaptionHtml2(dir, words);
|
|
39836
39977
|
if (json) {
|
|
39837
39978
|
console.log(
|
|
@@ -39866,7 +40007,7 @@ async function transcribeAudio(inputPath, dir, opts) {
|
|
|
39866
40007
|
);
|
|
39867
40008
|
}
|
|
39868
40009
|
}
|
|
39869
|
-
|
|
40010
|
+
writeFileSync19(result.transcriptPath, JSON.stringify(words, null, 2));
|
|
39870
40011
|
patchCaptionHtml2(dir, words);
|
|
39871
40012
|
if (opts.json) {
|
|
39872
40013
|
console.log(
|
|
@@ -39947,7 +40088,7 @@ var init_transcribe2 = __esm({
|
|
|
39947
40088
|
},
|
|
39948
40089
|
async run({ args }) {
|
|
39949
40090
|
const inputPath = resolve32(args.input);
|
|
39950
|
-
if (!
|
|
40091
|
+
if (!existsSync46(inputPath)) {
|
|
39951
40092
|
console.error(c.error(`File not found: ${args.input}`));
|
|
39952
40093
|
process.exit(1);
|
|
39953
40094
|
}
|
|
@@ -39968,9 +40109,9 @@ var init_transcribe2 = __esm({
|
|
|
39968
40109
|
});
|
|
39969
40110
|
|
|
39970
40111
|
// src/tts/manager.ts
|
|
39971
|
-
import { existsSync as
|
|
40112
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync25 } from "fs";
|
|
39972
40113
|
import { homedir as homedir8 } from "os";
|
|
39973
|
-
import { join as
|
|
40114
|
+
import { join as join48 } from "path";
|
|
39974
40115
|
function inferLangFromVoiceId(voiceId) {
|
|
39975
40116
|
const first = voiceId.charAt(0).toLowerCase();
|
|
39976
40117
|
return VOICE_PREFIX_LANG[first] ?? "en-us";
|
|
@@ -39979,29 +40120,29 @@ function isSupportedLang(value) {
|
|
|
39979
40120
|
return SUPPORTED_LANGS.includes(value);
|
|
39980
40121
|
}
|
|
39981
40122
|
async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
39982
|
-
const modelPath =
|
|
39983
|
-
if (
|
|
40123
|
+
const modelPath = join48(MODELS_DIR2, `${model}.onnx`);
|
|
40124
|
+
if (existsSync47(modelPath)) return modelPath;
|
|
39984
40125
|
const url = MODEL_URLS[model];
|
|
39985
40126
|
if (!url) {
|
|
39986
40127
|
throw new Error(
|
|
39987
40128
|
`Unknown TTS model: ${model}. Available: ${Object.keys(MODEL_URLS).join(", ")}`
|
|
39988
40129
|
);
|
|
39989
40130
|
}
|
|
39990
|
-
|
|
40131
|
+
mkdirSync25(MODELS_DIR2, { recursive: true });
|
|
39991
40132
|
options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
|
|
39992
40133
|
await downloadFile(url, modelPath);
|
|
39993
|
-
if (!
|
|
40134
|
+
if (!existsSync47(modelPath)) {
|
|
39994
40135
|
throw new Error(`Model download failed: ${model}`);
|
|
39995
40136
|
}
|
|
39996
40137
|
return modelPath;
|
|
39997
40138
|
}
|
|
39998
40139
|
async function ensureVoices(options) {
|
|
39999
|
-
const voicesPath =
|
|
40000
|
-
if (
|
|
40001
|
-
|
|
40140
|
+
const voicesPath = join48(VOICES_DIR, "voices-v1.0.bin");
|
|
40141
|
+
if (existsSync47(voicesPath)) return voicesPath;
|
|
40142
|
+
mkdirSync25(VOICES_DIR, { recursive: true });
|
|
40002
40143
|
options?.onProgress?.("Downloading voice data (~27 MB)...");
|
|
40003
40144
|
await downloadFile(VOICES_URL, voicesPath);
|
|
40004
|
-
if (!
|
|
40145
|
+
if (!existsSync47(voicesPath)) {
|
|
40005
40146
|
throw new Error("Voice data download failed");
|
|
40006
40147
|
}
|
|
40007
40148
|
return voicesPath;
|
|
@@ -40011,9 +40152,9 @@ var init_manager3 = __esm({
|
|
|
40011
40152
|
"src/tts/manager.ts"() {
|
|
40012
40153
|
"use strict";
|
|
40013
40154
|
init_download();
|
|
40014
|
-
CACHE_DIR3 =
|
|
40015
|
-
MODELS_DIR2 =
|
|
40016
|
-
VOICES_DIR =
|
|
40155
|
+
CACHE_DIR3 = join48(homedir8(), ".cache", "hyperframes", "tts");
|
|
40156
|
+
MODELS_DIR2 = join48(CACHE_DIR3, "models");
|
|
40157
|
+
VOICES_DIR = join48(CACHE_DIR3, "voices");
|
|
40017
40158
|
DEFAULT_MODEL2 = "kokoro-v1.0";
|
|
40018
40159
|
MODEL_URLS = {
|
|
40019
40160
|
"kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
|
|
@@ -40074,8 +40215,8 @@ __export(synthesize_exports, {
|
|
|
40074
40215
|
synthesize: () => synthesize
|
|
40075
40216
|
});
|
|
40076
40217
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
40077
|
-
import { existsSync as
|
|
40078
|
-
import { join as
|
|
40218
|
+
import { existsSync as existsSync48, writeFileSync as writeFileSync20, mkdirSync as mkdirSync26, readdirSync as readdirSync17, unlinkSync as unlinkSync6 } from "fs";
|
|
40219
|
+
import { join as join49, dirname as dirname19, basename as basename10 } from "path";
|
|
40079
40220
|
import { homedir as homedir9 } from "os";
|
|
40080
40221
|
function findPython() {
|
|
40081
40222
|
for (const name of ["python3", "python"]) {
|
|
@@ -40111,15 +40252,15 @@ function hasPythonPackage(python, pkg) {
|
|
|
40111
40252
|
}
|
|
40112
40253
|
}
|
|
40113
40254
|
function ensureSynthScript() {
|
|
40114
|
-
if (!
|
|
40115
|
-
|
|
40116
|
-
|
|
40255
|
+
if (!existsSync48(SCRIPT_PATH)) {
|
|
40256
|
+
mkdirSync26(SCRIPT_DIR, { recursive: true });
|
|
40257
|
+
writeFileSync20(SCRIPT_PATH, SYNTH_SCRIPT);
|
|
40117
40258
|
const currentName = basename10(SCRIPT_PATH);
|
|
40118
40259
|
try {
|
|
40119
40260
|
for (const entry of readdirSync17(SCRIPT_DIR)) {
|
|
40120
40261
|
if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
|
|
40121
40262
|
try {
|
|
40122
|
-
unlinkSync6(
|
|
40263
|
+
unlinkSync6(join49(SCRIPT_DIR, entry));
|
|
40123
40264
|
} catch {
|
|
40124
40265
|
}
|
|
40125
40266
|
}
|
|
@@ -40153,7 +40294,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
40153
40294
|
ensureVoices({ onProgress: options?.onProgress })
|
|
40154
40295
|
]);
|
|
40155
40296
|
const scriptPath = ensureSynthScript();
|
|
40156
|
-
|
|
40297
|
+
mkdirSync26(dirname19(outputPath), { recursive: true });
|
|
40157
40298
|
options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
|
|
40158
40299
|
try {
|
|
40159
40300
|
const stdout2 = execFileSync6(
|
|
@@ -40165,7 +40306,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
40165
40306
|
stdio: ["pipe", "pipe", "pipe"]
|
|
40166
40307
|
}
|
|
40167
40308
|
);
|
|
40168
|
-
if (!
|
|
40309
|
+
if (!existsSync48(outputPath)) {
|
|
40169
40310
|
throw new Error("Synthesis completed but no output file was created");
|
|
40170
40311
|
}
|
|
40171
40312
|
const lines = stdout2.trim().split("\n");
|
|
@@ -40178,7 +40319,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
40178
40319
|
langApplied: result.langApplied
|
|
40179
40320
|
};
|
|
40180
40321
|
} catch (err) {
|
|
40181
|
-
if (err instanceof SyntaxError &&
|
|
40322
|
+
if (err instanceof SyntaxError && existsSync48(outputPath)) {
|
|
40182
40323
|
throw new Error(
|
|
40183
40324
|
"Speech was generated but metadata could not be read. Check the output file manually."
|
|
40184
40325
|
);
|
|
@@ -40229,8 +40370,8 @@ print(json.dumps({
|
|
|
40229
40370
|
"langApplied": bool(lang and supports_lang),
|
|
40230
40371
|
}))
|
|
40231
40372
|
`;
|
|
40232
|
-
SCRIPT_DIR =
|
|
40233
|
-
SCRIPT_PATH =
|
|
40373
|
+
SCRIPT_DIR = join49(homedir9(), ".cache", "hyperframes", "tts");
|
|
40374
|
+
SCRIPT_PATH = join49(SCRIPT_DIR, "synth-v2.py");
|
|
40234
40375
|
}
|
|
40235
40376
|
});
|
|
40236
40377
|
|
|
@@ -40240,7 +40381,7 @@ __export(tts_exports, {
|
|
|
40240
40381
|
default: () => tts_default,
|
|
40241
40382
|
examples: () => examples16
|
|
40242
40383
|
});
|
|
40243
|
-
import { existsSync as
|
|
40384
|
+
import { existsSync as existsSync49, readFileSync as readFileSync33 } from "fs";
|
|
40244
40385
|
import { resolve as resolve33, extname as extname9 } from "path";
|
|
40245
40386
|
function listVoices(json) {
|
|
40246
40387
|
const rows = BUNDLED_VOICES.map((v) => ({ ...v, defaultLang: inferLangFromVoiceId(v.id) }));
|
|
@@ -40350,8 +40491,8 @@ var init_tts = __esm({
|
|
|
40350
40491
|
}
|
|
40351
40492
|
let text;
|
|
40352
40493
|
const maybeFile = resolve33(args.input);
|
|
40353
|
-
if (
|
|
40354
|
-
text =
|
|
40494
|
+
if (existsSync49(maybeFile) && extname9(maybeFile).toLowerCase() === ".txt") {
|
|
40495
|
+
text = readFileSync33(maybeFile, "utf-8").trim();
|
|
40355
40496
|
if (!text) {
|
|
40356
40497
|
console.error(c.error("File is empty."));
|
|
40357
40498
|
process.exit(1);
|
|
@@ -40443,15 +40584,15 @@ __export(docs_exports, {
|
|
|
40443
40584
|
default: () => docs_default,
|
|
40444
40585
|
examples: () => examples17
|
|
40445
40586
|
});
|
|
40446
|
-
import { readFileSync as
|
|
40447
|
-
import { resolve as resolve34, dirname as dirname20, join as
|
|
40587
|
+
import { readFileSync as readFileSync34, existsSync as existsSync50 } from "fs";
|
|
40588
|
+
import { resolve as resolve34, dirname as dirname20, join as join50 } from "path";
|
|
40448
40589
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
40449
40590
|
function docsDir() {
|
|
40450
40591
|
const thisFile = fileURLToPath7(import.meta.url);
|
|
40451
40592
|
const dir = dirname20(thisFile);
|
|
40452
40593
|
const devPath = resolve34(dir, "..", "docs");
|
|
40453
40594
|
const builtPath = resolve34(dir, "docs");
|
|
40454
|
-
return
|
|
40595
|
+
return existsSync50(devPath) ? devPath : builtPath;
|
|
40455
40596
|
}
|
|
40456
40597
|
function formatInlineCode(line) {
|
|
40457
40598
|
return line.replace(/`([^`]+)`/g, (_match, code) => c.accent(code));
|
|
@@ -40548,12 +40689,12 @@ var init_docs = __esm({
|
|
|
40548
40689
|
}
|
|
40549
40690
|
process.exit(1);
|
|
40550
40691
|
}
|
|
40551
|
-
const filePath =
|
|
40552
|
-
if (!
|
|
40692
|
+
const filePath = join50(docsDir(), entry.file);
|
|
40693
|
+
if (!existsSync50(filePath)) {
|
|
40553
40694
|
console.error(c.error(`Doc file not found: ${filePath}`));
|
|
40554
40695
|
process.exit(1);
|
|
40555
40696
|
}
|
|
40556
|
-
const content =
|
|
40697
|
+
const content = readFileSync34(filePath, "utf-8");
|
|
40557
40698
|
console.log();
|
|
40558
40699
|
renderMarkdown(content);
|
|
40559
40700
|
}
|
|
@@ -40979,8 +41120,8 @@ var validate_exports = {};
|
|
|
40979
41120
|
__export(validate_exports, {
|
|
40980
41121
|
default: () => validate_default
|
|
40981
41122
|
});
|
|
40982
|
-
import { existsSync as
|
|
40983
|
-
import { resolve as resolve35, join as
|
|
41123
|
+
import { existsSync as existsSync51, readFileSync as readFileSync35 } from "fs";
|
|
41124
|
+
import { resolve as resolve35, join as join51, dirname as dirname21 } from "path";
|
|
40984
41125
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
40985
41126
|
async function getCompositionDuration3(page) {
|
|
40986
41127
|
return page.evaluate(() => {
|
|
@@ -41035,8 +41176,8 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
41035
41176
|
"dist",
|
|
41036
41177
|
"hyperframe.runtime.iife.js"
|
|
41037
41178
|
);
|
|
41038
|
-
if (
|
|
41039
|
-
const runtimeSource =
|
|
41179
|
+
if (existsSync51(runtimePath)) {
|
|
41180
|
+
const runtimeSource = readFileSync35(runtimePath, "utf-8");
|
|
41040
41181
|
html = html.replace(
|
|
41041
41182
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
41042
41183
|
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
@@ -41051,10 +41192,10 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
41051
41192
|
res.end(html);
|
|
41052
41193
|
return;
|
|
41053
41194
|
}
|
|
41054
|
-
const filePath =
|
|
41055
|
-
if (
|
|
41195
|
+
const filePath = join51(projectDir, decodeURIComponent(url));
|
|
41196
|
+
if (existsSync51(filePath)) {
|
|
41056
41197
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
41057
|
-
res.end(
|
|
41198
|
+
res.end(readFileSync35(filePath));
|
|
41058
41199
|
return;
|
|
41059
41200
|
}
|
|
41060
41201
|
res.writeHead(404);
|
|
@@ -41244,14 +41385,14 @@ __export(snapshot_exports, {
|
|
|
41244
41385
|
default: () => snapshot_default,
|
|
41245
41386
|
examples: () => examples21
|
|
41246
41387
|
});
|
|
41247
|
-
import { spawn as
|
|
41248
|
-
import { existsSync as
|
|
41388
|
+
import { spawn as spawn12 } from "child_process";
|
|
41389
|
+
import { existsSync as existsSync52, mkdtempSync as mkdtempSync3, readFileSync as readFileSync36, mkdirSync as mkdirSync27, rmSync as rmSync10 } from "fs";
|
|
41249
41390
|
import { tmpdir as tmpdir5 } from "os";
|
|
41250
|
-
import { resolve as resolve36, join as
|
|
41391
|
+
import { resolve as resolve36, join as join52, dirname as dirname22, relative as relative6, isAbsolute as isAbsolute7 } from "path";
|
|
41251
41392
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
41252
41393
|
async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
|
|
41253
|
-
const tmp = mkdtempSync3(
|
|
41254
|
-
const outPath =
|
|
41394
|
+
const tmp = mkdtempSync3(join52(tmpdir5(), "hf-snapshot-frame-"));
|
|
41395
|
+
const outPath = join52(tmp, "frame.png");
|
|
41255
41396
|
try {
|
|
41256
41397
|
const result = await new Promise(
|
|
41257
41398
|
(resolvePromise) => {
|
|
@@ -41271,7 +41412,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
|
|
|
41271
41412
|
"-y",
|
|
41272
41413
|
outPath
|
|
41273
41414
|
);
|
|
41274
|
-
const ff =
|
|
41415
|
+
const ff = spawn12("ffmpeg", args);
|
|
41275
41416
|
let stderr = "";
|
|
41276
41417
|
let timedOut = false;
|
|
41277
41418
|
const timer = setTimeout(() => {
|
|
@@ -41291,8 +41432,8 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
|
|
|
41291
41432
|
});
|
|
41292
41433
|
}
|
|
41293
41434
|
);
|
|
41294
|
-
if (result.code !== 0 || result.timedOut || !
|
|
41295
|
-
return
|
|
41435
|
+
if (result.code !== 0 || result.timedOut || !existsSync52(outPath)) return null;
|
|
41436
|
+
return readFileSync36(outPath);
|
|
41296
41437
|
} finally {
|
|
41297
41438
|
try {
|
|
41298
41439
|
rmSync10(tmp, { recursive: true, force: true });
|
|
@@ -41305,17 +41446,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
41305
41446
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
41306
41447
|
const numFrames = opts.frames ?? 5;
|
|
41307
41448
|
let html = await bundleToSingleHtml2(projectDir);
|
|
41308
|
-
const runtimePath = resolve36(
|
|
41309
|
-
|
|
41310
|
-
"
|
|
41311
|
-
"..",
|
|
41312
|
-
"..",
|
|
41313
|
-
"core",
|
|
41314
|
-
"dist",
|
|
41315
|
-
"hyperframe.runtime.iife.js"
|
|
41316
|
-
);
|
|
41317
|
-
if (existsSync50(runtimePath)) {
|
|
41318
|
-
const runtimeSource = readFileSync35(runtimePath, "utf-8");
|
|
41449
|
+
const runtimePath = resolve36(__dirname4, "hyperframe.runtime.iife.js");
|
|
41450
|
+
if (existsSync52(runtimePath)) {
|
|
41451
|
+
const runtimeSource = readFileSync36(runtimePath, "utf-8");
|
|
41319
41452
|
html = html.replace(
|
|
41320
41453
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
41321
41454
|
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
@@ -41337,9 +41470,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
41337
41470
|
res.end();
|
|
41338
41471
|
return;
|
|
41339
41472
|
}
|
|
41340
|
-
if (
|
|
41473
|
+
if (existsSync52(filePath)) {
|
|
41341
41474
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
41342
|
-
res.end(
|
|
41475
|
+
res.end(readFileSync36(filePath));
|
|
41343
41476
|
return;
|
|
41344
41477
|
}
|
|
41345
41478
|
res.writeHead(404);
|
|
@@ -41412,8 +41545,8 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
41412
41545
|
return [];
|
|
41413
41546
|
}
|
|
41414
41547
|
const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_2, i2) => i2 / (numFrames - 1) * duration);
|
|
41415
|
-
const snapshotDir =
|
|
41416
|
-
|
|
41548
|
+
const snapshotDir = join52(projectDir, "snapshots");
|
|
41549
|
+
mkdirSync27(snapshotDir, { recursive: true });
|
|
41417
41550
|
let injectVideoFramesBatch2 = null;
|
|
41418
41551
|
let syncVideoFrameVisibility2 = null;
|
|
41419
41552
|
let extractMediaMetadata2 = null;
|
|
@@ -41487,7 +41620,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
41487
41620
|
const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
|
|
41488
41621
|
const candidate = resolve36(projectDir, decodedPath);
|
|
41489
41622
|
const rel = relative6(projectDir, candidate);
|
|
41490
|
-
if (!rel.startsWith("..") && !isAbsolute7(rel) &&
|
|
41623
|
+
if (!rel.startsWith("..") && !isAbsolute7(rel) && existsSync52(candidate)) {
|
|
41491
41624
|
filePath = candidate;
|
|
41492
41625
|
}
|
|
41493
41626
|
} catch {
|
|
@@ -41517,7 +41650,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
41517
41650
|
}
|
|
41518
41651
|
const timeLabel = opts.at?.length ? `${time.toFixed(1)}s` : `${Math.round(time / duration * 100)}pct`;
|
|
41519
41652
|
const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
|
|
41520
|
-
const framePath =
|
|
41653
|
+
const framePath = join52(snapshotDir, filename);
|
|
41521
41654
|
await page.screenshot({ path: framePath, type: "png" });
|
|
41522
41655
|
savedPaths.push(`snapshots/${filename}`);
|
|
41523
41656
|
}
|
|
@@ -41602,14 +41735,14 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
|
41602
41735
|
});
|
|
41603
41736
|
|
|
41604
41737
|
// src/capture/assetDownloader.ts
|
|
41605
|
-
import { writeFileSync as
|
|
41606
|
-
import { join as
|
|
41738
|
+
import { writeFileSync as writeFileSync21, mkdirSync as mkdirSync28 } from "fs";
|
|
41739
|
+
import { join as join53, extname as extname10 } from "path";
|
|
41607
41740
|
async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
|
|
41608
|
-
const assetsDir =
|
|
41609
|
-
|
|
41741
|
+
const assetsDir = join53(outputDir, "assets");
|
|
41742
|
+
mkdirSync28(assetsDir, { recursive: true });
|
|
41610
41743
|
const assets = [];
|
|
41611
41744
|
const downloadedUrls = /* @__PURE__ */ new Set();
|
|
41612
|
-
|
|
41745
|
+
mkdirSync28(join53(outputDir, "assets", "svgs"), { recursive: true });
|
|
41613
41746
|
for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
|
|
41614
41747
|
const svg = tokens.svgs[i2];
|
|
41615
41748
|
if (!svg.outerHTML || svg.outerHTML.length < 50) continue;
|
|
@@ -41617,7 +41750,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
41617
41750
|
const name = label2 ? slugify(label2) + ".svg" : svg.isLogo ? `logo-${i2}.svg` : `icon-${i2}.svg`;
|
|
41618
41751
|
const localPath = `assets/svgs/${name}`;
|
|
41619
41752
|
try {
|
|
41620
|
-
|
|
41753
|
+
writeFileSync21(join53(outputDir, localPath), svg.outerHTML, "utf-8");
|
|
41621
41754
|
assets.push({ url: "", localPath, type: "svg" });
|
|
41622
41755
|
} catch {
|
|
41623
41756
|
}
|
|
@@ -41630,7 +41763,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
41630
41763
|
const localPath = `assets/${name}`;
|
|
41631
41764
|
const buffer = await fetchBuffer(icon.href);
|
|
41632
41765
|
if (buffer) {
|
|
41633
|
-
|
|
41766
|
+
writeFileSync21(join53(outputDir, localPath), buffer);
|
|
41634
41767
|
assets.push({ url: icon.href, localPath, type: "favicon" });
|
|
41635
41768
|
break;
|
|
41636
41769
|
}
|
|
@@ -41687,7 +41820,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
41687
41820
|
const slug = isMeaningful ? slugify(rawName) : `${prefix}-${imgIdx}`;
|
|
41688
41821
|
const name = `${slug}${ext}`;
|
|
41689
41822
|
const localPath = `assets/${name}`;
|
|
41690
|
-
|
|
41823
|
+
writeFileSync21(join53(outputDir, localPath), buffer);
|
|
41691
41824
|
assets.push({ url, localPath, type: "image" });
|
|
41692
41825
|
imgIdx++;
|
|
41693
41826
|
} catch {
|
|
@@ -41700,7 +41833,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
41700
41833
|
const localPath = `assets/og-image${ext}`;
|
|
41701
41834
|
const buffer = await fetchBuffer(tokens.ogImage);
|
|
41702
41835
|
if (buffer && buffer.length > 5e3) {
|
|
41703
|
-
|
|
41836
|
+
writeFileSync21(join53(outputDir, localPath), buffer);
|
|
41704
41837
|
assets.push({ url: tokens.ogImage, localPath, type: "image" });
|
|
41705
41838
|
}
|
|
41706
41839
|
} catch {
|
|
@@ -41723,8 +41856,8 @@ function normalizeUrl(u) {
|
|
|
41723
41856
|
}
|
|
41724
41857
|
}
|
|
41725
41858
|
async function downloadAndRewriteFonts(css, outputDir) {
|
|
41726
|
-
const assetsDir =
|
|
41727
|
-
|
|
41859
|
+
const assetsDir = join53(outputDir, "assets", "fonts");
|
|
41860
|
+
mkdirSync28(assetsDir, { recursive: true });
|
|
41728
41861
|
const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
|
|
41729
41862
|
const fontUrls = /* @__PURE__ */ new Set();
|
|
41730
41863
|
let match;
|
|
@@ -41759,11 +41892,11 @@ async function downloadAndRewriteFonts(css, outputDir) {
|
|
|
41759
41892
|
try {
|
|
41760
41893
|
const urlObj = new URL(fontUrl);
|
|
41761
41894
|
const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
|
|
41762
|
-
const localPath =
|
|
41895
|
+
const localPath = join53(assetsDir, filename);
|
|
41763
41896
|
const relativePath = `assets/fonts/${filename}`;
|
|
41764
41897
|
const buffer = await fetchBuffer(fontUrl);
|
|
41765
41898
|
if (buffer) {
|
|
41766
|
-
|
|
41899
|
+
writeFileSync21(localPath, buffer);
|
|
41767
41900
|
rewritten = rewritten.split(fontUrl).join(relativePath);
|
|
41768
41901
|
familyCounts.set(family, familyCount + 1);
|
|
41769
41902
|
count++;
|
|
@@ -42556,8 +42689,8 @@ var init_animationCataloger = __esm({
|
|
|
42556
42689
|
});
|
|
42557
42690
|
|
|
42558
42691
|
// src/capture/mediaCapture.ts
|
|
42559
|
-
import { mkdirSync as
|
|
42560
|
-
import { join as
|
|
42692
|
+
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync22, readdirSync as readdirSync18, readFileSync as readFileSync37, statSync as statSync18 } from "fs";
|
|
42693
|
+
import { join as join54 } from "path";
|
|
42561
42694
|
async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
42562
42695
|
let savedCount = 0;
|
|
42563
42696
|
const savedHashes = /* @__PURE__ */ new Set();
|
|
@@ -42590,7 +42723,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
42590
42723
|
const hash2 = buf.toString("base64").slice(0, 100);
|
|
42591
42724
|
if (savedHashes.has(hash2)) continue;
|
|
42592
42725
|
savedHashes.add(hash2);
|
|
42593
|
-
|
|
42726
|
+
writeFileSync22(join54(lottieDir, `animation-${savedCount}.lottie`), buf);
|
|
42594
42727
|
savedCount++;
|
|
42595
42728
|
continue;
|
|
42596
42729
|
}
|
|
@@ -42608,7 +42741,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
42608
42741
|
} catch {
|
|
42609
42742
|
continue;
|
|
42610
42743
|
}
|
|
42611
|
-
|
|
42744
|
+
writeFileSync22(join54(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
|
|
42612
42745
|
savedCount++;
|
|
42613
42746
|
}
|
|
42614
42747
|
} catch {
|
|
@@ -42618,22 +42751,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
42618
42751
|
}
|
|
42619
42752
|
async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
42620
42753
|
const manifest = [];
|
|
42621
|
-
const previewDir =
|
|
42622
|
-
|
|
42754
|
+
const previewDir = join54(lottieDir, "previews");
|
|
42755
|
+
mkdirSync29(previewDir, { recursive: true });
|
|
42623
42756
|
for (const file of readdirSync18(lottieDir)) {
|
|
42624
42757
|
if (!file.endsWith(".json")) continue;
|
|
42625
42758
|
try {
|
|
42626
|
-
const raw = JSON.parse(
|
|
42759
|
+
const raw = JSON.parse(readFileSync37(join54(lottieDir, file), "utf-8"));
|
|
42627
42760
|
const fr = raw.fr || 30;
|
|
42628
42761
|
const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
|
|
42629
42762
|
const previewName = file.replace(".json", "-preview.png");
|
|
42630
|
-
const fileSize = statSync18(
|
|
42763
|
+
const fileSize = statSync18(join54(lottieDir, file)).size;
|
|
42631
42764
|
if (fileSize > 2e6) continue;
|
|
42632
42765
|
let previewPage;
|
|
42633
42766
|
try {
|
|
42634
42767
|
previewPage = await chromeBrowser.newPage();
|
|
42635
42768
|
await previewPage.setViewport({ width: 400, height: 400 });
|
|
42636
|
-
const animData = JSON.parse(
|
|
42769
|
+
const animData = JSON.parse(readFileSync37(join54(lottieDir, file), "utf-8"));
|
|
42637
42770
|
const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
|
|
42638
42771
|
await previewPage.setContent(
|
|
42639
42772
|
`<!DOCTYPE html>
|
|
@@ -42663,7 +42796,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
42663
42796
|
await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
|
|
42664
42797
|
});
|
|
42665
42798
|
await previewPage.screenshot({
|
|
42666
|
-
path:
|
|
42799
|
+
path: join54(previewDir, previewName),
|
|
42667
42800
|
type: "png",
|
|
42668
42801
|
omitBackground: true
|
|
42669
42802
|
});
|
|
@@ -42686,8 +42819,8 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
42686
42819
|
}
|
|
42687
42820
|
}
|
|
42688
42821
|
if (manifest.length > 0) {
|
|
42689
|
-
|
|
42690
|
-
|
|
42822
|
+
writeFileSync22(
|
|
42823
|
+
join54(outputDir, "extracted", "lottie-manifest.json"),
|
|
42691
42824
|
JSON.stringify(manifest, null, 2),
|
|
42692
42825
|
"utf-8"
|
|
42693
42826
|
);
|
|
@@ -42749,15 +42882,15 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
42749
42882
|
return true;
|
|
42750
42883
|
});
|
|
42751
42884
|
if (uniqueVideos.length > 0) {
|
|
42752
|
-
const videoManifestDir =
|
|
42753
|
-
|
|
42754
|
-
const previewDir =
|
|
42755
|
-
|
|
42885
|
+
const videoManifestDir = join54(outputDir, "assets", "videos");
|
|
42886
|
+
mkdirSync29(videoManifestDir, { recursive: true });
|
|
42887
|
+
const previewDir = join54(videoManifestDir, "previews");
|
|
42888
|
+
mkdirSync29(previewDir, { recursive: true });
|
|
42756
42889
|
const videoManifest = [];
|
|
42757
42890
|
for (let vi = 0; vi < uniqueVideos.length && vi < 20; vi++) {
|
|
42758
42891
|
const v = uniqueVideos[vi];
|
|
42759
42892
|
const previewName = `video-${vi}-preview.png`;
|
|
42760
|
-
const previewPath =
|
|
42893
|
+
const previewPath = join54(previewDir, previewName);
|
|
42761
42894
|
try {
|
|
42762
42895
|
await page.evaluate(`window.scrollTo(0, ${Math.max(0, v.top - 100)})`);
|
|
42763
42896
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
@@ -42795,8 +42928,8 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
42795
42928
|
});
|
|
42796
42929
|
}
|
|
42797
42930
|
if (videoManifest.length > 0) {
|
|
42798
|
-
|
|
42799
|
-
|
|
42931
|
+
writeFileSync22(
|
|
42932
|
+
join54(outputDir, "extracted", "video-manifest.json"),
|
|
42800
42933
|
JSON.stringify(videoManifest, null, 2),
|
|
42801
42934
|
"utf-8"
|
|
42802
42935
|
);
|
|
@@ -83251,8 +83384,8 @@ ${underline2}`);
|
|
|
83251
83384
|
});
|
|
83252
83385
|
|
|
83253
83386
|
// src/capture/contentExtractor.ts
|
|
83254
|
-
import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as
|
|
83255
|
-
import { join as
|
|
83387
|
+
import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as readFileSync38 } from "fs";
|
|
83388
|
+
import { join as join55 } from "path";
|
|
83256
83389
|
async function detectLibraries(page, capturedShaders) {
|
|
83257
83390
|
let detectedLibraries = [];
|
|
83258
83391
|
try {
|
|
@@ -83372,7 +83505,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
83372
83505
|
try {
|
|
83373
83506
|
const { GoogleGenAI: GoogleGenAI2 } = await Promise.resolve().then(() => (init_node4(), node_exports));
|
|
83374
83507
|
const ai = new GoogleGenAI2({ apiKey: geminiKey });
|
|
83375
|
-
const imageFiles = readdirSync19(
|
|
83508
|
+
const imageFiles = readdirSync19(join55(outputDir, "assets")).filter(
|
|
83376
83509
|
(f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
|
|
83377
83510
|
);
|
|
83378
83511
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -83381,10 +83514,10 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
83381
83514
|
const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
|
|
83382
83515
|
const results = await Promise.allSettled(
|
|
83383
83516
|
batch.map(async (file) => {
|
|
83384
|
-
const filePath =
|
|
83517
|
+
const filePath = join55(outputDir, "assets", file);
|
|
83385
83518
|
const stat3 = statSync20(filePath);
|
|
83386
83519
|
if (stat3.size > 4e6) return { file, caption: "" };
|
|
83387
|
-
const buffer =
|
|
83520
|
+
const buffer = readFileSync38(filePath);
|
|
83388
83521
|
const base64 = buffer.toString("base64");
|
|
83389
83522
|
const ext = file.split(".").pop()?.toLowerCase() || "png";
|
|
83390
83523
|
const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
|
|
@@ -83430,11 +83563,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
83430
83563
|
const uncaptionedLines = [];
|
|
83431
83564
|
const svgLines = [];
|
|
83432
83565
|
const fontLines = [];
|
|
83433
|
-
const assetsPath =
|
|
83566
|
+
const assetsPath = join55(outputDir, "assets");
|
|
83434
83567
|
try {
|
|
83435
83568
|
for (const file of readdirSync19(assetsPath)) {
|
|
83436
83569
|
if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
|
|
83437
|
-
const filePath =
|
|
83570
|
+
const filePath = join55(assetsPath, file);
|
|
83438
83571
|
const stat3 = statSync20(filePath);
|
|
83439
83572
|
if (!stat3.isFile()) continue;
|
|
83440
83573
|
const sizeKb = Math.round(stat3.size / 1024);
|
|
@@ -83463,7 +83596,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
83463
83596
|
} catch {
|
|
83464
83597
|
}
|
|
83465
83598
|
try {
|
|
83466
|
-
const svgsPath =
|
|
83599
|
+
const svgsPath = join55(assetsPath, "svgs");
|
|
83467
83600
|
for (const file of readdirSync19(svgsPath)) {
|
|
83468
83601
|
if (!file.endsWith(".svg")) continue;
|
|
83469
83602
|
const svgMatch = tokens.svgs.find(
|
|
@@ -83478,7 +83611,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
83478
83611
|
} catch {
|
|
83479
83612
|
}
|
|
83480
83613
|
try {
|
|
83481
|
-
const fontsPath =
|
|
83614
|
+
const fontsPath = join55(assetsPath, "fonts");
|
|
83482
83615
|
for (const file of readdirSync19(fontsPath)) {
|
|
83483
83616
|
fontLines.push(`fonts/${file} \u2014 font file`);
|
|
83484
83617
|
}
|
|
@@ -83497,13 +83630,13 @@ var agentPromptGenerator_exports = {};
|
|
|
83497
83630
|
__export(agentPromptGenerator_exports, {
|
|
83498
83631
|
generateAgentPrompt: () => generateAgentPrompt
|
|
83499
83632
|
});
|
|
83500
|
-
import { writeFileSync as
|
|
83501
|
-
import { join as
|
|
83633
|
+
import { writeFileSync as writeFileSync23 } from "fs";
|
|
83634
|
+
import { join as join56 } from "path";
|
|
83502
83635
|
function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, detectedLibraries) {
|
|
83503
83636
|
const prompt = buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries);
|
|
83504
|
-
|
|
83505
|
-
|
|
83506
|
-
|
|
83637
|
+
writeFileSync23(join56(outputDir, "AGENTS.md"), prompt, "utf-8");
|
|
83638
|
+
writeFileSync23(join56(outputDir, "CLAUDE.md"), prompt, "utf-8");
|
|
83639
|
+
writeFileSync23(join56(outputDir, ".cursorrules"), prompt, "utf-8");
|
|
83507
83640
|
}
|
|
83508
83641
|
function buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries) {
|
|
83509
83642
|
const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
|
|
@@ -83570,15 +83703,15 @@ var init_agentPromptGenerator = __esm({
|
|
|
83570
83703
|
});
|
|
83571
83704
|
|
|
83572
83705
|
// src/capture/scaffolding.ts
|
|
83573
|
-
import { existsSync as
|
|
83574
|
-
import { join as
|
|
83706
|
+
import { existsSync as existsSync53, writeFileSync as writeFileSync24, readFileSync as readFileSync39 } from "fs";
|
|
83707
|
+
import { join as join57, resolve as resolve37 } from "path";
|
|
83575
83708
|
function loadEnvFile(startDir) {
|
|
83576
83709
|
try {
|
|
83577
83710
|
let dir = resolve37(startDir);
|
|
83578
83711
|
for (let i2 = 0; i2 < 5; i2++) {
|
|
83579
83712
|
const envPath = resolve37(dir, ".env");
|
|
83580
83713
|
try {
|
|
83581
|
-
const envContent =
|
|
83714
|
+
const envContent = readFileSync39(envPath, "utf-8");
|
|
83582
83715
|
for (const line of envContent.split("\n")) {
|
|
83583
83716
|
const trimmed = line.trim();
|
|
83584
83717
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -83597,10 +83730,10 @@ function loadEnvFile(startDir) {
|
|
|
83597
83730
|
}
|
|
83598
83731
|
}
|
|
83599
83732
|
async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
|
|
83600
|
-
const metaPath =
|
|
83601
|
-
if (!
|
|
83733
|
+
const metaPath = join57(outputDir, "meta.json");
|
|
83734
|
+
if (!existsSync53(metaPath)) {
|
|
83602
83735
|
const hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
83603
|
-
|
|
83736
|
+
writeFileSync24(
|
|
83604
83737
|
metaPath,
|
|
83605
83738
|
JSON.stringify({ id: hostname + "-video", name: tokens.title || hostname }, null, 2),
|
|
83606
83739
|
"utf-8"
|
|
@@ -83635,11 +83768,11 @@ var screenshotCapture_exports = {};
|
|
|
83635
83768
|
__export(screenshotCapture_exports, {
|
|
83636
83769
|
captureScrollScreenshots: () => captureScrollScreenshots
|
|
83637
83770
|
});
|
|
83638
|
-
import { writeFileSync as
|
|
83639
|
-
import { join as
|
|
83771
|
+
import { writeFileSync as writeFileSync25, mkdirSync as mkdirSync30 } from "fs";
|
|
83772
|
+
import { join as join58 } from "path";
|
|
83640
83773
|
async function captureScrollScreenshots(page, outputDir) {
|
|
83641
|
-
const screenshotsDir =
|
|
83642
|
-
|
|
83774
|
+
const screenshotsDir = join58(outputDir, "screenshots");
|
|
83775
|
+
mkdirSync30(screenshotsDir, { recursive: true });
|
|
83643
83776
|
const MAX_SCREENSHOTS = 20;
|
|
83644
83777
|
const filePaths = [];
|
|
83645
83778
|
try {
|
|
@@ -83672,9 +83805,9 @@ async function captureScrollScreenshots(page, outputDir) {
|
|
|
83672
83805
|
finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
|
|
83673
83806
|
);
|
|
83674
83807
|
const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
|
|
83675
|
-
const filePath =
|
|
83808
|
+
const filePath = join58(screenshotsDir, filename);
|
|
83676
83809
|
const buffer = await page.screenshot({ type: "png" });
|
|
83677
|
-
|
|
83810
|
+
writeFileSync25(filePath, buffer);
|
|
83678
83811
|
filePaths.push(`screenshots/${filename}`);
|
|
83679
83812
|
}
|
|
83680
83813
|
await page.evaluate(`window.scrollTo(0, 0)`);
|
|
@@ -83985,8 +84118,8 @@ var capture_exports = {};
|
|
|
83985
84118
|
__export(capture_exports, {
|
|
83986
84119
|
captureWebsite: () => captureWebsite
|
|
83987
84120
|
});
|
|
83988
|
-
import { mkdirSync as
|
|
83989
|
-
import { join as
|
|
84121
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync26, existsSync as existsSync54 } from "fs";
|
|
84122
|
+
import { join as join59 } from "path";
|
|
83990
84123
|
async function captureWebsite(opts, onProgress) {
|
|
83991
84124
|
const {
|
|
83992
84125
|
url,
|
|
@@ -84003,9 +84136,9 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84003
84136
|
onProgress?.(stage, detail);
|
|
84004
84137
|
};
|
|
84005
84138
|
loadEnvFile(outputDir);
|
|
84006
|
-
|
|
84007
|
-
|
|
84008
|
-
|
|
84139
|
+
mkdirSync31(join59(outputDir, "extracted"), { recursive: true });
|
|
84140
|
+
mkdirSync31(join59(outputDir, "screenshots"), { recursive: true });
|
|
84141
|
+
mkdirSync31(join59(outputDir, "assets"), { recursive: true });
|
|
84009
84142
|
progress("browser", "Launching headless Chrome...");
|
|
84010
84143
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
84011
84144
|
const browser = await ensureBrowser2();
|
|
@@ -84161,8 +84294,8 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84161
84294
|
} catch {
|
|
84162
84295
|
}
|
|
84163
84296
|
if (discoveredLotties.length > 0) {
|
|
84164
|
-
const lottieDir =
|
|
84165
|
-
|
|
84297
|
+
const lottieDir = join59(outputDir, "assets", "lottie");
|
|
84298
|
+
mkdirSync31(lottieDir, { recursive: true });
|
|
84166
84299
|
const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
|
|
84167
84300
|
if (savedCount > 0) {
|
|
84168
84301
|
await renderLottiePreviews(chromeBrowser, lottieDir, outputDir);
|
|
@@ -84180,8 +84313,8 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84180
84313
|
return true;
|
|
84181
84314
|
});
|
|
84182
84315
|
capturedShaders = unique;
|
|
84183
|
-
|
|
84184
|
-
|
|
84316
|
+
writeFileSync26(
|
|
84317
|
+
join59(outputDir, "extracted", "shaders.json"),
|
|
84185
84318
|
JSON.stringify(unique, null, 2),
|
|
84186
84319
|
"utf-8"
|
|
84187
84320
|
);
|
|
@@ -84191,8 +84324,8 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84191
84324
|
}
|
|
84192
84325
|
progress("tokens", "Extracting design tokens...");
|
|
84193
84326
|
const tokens = await extractTokens(page1);
|
|
84194
|
-
|
|
84195
|
-
|
|
84327
|
+
writeFileSync26(
|
|
84328
|
+
join59(outputDir, "extracted", "tokens.json"),
|
|
84196
84329
|
JSON.stringify(tokens, null, 2),
|
|
84197
84330
|
"utf-8"
|
|
84198
84331
|
);
|
|
@@ -84265,8 +84398,8 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84265
84398
|
scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
|
|
84266
84399
|
representativeAnimations: representativeAnims
|
|
84267
84400
|
};
|
|
84268
|
-
|
|
84269
|
-
|
|
84401
|
+
writeFileSync26(
|
|
84402
|
+
join59(outputDir, "extracted", "animations.json"),
|
|
84270
84403
|
JSON.stringify(leanCatalog, null, 2),
|
|
84271
84404
|
"utf-8"
|
|
84272
84405
|
);
|
|
@@ -84277,18 +84410,18 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84277
84410
|
assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
|
|
84278
84411
|
}
|
|
84279
84412
|
if (visibleTextContent) {
|
|
84280
|
-
|
|
84413
|
+
writeFileSync26(join59(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
|
|
84281
84414
|
}
|
|
84282
84415
|
if (catalogedAssets.length > 0) {
|
|
84283
|
-
|
|
84284
|
-
|
|
84416
|
+
writeFileSync26(
|
|
84417
|
+
join59(outputDir, "extracted", "assets-catalog.json"),
|
|
84285
84418
|
JSON.stringify(catalogedAssets, null, 2),
|
|
84286
84419
|
"utf-8"
|
|
84287
84420
|
);
|
|
84288
84421
|
}
|
|
84289
84422
|
if (detectedLibraries.length > 0) {
|
|
84290
|
-
|
|
84291
|
-
|
|
84423
|
+
writeFileSync26(
|
|
84424
|
+
join59(outputDir, "extracted", "detected-libraries.json"),
|
|
84292
84425
|
JSON.stringify(detectedLibraries, null, 2),
|
|
84293
84426
|
"utf-8"
|
|
84294
84427
|
);
|
|
@@ -84298,8 +84431,8 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84298
84431
|
try {
|
|
84299
84432
|
const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
|
|
84300
84433
|
if (lines.length > 0) {
|
|
84301
|
-
|
|
84302
|
-
|
|
84434
|
+
writeFileSync26(
|
|
84435
|
+
join59(outputDir, "extracted", "asset-descriptions.md"),
|
|
84303
84436
|
"# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
|
|
84304
84437
|
"utf-8"
|
|
84305
84438
|
);
|
|
@@ -84315,7 +84448,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
84315
84448
|
animationCatalog,
|
|
84316
84449
|
screenshots.length > 0,
|
|
84317
84450
|
discoveredLotties.length > 0,
|
|
84318
|
-
|
|
84451
|
+
existsSync54(join59(outputDir, "extracted", "shaders.json")),
|
|
84319
84452
|
catalogedAssets,
|
|
84320
84453
|
progress,
|
|
84321
84454
|
warnings,
|
|
@@ -84494,11 +84627,11 @@ var init_capture2 = __esm({
|
|
|
84494
84627
|
} catch (err) {
|
|
84495
84628
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
84496
84629
|
try {
|
|
84497
|
-
const { mkdirSync:
|
|
84498
|
-
|
|
84630
|
+
const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync27 } = await import("fs");
|
|
84631
|
+
mkdirSync33(outputDir, { recursive: true });
|
|
84499
84632
|
const isTimeout = /timeout|timed out/i.test(errMsg);
|
|
84500
84633
|
const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
|
|
84501
|
-
|
|
84634
|
+
writeFileSync27(
|
|
84502
84635
|
`${outputDir}/BLOCKED.md`,
|
|
84503
84636
|
`# Capture Failed
|
|
84504
84637
|
|
|
@@ -84661,10 +84794,10 @@ __export(autoUpdate_exports, {
|
|
|
84661
84794
|
reportCompletedUpdate: () => reportCompletedUpdate,
|
|
84662
84795
|
scheduleBackgroundInstall: () => scheduleBackgroundInstall
|
|
84663
84796
|
});
|
|
84664
|
-
import { spawn as
|
|
84665
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
84797
|
+
import { spawn as spawn13 } from "child_process";
|
|
84798
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync32, openSync } from "fs";
|
|
84666
84799
|
import { homedir as homedir10 } from "os";
|
|
84667
|
-
import { join as
|
|
84800
|
+
import { join as join60 } from "path";
|
|
84668
84801
|
import { compareVersions as compareVersions2 } from "compare-versions";
|
|
84669
84802
|
function isAutoInstallDisabled() {
|
|
84670
84803
|
if (isDevMode()) return true;
|
|
@@ -84679,15 +84812,15 @@ function majorOf(version) {
|
|
|
84679
84812
|
}
|
|
84680
84813
|
function log(line) {
|
|
84681
84814
|
try {
|
|
84682
|
-
|
|
84815
|
+
mkdirSync32(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
84683
84816
|
appendFileSync2(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
84684
84817
|
`, { mode: 384 });
|
|
84685
84818
|
} catch {
|
|
84686
84819
|
}
|
|
84687
84820
|
}
|
|
84688
84821
|
function launchDetachedInstall(installCommand, version) {
|
|
84689
|
-
|
|
84690
|
-
const configFile =
|
|
84822
|
+
mkdirSync32(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
84823
|
+
const configFile = join60(CONFIG_DIR2, "config.json");
|
|
84691
84824
|
const nodeScript = `
|
|
84692
84825
|
const { exec } = require("node:child_process");
|
|
84693
84826
|
const { readFileSync, renameSync, writeFileSync } = require("node:fs");
|
|
@@ -84712,7 +84845,7 @@ function launchDetachedInstall(installCommand, version) {
|
|
|
84712
84845
|
});
|
|
84713
84846
|
`;
|
|
84714
84847
|
const out = openSync(LOG_FILE, "a", 384);
|
|
84715
|
-
const child =
|
|
84848
|
+
const child = spawn13(process.execPath, ["-e", nodeScript], {
|
|
84716
84849
|
detached: true,
|
|
84717
84850
|
stdio: ["ignore", out, out],
|
|
84718
84851
|
windowsHide: true,
|
|
@@ -84806,8 +84939,8 @@ var init_autoUpdate = __esm({
|
|
|
84806
84939
|
init_config();
|
|
84807
84940
|
init_env();
|
|
84808
84941
|
init_installerDetection();
|
|
84809
|
-
CONFIG_DIR2 =
|
|
84810
|
-
LOG_FILE =
|
|
84942
|
+
CONFIG_DIR2 = join60(homedir10(), ".hyperframes");
|
|
84943
|
+
LOG_FILE = join60(CONFIG_DIR2, "auto-update.log");
|
|
84811
84944
|
PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
84812
84945
|
}
|
|
84813
84946
|
});
|