@hyperframes/studio-server 0.8.188 → 0.8.189
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/{chunk-T5CGF7VZ.js → chunk-HTHV7ZM6.js} +4 -4
- package/dist/{chunk-25IT6FMR.js → chunk-N2HH4SGD.js} +212 -74
- package/dist/{chunk-OVOXGASQ.js → chunk-XMNHDWQI.js} +3 -1
- package/dist/{chunk-XM2TJIF5.js → chunk-YIMSBQIO.js} +54 -22
- package/dist/helpers/mediaCodecMap.js +1 -1
- package/dist/helpers/mediaProxyPreview.d.ts +1 -1
- package/dist/helpers/mediaProxyPreview.js +3 -3
- package/dist/helpers/proxyTranscoder.d.ts +1 -0
- package/dist/helpers/proxyTranscoder.js +2 -2
- package/dist/history/index.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/{mediaProxyPreview-B5j7l9r4.d.ts → mediaProxyPreview-CAiGJucG.d.ts} +1 -1
- package/package.json +3 -3
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROXY_PARAMS_VERSION,
|
|
3
3
|
resolveProxy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-N2HH4SGD.js";
|
|
5
5
|
import {
|
|
6
6
|
createMediaCodecProbeCache,
|
|
7
7
|
proxyVariantFor,
|
|
8
8
|
recordProxyPrewarm,
|
|
9
9
|
scanProjectMediaCodecMap,
|
|
10
10
|
shouldPrewarmProxy
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XMNHDWQI.js";
|
|
12
12
|
|
|
13
13
|
// src/helpers/mediaProxyPreview.ts
|
|
14
14
|
import { resolve } from "path";
|
|
@@ -24,7 +24,7 @@ function proxyEtagSalt(raw, box) {
|
|
|
24
24
|
if (raw === void 0) return "";
|
|
25
25
|
return `:proxy:${raw}:${PROXY_PARAMS_VERSION}${box ? `:${formatPreviewProxyBox(box)}` : ""}`;
|
|
26
26
|
}
|
|
27
|
-
async function injectMediaCodecMapIntoHtml(html, projectDir, htmlSources, probeCache, prewarm = true, signal) {
|
|
27
|
+
async function injectMediaCodecMapIntoHtml(html, projectDir, htmlSources, probeCache, prewarm = true, signal, box) {
|
|
28
28
|
let map;
|
|
29
29
|
try {
|
|
30
30
|
map = await scanProjectMediaCodecMap(
|
|
@@ -43,7 +43,7 @@ async function injectMediaCodecMapIntoHtml(html, projectDir, htmlSources, probeC
|
|
|
43
43
|
projectDir,
|
|
44
44
|
resolve(projectDir, rootRelativePathname.replace(/^\/+/, "")),
|
|
45
45
|
proxyVariantFor(facts),
|
|
46
|
-
|
|
46
|
+
box,
|
|
47
47
|
{ signal }
|
|
48
48
|
).catch(() => {
|
|
49
49
|
});
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
PROXY_VARIANT_CONFIG,
|
|
3
3
|
probeFirstFrameColour,
|
|
4
4
|
probeMediaMetadata
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XMNHDWQI.js";
|
|
6
6
|
import {
|
|
7
7
|
mkdirWithinProject,
|
|
8
8
|
realProjectRoot,
|
|
@@ -12,8 +12,18 @@ import {
|
|
|
12
12
|
// src/helpers/proxyTranscoder.ts
|
|
13
13
|
import { spawn } from "child_process";
|
|
14
14
|
import { createHash, randomUUID } from "crypto";
|
|
15
|
-
import {
|
|
16
|
-
|
|
15
|
+
import {
|
|
16
|
+
existsSync as existsSync2,
|
|
17
|
+
mkdtempSync,
|
|
18
|
+
renameSync,
|
|
19
|
+
rmSync,
|
|
20
|
+
statSync as statSync2,
|
|
21
|
+
unlinkSync as unlinkSync2,
|
|
22
|
+
utimesSync,
|
|
23
|
+
writeFileSync
|
|
24
|
+
} from "fs";
|
|
25
|
+
import { tmpdir } from "os";
|
|
26
|
+
import { basename, dirname, extname as extname2, isAbsolute, join as join2, relative, resolve, sep } from "path";
|
|
17
27
|
import {
|
|
18
28
|
formatPreviewProxyBox,
|
|
19
29
|
hdrToSdrToneMapFilter
|
|
@@ -31,7 +41,9 @@ var PROXY_EXTENSIONS = new Set(
|
|
|
31
41
|
Object.values(PROXY_VARIANT_CONFIG).map(({ extension }) => extension)
|
|
32
42
|
);
|
|
33
43
|
var TRANSCODER_PROXY_NAME = /^[0-9a-f]{64}\.\w+$/;
|
|
34
|
-
var TRANSCODER_TEMP_NAME = /^\.tmp-[0-9a-f-]{36}-[0-9a-f]{64}\.\w+$/;
|
|
44
|
+
var TRANSCODER_TEMP_NAME = /^\.tmp-[0-9a-f-]{36}-(?:\.part-[0-9a-f]{64}-\d+|[0-9a-f]{64})\.\w+$/;
|
|
45
|
+
var TRANSCODER_PIECE_NAME = /^\.part-([0-9a-f]{64})-\d+(\.\w+)$/;
|
|
46
|
+
var STALE_PIECE_MS = 60 * 60 * 1e3;
|
|
35
47
|
var lastSweepAt = /* @__PURE__ */ new Map();
|
|
36
48
|
function positiveEnvNumber(name, fallback) {
|
|
37
49
|
const parsed = Number(process.env[name]);
|
|
@@ -54,6 +66,15 @@ function shouldSkipSweep(cacheDir, now, minSweepIntervalMs) {
|
|
|
54
66
|
lastSweepAt.set(cacheDir, now);
|
|
55
67
|
return false;
|
|
56
68
|
}
|
|
69
|
+
function isLeftoverName(name) {
|
|
70
|
+
return TRANSCODER_TEMP_NAME.test(name) || TRANSCODER_PIECE_NAME.test(name);
|
|
71
|
+
}
|
|
72
|
+
function leftoverIsDead(cacheDir, name, modifiedAt, protectedPaths, now, staleTempMs) {
|
|
73
|
+
const piece = TRANSCODER_PIECE_NAME.exec(name);
|
|
74
|
+
if (!piece) return now - modifiedAt >= staleTempMs;
|
|
75
|
+
const copyIsRunning = protectedPaths.has(join(cacheDir, `${piece[1]}${piece[2]}`));
|
|
76
|
+
return !copyIsRunning && now - modifiedAt >= STALE_PIECE_MS;
|
|
77
|
+
}
|
|
57
78
|
function readCacheInventory(cacheDir, protectedPaths, now, staleTempMs) {
|
|
58
79
|
const entries = [];
|
|
59
80
|
const staleTemps = [];
|
|
@@ -67,8 +88,10 @@ function readCacheInventory(cacheDir, protectedPaths, now, staleTempMs) {
|
|
|
67
88
|
modifiedAt: stat.mtimeMs,
|
|
68
89
|
protected: protectedPaths.has(path)
|
|
69
90
|
};
|
|
70
|
-
if (
|
|
71
|
-
if (
|
|
91
|
+
if (isLeftoverName(dirent.name)) {
|
|
92
|
+
if (leftoverIsDead(cacheDir, dirent.name, stat.mtimeMs, protectedPaths, now, staleTempMs)) {
|
|
93
|
+
staleTemps.push(entry);
|
|
94
|
+
}
|
|
72
95
|
} else if (TRANSCODER_PROXY_NAME.test(dirent.name) && PROXY_EXTENSIONS.has(extname(dirent.name))) {
|
|
73
96
|
entries.push(entry);
|
|
74
97
|
}
|
|
@@ -133,11 +156,15 @@ var MAX_CONCURRENT_TRANSCODES = boundedEnvInteger("HYPERFRAMES_PROXY_MAX_CONCURR
|
|
|
133
156
|
var MAX_QUEUED_TRANSCODES = boundedEnvInteger("HYPERFRAMES_PROXY_MAX_QUEUE", 8, 0, 256);
|
|
134
157
|
var STDERR_TAIL_MAX_CHARS = 4e3;
|
|
135
158
|
var TRANSCODE_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
159
|
+
var PROXY_CHUNK_SECONDS = 60;
|
|
160
|
+
var CHUNK_PREFIX = ".part-";
|
|
161
|
+
var CONCAT_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
136
162
|
var FAILURE_CACHE_TTL_MS = 60 * 1e3;
|
|
137
163
|
var PROXY_PENDING_RETRY_AFTER_SECONDS = 2;
|
|
138
164
|
var ENVIRONMENT_FAILURE_TTL_MS = 5 * PROXY_PENDING_RETRY_AFTER_SECONDS * 1e3;
|
|
139
165
|
var MAX_FAILURE_CACHE_ENTRIES = 128;
|
|
140
166
|
var DEFAULT_PROXY_WAIT_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
167
|
+
var UNTOUCHED_TEMP_IS_DEAD_MS = 10 * 60 * 1e3;
|
|
141
168
|
var ProxyTranscodeError = class extends Error {
|
|
142
169
|
exitCode;
|
|
143
170
|
stderrTail;
|
|
@@ -305,9 +332,9 @@ var inFlight = /* @__PURE__ */ new Map();
|
|
|
305
332
|
function forget(job) {
|
|
306
333
|
if (inFlight.get(job.cachePath)?.job === job) inFlight.delete(job.cachePath);
|
|
307
334
|
}
|
|
308
|
-
function maintainProxyCache(cacheDir) {
|
|
335
|
+
function maintainProxyCache(cacheDir, staleTempMs) {
|
|
309
336
|
try {
|
|
310
|
-
cleanupProxyCache(cacheDir, { protectedPaths: new Set(inFlight.keys()) });
|
|
337
|
+
cleanupProxyCache(cacheDir, { protectedPaths: new Set(inFlight.keys()), staleTempMs });
|
|
311
338
|
} catch (error) {
|
|
312
339
|
console.warn(
|
|
313
340
|
`[media-proxy] cache cleanup failed: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -372,83 +399,173 @@ function stderrReason(stderrTail) {
|
|
|
372
399
|
const line = errorLines.at(-1) ?? lines.at(-1);
|
|
373
400
|
return line ? `: ${line.replace(/[.!]+$/, "")}` : "";
|
|
374
401
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
402
|
+
function chunkRanges(durationSeconds) {
|
|
403
|
+
if (!durationSeconds || durationSeconds <= PROXY_CHUNK_SECONDS * 1.5) return null;
|
|
404
|
+
const count = Math.floor(durationSeconds / PROXY_CHUNK_SECONDS);
|
|
405
|
+
return Array.from({ length: count }, (_, index) => ({
|
|
406
|
+
startSeconds: index * PROXY_CHUNK_SECONDS,
|
|
407
|
+
lengthSeconds: index === count - 1 ? durationSeconds - index * PROXY_CHUNK_SECONDS : PROXY_CHUNK_SECONDS
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
function ffmpegBudgetError(chunksKept, chunkCount) {
|
|
411
|
+
return new ProxyTranscodeError(
|
|
412
|
+
`ffmpeg ran out of its ${TRANSCODE_TIMEOUT_MS}ms budget with ${chunksKept}/${chunkCount} pieces done; the finished pieces are kept and the next attempt continues from them`,
|
|
413
|
+
null,
|
|
414
|
+
""
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
async function encodeInChunks(ranges, chunkPrefix, tempPath, encode, concat) {
|
|
418
|
+
const extension = extname2(tempPath);
|
|
419
|
+
const deadline = Date.now() + TRANSCODE_TIMEOUT_MS;
|
|
420
|
+
const pieces = ranges.map((_, index) => `${chunkPrefix}${index}${extension}`);
|
|
421
|
+
for (const [index, range] of ranges.entries()) {
|
|
422
|
+
const piece = pieces[index];
|
|
423
|
+
if (existsSync2(piece)) continue;
|
|
424
|
+
const timeoutMs = deadline - Date.now();
|
|
425
|
+
if (timeoutMs <= 0) throw ffmpegBudgetError(index, ranges.length);
|
|
426
|
+
const pieceTemp = join2(dirname(piece), `.tmp-${randomUUID()}-${basename(piece)}`);
|
|
427
|
+
try {
|
|
428
|
+
await encode(pieceTemp, timeoutMs, range);
|
|
429
|
+
renameSync(pieceTemp, piece);
|
|
430
|
+
} finally {
|
|
431
|
+
if (existsSync2(pieceTemp)) unlinkSync2(pieceTemp);
|
|
432
|
+
}
|
|
380
433
|
}
|
|
381
|
-
const
|
|
434
|
+
const listDir = mkdtempSync(join2(tmpdir(), "hf-proxy-join-"));
|
|
435
|
+
try {
|
|
436
|
+
const listPath = join2(listDir, "pieces.txt");
|
|
437
|
+
writeFileSync(
|
|
438
|
+
listPath,
|
|
439
|
+
pieces.map((piece) => `file '${piece.replace(/\\/g, "/").replace(/'/g, "'\\''")}'
|
|
440
|
+
`).join("")
|
|
441
|
+
);
|
|
442
|
+
await concat(listPath, tempPath);
|
|
443
|
+
} finally {
|
|
444
|
+
rmSync(listDir, { recursive: true, force: true });
|
|
445
|
+
}
|
|
446
|
+
for (const piece of pieces) if (existsSync2(piece)) unlinkSync2(piece);
|
|
447
|
+
}
|
|
448
|
+
var H264_ARGS = [
|
|
449
|
+
"-c:v",
|
|
450
|
+
"libx264",
|
|
451
|
+
"-profile:v",
|
|
452
|
+
"high",
|
|
453
|
+
"-pix_fmt",
|
|
454
|
+
"yuv420p",
|
|
455
|
+
"-colorspace",
|
|
456
|
+
"bt709",
|
|
457
|
+
"-color_primaries",
|
|
458
|
+
"bt709",
|
|
459
|
+
"-color_trc",
|
|
460
|
+
"bt709",
|
|
461
|
+
"-crf",
|
|
462
|
+
"18",
|
|
463
|
+
"-preset",
|
|
464
|
+
"veryfast",
|
|
465
|
+
"-c:a",
|
|
466
|
+
"aac",
|
|
467
|
+
"-movflags",
|
|
468
|
+
"+faststart"
|
|
469
|
+
];
|
|
470
|
+
var VP8_ARGS = [
|
|
471
|
+
"-c:v",
|
|
472
|
+
"libvpx",
|
|
473
|
+
"-b:v",
|
|
474
|
+
"0",
|
|
475
|
+
"-crf",
|
|
476
|
+
"23",
|
|
477
|
+
"-deadline",
|
|
478
|
+
"good",
|
|
479
|
+
"-pix_fmt",
|
|
480
|
+
"yuva420p",
|
|
481
|
+
"-colorspace",
|
|
482
|
+
"bt709",
|
|
483
|
+
"-color_primaries",
|
|
484
|
+
"bt709",
|
|
485
|
+
"-color_trc",
|
|
486
|
+
"bt709",
|
|
487
|
+
"-cpu-used",
|
|
488
|
+
"4",
|
|
489
|
+
"-auto-alt-ref",
|
|
490
|
+
"0",
|
|
491
|
+
"-metadata:s:v:0",
|
|
492
|
+
"alpha_mode=1",
|
|
493
|
+
"-ac",
|
|
494
|
+
"2",
|
|
495
|
+
"-c:a",
|
|
496
|
+
"libopus"
|
|
497
|
+
];
|
|
498
|
+
async function buildVideoFilter(ffmpegPath, sourcePath, metadata, keepsAlpha, box) {
|
|
382
499
|
const { hdrTransfer } = metadata.color;
|
|
383
500
|
const toneMap = (hdrTransfer === "pq" || hdrTransfer === "hlg") && !keepsAlpha;
|
|
384
501
|
if (toneMap) await ensureHdrFilters(ffmpegPath);
|
|
385
502
|
const firstFrame = toneMap ? await probeFirstFrameColour(sourcePath) : {};
|
|
386
503
|
const evenScale = proxyScaleFilter(box);
|
|
387
504
|
const pixelFormat = keepsAlpha ? "yuva420p" : "yuv420p";
|
|
388
|
-
|
|
505
|
+
return toneMap ? [
|
|
389
506
|
hdrToSdrToneMapFilter(metadata.color, firstFrame),
|
|
390
507
|
`${evenScale}:out_color_matrix=bt709:out_range=tv`,
|
|
391
508
|
`format=${pixelFormat}`
|
|
392
509
|
].join(",") : [evenScale, `format=${pixelFormat}`].join(",");
|
|
510
|
+
}
|
|
511
|
+
async function runFfmpeg(sourcePath, outputPath, chunkPrefix, variant, box, signal) {
|
|
512
|
+
const metadata = await probeMediaMetadata(sourcePath);
|
|
513
|
+
const ffmpegPath = findFfBinary("ffmpeg", { configuredMustExist: true });
|
|
514
|
+
if (!ffmpegPath) {
|
|
515
|
+
throw new FfmpegUnavailableError();
|
|
516
|
+
}
|
|
517
|
+
const keepsAlpha = variant === "vp8";
|
|
518
|
+
const videoFilter = await buildVideoFilter(ffmpegPath, sourcePath, metadata, keepsAlpha, box);
|
|
519
|
+
const alphaDecoder = keepsAlpha ? alphaDecoderFor(metadata.color.codecName) : null;
|
|
520
|
+
const decoderArgs = alphaDecoder ? ["-c:v", alphaDecoder] : [];
|
|
521
|
+
const encode = (target, timeoutMs, range) => spawnFfmpeg(
|
|
522
|
+
ffmpegPath,
|
|
523
|
+
[
|
|
524
|
+
"-y",
|
|
525
|
+
...range ? ["-ss", String(range.startSeconds)] : [],
|
|
526
|
+
...decoderArgs,
|
|
527
|
+
"-i",
|
|
528
|
+
sourcePath,
|
|
529
|
+
...range ? ["-t", String(range.lengthSeconds)] : [],
|
|
530
|
+
"-vf",
|
|
531
|
+
videoFilter,
|
|
532
|
+
...variant === "vp8" ? VP8_ARGS : H264_ARGS,
|
|
533
|
+
target
|
|
534
|
+
],
|
|
535
|
+
timeoutMs,
|
|
536
|
+
signal
|
|
537
|
+
);
|
|
538
|
+
const ranges = chunkRanges(metadata.durationSeconds);
|
|
539
|
+
if (!ranges) return encode(outputPath, TRANSCODE_TIMEOUT_MS);
|
|
540
|
+
await encodeInChunks(
|
|
541
|
+
ranges,
|
|
542
|
+
chunkPrefix,
|
|
543
|
+
outputPath,
|
|
544
|
+
encode,
|
|
545
|
+
(listPath, target) => spawnFfmpeg(ffmpegPath, concatArgs(listPath, target, variant), CONCAT_TIMEOUT_MS, signal)
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
function concatArgs(listPath, target, variant) {
|
|
549
|
+
return [
|
|
550
|
+
"-y",
|
|
551
|
+
"-f",
|
|
552
|
+
"concat",
|
|
553
|
+
"-safe",
|
|
554
|
+
"0",
|
|
555
|
+
"-i",
|
|
556
|
+
listPath,
|
|
557
|
+
"-c",
|
|
558
|
+
"copy",
|
|
559
|
+
...variant === "h264" ? ["-movflags", "+faststart"] : [],
|
|
560
|
+
target
|
|
561
|
+
];
|
|
562
|
+
}
|
|
563
|
+
function spawnFfmpeg(ffmpegPath, args, timeoutMs, signal) {
|
|
393
564
|
return new Promise((resolvePromise, reject) => {
|
|
394
|
-
const alphaDecoder = keepsAlpha ? alphaDecoderFor(metadata.color.codecName) : null;
|
|
395
|
-
const decoderArgs = alphaDecoder ? ["-c:v", alphaDecoder] : [];
|
|
396
|
-
const commonArgs = ["-y", ...decoderArgs, "-i", sourcePath, "-vf", videoFilter];
|
|
397
|
-
const h264Args = [
|
|
398
|
-
"-c:v",
|
|
399
|
-
"libx264",
|
|
400
|
-
"-profile:v",
|
|
401
|
-
"high",
|
|
402
|
-
"-pix_fmt",
|
|
403
|
-
"yuv420p",
|
|
404
|
-
"-colorspace",
|
|
405
|
-
"bt709",
|
|
406
|
-
"-color_primaries",
|
|
407
|
-
"bt709",
|
|
408
|
-
"-color_trc",
|
|
409
|
-
"bt709",
|
|
410
|
-
"-crf",
|
|
411
|
-
"18",
|
|
412
|
-
"-preset",
|
|
413
|
-
"veryfast",
|
|
414
|
-
"-c:a",
|
|
415
|
-
"aac",
|
|
416
|
-
"-movflags",
|
|
417
|
-
"+faststart"
|
|
418
|
-
];
|
|
419
|
-
const vp8Args = [
|
|
420
|
-
"-c:v",
|
|
421
|
-
"libvpx",
|
|
422
|
-
"-b:v",
|
|
423
|
-
"0",
|
|
424
|
-
"-crf",
|
|
425
|
-
"23",
|
|
426
|
-
"-deadline",
|
|
427
|
-
"good",
|
|
428
|
-
"-pix_fmt",
|
|
429
|
-
"yuva420p",
|
|
430
|
-
"-colorspace",
|
|
431
|
-
"bt709",
|
|
432
|
-
"-color_primaries",
|
|
433
|
-
"bt709",
|
|
434
|
-
"-color_trc",
|
|
435
|
-
"bt709",
|
|
436
|
-
"-cpu-used",
|
|
437
|
-
"4",
|
|
438
|
-
"-auto-alt-ref",
|
|
439
|
-
"0",
|
|
440
|
-
"-metadata:s:v:0",
|
|
441
|
-
"alpha_mode=1",
|
|
442
|
-
"-ac",
|
|
443
|
-
"2",
|
|
444
|
-
"-c:a",
|
|
445
|
-
"libopus"
|
|
446
|
-
];
|
|
447
|
-
const args = [...commonArgs, ...variant === "vp8" ? vp8Args : h264Args, outputPath];
|
|
448
565
|
signal.throwIfAborted();
|
|
449
566
|
const proc = spawn(ffmpegPath, args, {
|
|
450
567
|
stdio: ["ignore", "ignore", "pipe"],
|
|
451
|
-
timeout:
|
|
568
|
+
timeout: timeoutMs,
|
|
452
569
|
killSignal: "SIGKILL",
|
|
453
570
|
signal,
|
|
454
571
|
windowsHide: true
|
|
@@ -467,7 +584,7 @@ async function runFfmpeg(sourcePath, outputPath, variant, box, signal) {
|
|
|
467
584
|
} else if (signal2) {
|
|
468
585
|
reject(
|
|
469
586
|
new ProxyTranscodeError(
|
|
470
|
-
`ffmpeg killed by ${signal2} (timeout ${
|
|
587
|
+
`ffmpeg killed by ${signal2} (timeout ${timeoutMs}ms or external kill)`,
|
|
471
588
|
null,
|
|
472
589
|
stderrTail
|
|
473
590
|
)
|
|
@@ -492,7 +609,18 @@ async function transcodeToCache(job, projectDir, absoluteSourcePath, cachePath,
|
|
|
492
609
|
mkdirWithinProject(projectDir, cacheDir);
|
|
493
610
|
const tempPath = join2(cacheDir, `.tmp-${randomUUID()}-${basename(cachePath)}`);
|
|
494
611
|
try {
|
|
495
|
-
|
|
612
|
+
const chunkPrefix = join2(
|
|
613
|
+
cacheDir,
|
|
614
|
+
`${CHUNK_PREFIX}${basename(cachePath, extname2(cachePath))}-`
|
|
615
|
+
);
|
|
616
|
+
await runFfmpeg(
|
|
617
|
+
absoluteSourcePath,
|
|
618
|
+
tempPath,
|
|
619
|
+
chunkPrefix,
|
|
620
|
+
variant,
|
|
621
|
+
box,
|
|
622
|
+
job.abandoned.signal
|
|
623
|
+
);
|
|
496
624
|
renameSync(tempPath, cachePath);
|
|
497
625
|
maintainProxyCache(cacheDir);
|
|
498
626
|
return cachePath;
|
|
@@ -560,13 +688,23 @@ async function resolveProxy(projectDir, absoluteSourcePath, variant = "h264", bo
|
|
|
560
688
|
}
|
|
561
689
|
async function resolveProxies(projectDir, sources, onSettled = () => {
|
|
562
690
|
}) {
|
|
691
|
+
const first = sources[0];
|
|
692
|
+
if (first) {
|
|
693
|
+
maintainProxyCache(
|
|
694
|
+
dirname(getProxyCachePath(projectDir, first.sourcePath, first.variant)),
|
|
695
|
+
Math.min(
|
|
696
|
+
Number(process.env.HYPERFRAMES_PROXY_CACHE_STALE_TEMP_MS) || UNTOUCHED_TEMP_IS_DEAD_MS,
|
|
697
|
+
UNTOUCHED_TEMP_IS_DEAD_MS
|
|
698
|
+
)
|
|
699
|
+
);
|
|
700
|
+
}
|
|
563
701
|
const results = [];
|
|
564
702
|
let next = 0;
|
|
565
703
|
const worker = async () => {
|
|
566
704
|
for (let index = next++; index < sources.length; index = next++) {
|
|
567
|
-
const { sourcePath, variant } = sources[index];
|
|
705
|
+
const { sourcePath, variant, box } = sources[index];
|
|
568
706
|
results[index] = await waitForProxy(
|
|
569
|
-
resolveProxy(projectDir, sourcePath, variant),
|
|
707
|
+
resolveProxy(projectDir, sourcePath, variant, box),
|
|
570
708
|
TRANSCODE_TIMEOUT_MS
|
|
571
709
|
).then(
|
|
572
710
|
(value) => ({ status: "fulfilled", value }),
|
|
@@ -121,7 +121,7 @@ async function probeMediaMetadata(filePath, runner = execFileRunner) {
|
|
|
121
121
|
"-v",
|
|
122
122
|
"error",
|
|
123
123
|
"-show_entries",
|
|
124
|
-
"stream=codec_type,codec_name,profile,pix_fmt,color_space,color_transfer,color_primaries,bits_per_raw_sample:stream_disposition=attached_pic:stream_tags=alpha_mode",
|
|
124
|
+
"stream=codec_type,codec_name,profile,pix_fmt,color_space,color_transfer,color_primaries,bits_per_raw_sample:stream_disposition=attached_pic:stream_tags=alpha_mode:format=duration",
|
|
125
125
|
"-of",
|
|
126
126
|
"json",
|
|
127
127
|
"--",
|
|
@@ -145,6 +145,8 @@ async function probeMediaMetadata(filePath, runner = execFileRunner) {
|
|
|
145
145
|
if (kind === "video") {
|
|
146
146
|
metadata.hasAudio = (parsed.streams ?? []).some((item) => item.codec_type === "audio");
|
|
147
147
|
metadata.hasAlpha = stream !== void 0 && videoStreamHasAlpha(stream);
|
|
148
|
+
const duration = Number(parsed.format?.duration);
|
|
149
|
+
if (Number.isFinite(duration) && duration > 0) metadata.durationSeconds = duration;
|
|
148
150
|
}
|
|
149
151
|
return metadata;
|
|
150
152
|
} catch {
|
|
@@ -11,7 +11,7 @@ import { mkdir as mkdir2, readdir as readdir3, rm as rm3, rmdir, writeFile } fro
|
|
|
11
11
|
import {
|
|
12
12
|
existsSync as existsSync3,
|
|
13
13
|
lstatSync as lstatSync4,
|
|
14
|
-
statSync as
|
|
14
|
+
statSync as statSync5,
|
|
15
15
|
mkdirSync as mkdirSync5,
|
|
16
16
|
readdirSync as readdirSync4,
|
|
17
17
|
readFileSync as readFileSync10,
|
|
@@ -107,7 +107,15 @@ import { replaceFileAtomically } from "@hyperframes/core/atomic-file";
|
|
|
107
107
|
|
|
108
108
|
// src/history/ownerLock.ts
|
|
109
109
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
110
|
-
import {
|
|
110
|
+
import {
|
|
111
|
+
linkSync,
|
|
112
|
+
mkdirSync,
|
|
113
|
+
readFileSync,
|
|
114
|
+
renameSync,
|
|
115
|
+
rmSync,
|
|
116
|
+
statSync,
|
|
117
|
+
writeFileSync
|
|
118
|
+
} from "fs";
|
|
111
119
|
import { join } from "path";
|
|
112
120
|
var HistoryBusyError = class extends Error {
|
|
113
121
|
constructor(pid, url) {
|
|
@@ -120,6 +128,8 @@ var HistoryBusyError = class extends Error {
|
|
|
120
128
|
url;
|
|
121
129
|
};
|
|
122
130
|
var WINDOWS_BUSY = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES"]);
|
|
131
|
+
var NO_HARD_LINKS = /* @__PURE__ */ new Set(["ENOTSUP", "EOPNOTSUPP", "ENOSYS", "EPERM"]);
|
|
132
|
+
var TAKING_MS = 2e3;
|
|
123
133
|
function busyOnWindows(error) {
|
|
124
134
|
return process.platform === "win32" && WINDOWS_BUSY.has(error.code ?? "");
|
|
125
135
|
}
|
|
@@ -141,6 +151,17 @@ function ownerOf(file) {
|
|
|
141
151
|
throw error;
|
|
142
152
|
}
|
|
143
153
|
}
|
|
154
|
+
function beingTaken(file) {
|
|
155
|
+
try {
|
|
156
|
+
const { size, mtimeMs } = statSync(file);
|
|
157
|
+
return size === 0 && Date.now() - mtimeMs < TAKING_MS;
|
|
158
|
+
} catch {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function deadHolder(file, pid) {
|
|
163
|
+
return !alive(pid) && !beingTaken(file);
|
|
164
|
+
}
|
|
144
165
|
function claim(file) {
|
|
145
166
|
const draft = `${file}-${process.pid}-${randomUUID2()}.tmp`;
|
|
146
167
|
writeFileSync(draft, String(process.pid));
|
|
@@ -148,12 +169,23 @@ function claim(file) {
|
|
|
148
169
|
linkSync(draft, file);
|
|
149
170
|
return true;
|
|
150
171
|
} catch (error) {
|
|
151
|
-
|
|
152
|
-
return false;
|
|
172
|
+
const code = error.code ?? "";
|
|
173
|
+
if (code === "EEXIST") return false;
|
|
174
|
+
if (!NO_HARD_LINKS.has(code)) throw error;
|
|
175
|
+
return createExclusively(file);
|
|
153
176
|
} finally {
|
|
154
177
|
rmSync(draft, { force: true });
|
|
155
178
|
}
|
|
156
179
|
}
|
|
180
|
+
function createExclusively(file) {
|
|
181
|
+
try {
|
|
182
|
+
writeFileSync(file, String(process.pid), { flag: "wx" });
|
|
183
|
+
return true;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
if (error.code !== "EEXIST") throw error;
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
157
189
|
function releaseOwn(file) {
|
|
158
190
|
if (ownerOf(file) === process.pid) rmSync(file, { force: true });
|
|
159
191
|
}
|
|
@@ -161,12 +193,12 @@ function evictDeadOwner(file) {
|
|
|
161
193
|
const evictor = `${file}.evict`;
|
|
162
194
|
if (!claim(evictor)) {
|
|
163
195
|
const holder = ownerOf(evictor);
|
|
164
|
-
if (holder !== null &&
|
|
196
|
+
if (holder !== null && deadHolder(evictor, holder)) rmSync(evictor, { force: true });
|
|
165
197
|
return false;
|
|
166
198
|
}
|
|
167
199
|
try {
|
|
168
200
|
const pid = ownerOf(file);
|
|
169
|
-
if (pid !== null &&
|
|
201
|
+
if (pid !== null && deadHolder(file, pid)) rmSync(file, { force: true });
|
|
170
202
|
return true;
|
|
171
203
|
} finally {
|
|
172
204
|
releaseOwn(evictor);
|
|
@@ -191,7 +223,7 @@ function attemptClaim(file, urlFile, deadline) {
|
|
|
191
223
|
if (claim(file)) return "claimed";
|
|
192
224
|
const pid = ownerOf(file);
|
|
193
225
|
if (pid === null) return "retry";
|
|
194
|
-
if (
|
|
226
|
+
if (deadHolder(file, pid) && evictDeadOwner(file)) return "retry";
|
|
195
227
|
if (Date.now() >= deadline) throw new HistoryBusyError(pid, servedBy(file, urlFile, pid));
|
|
196
228
|
return "wait";
|
|
197
229
|
}
|
|
@@ -526,14 +558,14 @@ async function openBlobStore(dir) {
|
|
|
526
558
|
|
|
527
559
|
// src/history/pruneHistories.ts
|
|
528
560
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
529
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync5, renameSync as renameSync3, statSync as
|
|
561
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5, renameSync as renameSync3, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
530
562
|
import { lstat, readdir as readdir2, rm as rm2 } from "fs/promises";
|
|
531
563
|
import { tmpdir } from "os";
|
|
532
564
|
import { dirname as dirname2, join as join4 } from "path";
|
|
533
565
|
|
|
534
566
|
// src/history/historyId.ts
|
|
535
567
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
536
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
568
|
+
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
537
569
|
import { basename, join as join3, resolve as resolve3 } from "path";
|
|
538
570
|
import { replaceFileAtomically as replaceFileAtomically2 } from "@hyperframes/core/atomic-file";
|
|
539
571
|
var ID_PATH = join3(".hyperframes", "history-id");
|
|
@@ -566,7 +598,7 @@ function readRecord(historyDir) {
|
|
|
566
598
|
function isCopyOf0878Folder(recordedDir, id, folder) {
|
|
567
599
|
let there;
|
|
568
600
|
try {
|
|
569
|
-
there =
|
|
601
|
+
there = statSync2(recordedDir, { throwIfNoEntry: false });
|
|
570
602
|
} catch {
|
|
571
603
|
return false;
|
|
572
604
|
}
|
|
@@ -574,7 +606,7 @@ function isCopyOf0878Folder(recordedDir, id, folder) {
|
|
|
574
606
|
}
|
|
575
607
|
function projectHistoryId(projectDir, historyRoot) {
|
|
576
608
|
const dir = resolve3(projectDir);
|
|
577
|
-
const folder =
|
|
609
|
+
const folder = statSync2(dir);
|
|
578
610
|
let id = readId(dir);
|
|
579
611
|
if (!id && existsSync(join3(dir, ID_PATH)))
|
|
580
612
|
throw new HistoryIdError(
|
|
@@ -701,24 +733,24 @@ function abandonedProject(home, id, now, tempDir) {
|
|
|
701
733
|
return projectGone(dir, id, record?.dev, tempDir) ? dir : null;
|
|
702
734
|
}
|
|
703
735
|
function projectGone(dir, id, dev, tempDir) {
|
|
704
|
-
if (!
|
|
736
|
+
if (!statSync3(join4(dir, ID_PATH), { throwIfNoEntry: false }))
|
|
705
737
|
return diskStillHere(dir, dev, tempDir);
|
|
706
738
|
const there = readId(dir);
|
|
707
739
|
return there !== null && there !== id;
|
|
708
740
|
}
|
|
709
741
|
function diskStillHere(dir, dev, tempDir) {
|
|
710
742
|
let at = dir;
|
|
711
|
-
let stat2 =
|
|
743
|
+
let stat2 = statSync3(at, { throwIfNoEntry: false });
|
|
712
744
|
while (!stat2) {
|
|
713
745
|
if (dirname2(at) === at) return false;
|
|
714
746
|
at = dirname2(at);
|
|
715
|
-
stat2 =
|
|
747
|
+
stat2 = statSync3(at, { throwIfNoEntry: false });
|
|
716
748
|
}
|
|
717
749
|
if (typeof dev === "number") return stat2.dev === dev;
|
|
718
750
|
return at === dir || isSafePath(tempDir, at);
|
|
719
751
|
}
|
|
720
752
|
function lastUsed(home) {
|
|
721
|
-
const mtime = (file) =>
|
|
753
|
+
const mtime = (file) => statSync3(join4(home, file), { throwIfNoEntry: false })?.mtimeMs ?? 0;
|
|
722
754
|
return Math.max(mtime("project.json"), mtime("log.jsonl"));
|
|
723
755
|
}
|
|
724
756
|
async function bytesIn(dir) {
|
|
@@ -749,7 +781,7 @@ function pruneGoneProjectHistoriesDaily(historyRoot, now, { onError, budgetMs }
|
|
|
749
781
|
|
|
750
782
|
// src/history/videoState.ts
|
|
751
783
|
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
752
|
-
import { createReadStream as createReadStream2, existsSync as existsSync2, readFileSync as readFileSync8, renameSync as renameSync4, statSync as
|
|
784
|
+
import { createReadStream as createReadStream2, existsSync as existsSync2, readFileSync as readFileSync8, renameSync as renameSync4, statSync as statSync4 } from "fs";
|
|
753
785
|
import { isAbsolute as isAbsolute4, join as join7, resolve as resolve6 } from "path";
|
|
754
786
|
import { replaceFileAtomically as replaceFileAtomically3 } from "@hyperframes/core/atomic-file";
|
|
755
787
|
|
|
@@ -1320,7 +1352,7 @@ function retainRevision(retained, revision) {
|
|
|
1320
1352
|
return [revision, ...retained.filter((id) => id !== revision)].slice(0, 2);
|
|
1321
1353
|
}
|
|
1322
1354
|
async function recordRenderSuccess(projectDir, output, status = "completed", capture) {
|
|
1323
|
-
const outputFile =
|
|
1355
|
+
const outputFile = statSync4(output);
|
|
1324
1356
|
if (!outputFile.isFile() && !outputFile.isDirectory() || outputFile.isFile() && outputFile.size === 0)
|
|
1325
1357
|
throw new Error("Render output is missing or empty.");
|
|
1326
1358
|
const after = capture ? await beginArtifactCapture(projectDir) : null;
|
|
@@ -1556,8 +1588,8 @@ function fileLeftIn(dir, at, deleted) {
|
|
|
1556
1588
|
return void 0;
|
|
1557
1589
|
}
|
|
1558
1590
|
function ignoresCase(dir) {
|
|
1559
|
-
const self =
|
|
1560
|
-
const other =
|
|
1591
|
+
const self = statSync5(join8(dir, ID_PATH), { throwIfNoEntry: false });
|
|
1592
|
+
const other = statSync5(join8(dir, ID_PATH.toUpperCase()), { throwIfNoEntry: false });
|
|
1561
1593
|
return self !== void 0 && other?.ino === self.ino && other.dev === self.dev;
|
|
1562
1594
|
}
|
|
1563
1595
|
var blocks = (removed, added) => added.startsWith(`${removed}/`) || removed.startsWith(`${added}/`);
|
|
@@ -1597,7 +1629,7 @@ var Engine = class {
|
|
|
1597
1629
|
this.dir = resolve7(options.projectDir);
|
|
1598
1630
|
this.home = join8(options.historyRoot, projectId);
|
|
1599
1631
|
this.foldsCase = ignoresCase(this.dir);
|
|
1600
|
-
const folder =
|
|
1632
|
+
const folder = statSync5(this.dir, { throwIfNoEntry: false });
|
|
1601
1633
|
if (!folder || readId(this.dir) !== projectId || !isRecordedFolder(this.home, folder))
|
|
1602
1634
|
throw this.replaced();
|
|
1603
1635
|
this.folder = { dev: folder.dev, ino: folder.ino, birthtimeMs: folder.birthtimeMs };
|
|
@@ -1662,7 +1694,7 @@ var Engine = class {
|
|
|
1662
1694
|
}
|
|
1663
1695
|
/** Another project if the folder or its id changed, or the id is gone: a recreated folder may reuse the inode. */
|
|
1664
1696
|
whereFolder() {
|
|
1665
|
-
const now =
|
|
1697
|
+
const now = statSync5(this.dir, { throwIfNoEntry: false });
|
|
1666
1698
|
if (!now) return "gone";
|
|
1667
1699
|
const same = now.dev === this.folder.dev && sameFolder(now, this.folder);
|
|
1668
1700
|
return same && readId(this.dir) === this.projectId ? "here" : "replaced";
|
|
@@ -2467,7 +2499,7 @@ async function openProjectHistory(options) {
|
|
|
2467
2499
|
function readProjectHistory(options) {
|
|
2468
2500
|
const dir = resolve7(options.projectDir);
|
|
2469
2501
|
const id = readId(dir);
|
|
2470
|
-
const home = id && isRecordedFolder(join8(options.historyRoot, id),
|
|
2502
|
+
const home = id && isRecordedFolder(join8(options.historyRoot, id), statSync5(dir)) ? join8(options.historyRoot, id) : null;
|
|
2471
2503
|
const read = home && readLog(logFileIn(home), () => {
|
|
2472
2504
|
});
|
|
2473
2505
|
const log = withoutHiddenPaths(read || { baseline: /* @__PURE__ */ new Map(), entries: [], pins: /* @__PURE__ */ new Set() });
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolveProxyVariantRequest,
|
|
14
14
|
scanProjectMediaCodecMap,
|
|
15
15
|
shouldPrewarmProxy
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-XMNHDWQI.js";
|
|
17
17
|
import "../chunk-QF7MFJJU.js";
|
|
18
18
|
import "../chunk-SVQFE44C.js";
|
|
19
19
|
import "../chunk-L3HJVTQE.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '@hyperframes/core';
|
|
2
|
-
export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-
|
|
2
|
+
export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-CAiGJucG.js';
|
|
3
3
|
import './mediaCodecMap.js';
|
|
4
4
|
import 'sharp';
|
|
5
5
|
import '@hyperframes/parsers';
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
isAutoProxyEnabled,
|
|
5
5
|
proxyEtagSalt,
|
|
6
6
|
resolvePreviewMediaCodecProbeCache
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-HTHV7ZM6.js";
|
|
8
|
+
import "../chunk-N2HH4SGD.js";
|
|
9
|
+
import "../chunk-XMNHDWQI.js";
|
|
10
10
|
import "../chunk-QF7MFJJU.js";
|
|
11
11
|
import "../chunk-SVQFE44C.js";
|
|
12
12
|
import "../chunk-L3HJVTQE.js";
|
|
@@ -71,6 +71,7 @@ declare function resolveProxy(projectDir: string, absoluteSourcePath: string, va
|
|
|
71
71
|
declare function resolveProxies(projectDir: string, sources: ReadonlyArray<{
|
|
72
72
|
sourcePath: string;
|
|
73
73
|
variant: ProxyVariant;
|
|
74
|
+
box?: PreviewProxyBox;
|
|
74
75
|
}>, onSettled?: () => void): Promise<PromiseSettledResult<string>[]>;
|
|
75
76
|
interface ResolveProxyOptions {
|
|
76
77
|
priority?: boolean;
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
resolveProxies,
|
|
17
17
|
resolveProxy,
|
|
18
18
|
waitForProxy
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import "../chunk-
|
|
19
|
+
} from "../chunk-N2HH4SGD.js";
|
|
20
|
+
import "../chunk-XMNHDWQI.js";
|
|
21
21
|
import "../chunk-QF7MFJJU.js";
|
|
22
22
|
import "../chunk-SVQFE44C.js";
|
|
23
23
|
import "../chunk-L3HJVTQE.js";
|
package/dist/history/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-
|
|
3
|
-
export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-
|
|
2
|
+
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-CAiGJucG.js';
|
|
3
|
+
export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-CAiGJucG.js';
|
|
4
4
|
export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryResult, f as HistoryTarget, g as HistoryWho, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-ByC9sa3X.js';
|
|
5
5
|
export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput } from './history/index.js';
|
|
6
6
|
export { CACHE_DIR_NAME as PROXY_CACHE_DIR_NAME } from './helpers/proxyTranscoder.js';
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
resolveProjectSignature,
|
|
61
61
|
retainSnapshotOutput,
|
|
62
62
|
settledFileTag
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-YIMSBQIO.js";
|
|
64
64
|
import {
|
|
65
65
|
clearElementScreenshotIsolation,
|
|
66
66
|
getElementScreenshotClip
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
isAutoProxyEnabled,
|
|
81
81
|
proxyEtagSalt,
|
|
82
82
|
resolvePreviewMediaCodecProbeCache
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-HTHV7ZM6.js";
|
|
84
84
|
import {
|
|
85
85
|
CACHE_DIR_NAME,
|
|
86
86
|
PROXY_PENDING_RETRY_AFTER_SECONDS,
|
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
proxyActivityMark,
|
|
92
92
|
resolveProxy,
|
|
93
93
|
waitForProxy
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-N2HH4SGD.js";
|
|
95
95
|
import {
|
|
96
96
|
PROXY_VARIANT_CONFIG,
|
|
97
97
|
decideMediaProxyEligibility,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
probeMediaMetadata,
|
|
101
101
|
recordProxyRequest,
|
|
102
102
|
resolveProxyVariantRequest
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-XMNHDWQI.js";
|
|
104
104
|
import {
|
|
105
105
|
folderGone,
|
|
106
106
|
isInHiddenOrVendorDir,
|
|
@@ -302,7 +302,7 @@ declare function proxyEtagSalt(raw: string | undefined, box?: PreviewProxyBox):
|
|
|
302
302
|
*/
|
|
303
303
|
declare function injectMediaCodecMapIntoHtml(html: string, projectDir: string, htmlSources: HtmlSourceLike[], probeCache?: MediaCodecProbeCache, prewarm?: boolean,
|
|
304
304
|
/** Aborting it stops the pre-warms nobody else waits for. */
|
|
305
|
-
signal?: AbortSignal): Promise<string>;
|
|
305
|
+
signal?: AbortSignal, box?: PreviewProxyBox): Promise<string>;
|
|
306
306
|
/**
|
|
307
307
|
* Adapter-aware wrapper used by the studio preview routes: skipped entirely
|
|
308
308
|
* (no scan, no injection) when auto-proxy is off for this adapter.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.189",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"linkedom": "^0.18.12",
|
|
85
85
|
"postcss": "^8.5.8",
|
|
86
86
|
"postcss-selector-parser": "^7.1.2",
|
|
87
|
-
"@hyperframes/parsers": "0.8.
|
|
88
|
-
"@hyperframes/core": "0.8.
|
|
87
|
+
"@hyperframes/parsers": "0.8.189",
|
|
88
|
+
"@hyperframes/core": "0.8.189"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/node": "^25.0.10",
|