hyperframes 0.8.15 → 0.8.17
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 +1000 -758
- package/dist/fontLocalizeCli.js +514 -301
- package/dist/hyperframe-runtime.js +25 -25
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +25 -25
- package/dist/hyperframes-player.global.js +2 -2
- package/dist/studio/assets/hyperframes-player-DejBDgXB.js +459 -0
- package/dist/studio/assets/index-BX3KHhGX.js +71 -0
- package/dist/studio/assets/{index-DKoZIpw1.js → index-CU6o8PuW.js} +180 -180
- package/dist/studio/assets/{index-CVtYYTnA.js → index-CklNVmi3.js} +1 -1
- package/dist/studio/assets/{index-CtDg2lB7.js → index-uu4Zd3BU.js} +1 -1
- package/dist/studio/index.d.ts +9 -13
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +1660 -1284
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/studio/assets/hyperframes-player-BlIp1Y-b.js +0 -459
package/dist/fontLocalizeCli.js
CHANGED
|
@@ -17022,7 +17022,7 @@ var require_util = __commonJS({
|
|
|
17022
17022
|
return path;
|
|
17023
17023
|
}
|
|
17024
17024
|
exports.normalize = normalize;
|
|
17025
|
-
function
|
|
17025
|
+
function join56(aRoot, aPath) {
|
|
17026
17026
|
if (aRoot === "") {
|
|
17027
17027
|
aRoot = ".";
|
|
17028
17028
|
}
|
|
@@ -17054,7 +17054,7 @@ var require_util = __commonJS({
|
|
|
17054
17054
|
}
|
|
17055
17055
|
return joined;
|
|
17056
17056
|
}
|
|
17057
|
-
exports.join =
|
|
17057
|
+
exports.join = join56;
|
|
17058
17058
|
exports.isAbsolute = function(aPath) {
|
|
17059
17059
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
17060
17060
|
};
|
|
@@ -17227,7 +17227,7 @@ var require_util = __commonJS({
|
|
|
17227
17227
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
17228
17228
|
}
|
|
17229
17229
|
}
|
|
17230
|
-
sourceURL =
|
|
17230
|
+
sourceURL = join56(urlGenerate(parsed), sourceURL);
|
|
17231
17231
|
}
|
|
17232
17232
|
return normalize(sourceURL);
|
|
17233
17233
|
}
|
|
@@ -50798,7 +50798,7 @@ function compileTag(tag, isVideo, generateId) {
|
|
|
50798
50798
|
result = injectAttr(result, "data-hf-auto-start", "");
|
|
50799
50799
|
startStr = "0";
|
|
50800
50800
|
}
|
|
50801
|
-
const start =
|
|
50801
|
+
const start = parseNumeric(startStr);
|
|
50802
50802
|
const attrReader = { getAttribute: (name) => getAttr(result, name) };
|
|
50803
50803
|
const mediaStart = readMediaStart(attrReader);
|
|
50804
50804
|
const playbackRate = readElementPlaybackRate(attrReader);
|
|
@@ -50806,14 +50806,15 @@ function compileTag(tag, isVideo, generateId) {
|
|
|
50806
50806
|
const durationStr = getAttr(result, "data-duration");
|
|
50807
50807
|
const duration = parseStrictFiniteTimingNumber(durationStr);
|
|
50808
50808
|
if (duration != null) {
|
|
50809
|
-
|
|
50810
|
-
|
|
50809
|
+
if (start != null) {
|
|
50810
|
+
result = injectAttr(result, "data-end", String(start + duration));
|
|
50811
|
+
}
|
|
50811
50812
|
} else if (id) {
|
|
50812
50813
|
unresolved = {
|
|
50813
50814
|
id,
|
|
50814
50815
|
tagName: isVideo ? "video" : "audio",
|
|
50815
50816
|
src: getAttr(result, "src") ?? void 0,
|
|
50816
|
-
start,
|
|
50817
|
+
start: start ?? 0,
|
|
50817
50818
|
mediaStart,
|
|
50818
50819
|
playbackRate
|
|
50819
50820
|
};
|
|
@@ -50854,7 +50855,7 @@ function compileTimingAttrs(html) {
|
|
|
50854
50855
|
unresolved.push({
|
|
50855
50856
|
id,
|
|
50856
50857
|
tagName: "div",
|
|
50857
|
-
start:
|
|
50858
|
+
start: parseNumeric(startStr) ?? 0,
|
|
50858
50859
|
mediaStart: 0,
|
|
50859
50860
|
playbackRate: 1,
|
|
50860
50861
|
compositionSrc: compositionSrc ?? void 0
|
|
@@ -50873,9 +50874,10 @@ function injectDurations(html, resolutions) {
|
|
|
50873
50874
|
result = setAttr(result, "data-duration", String(duration));
|
|
50874
50875
|
}
|
|
50875
50876
|
if (!hasAttr(result, "data-end")) {
|
|
50876
|
-
const
|
|
50877
|
-
|
|
50878
|
-
|
|
50877
|
+
const start = parseNumeric(getAttr(result, "data-start"));
|
|
50878
|
+
if (start != null) {
|
|
50879
|
+
result = injectAttr(result, "data-end", String(start + duration));
|
|
50880
|
+
}
|
|
50879
50881
|
}
|
|
50880
50882
|
return result;
|
|
50881
50883
|
});
|
|
@@ -50906,7 +50908,7 @@ function extractResolvedMedia(html) {
|
|
|
50906
50908
|
id,
|
|
50907
50909
|
tagName: isVideo ? "video" : "audio",
|
|
50908
50910
|
src: getAttr(tag, "src") ?? void 0,
|
|
50909
|
-
start:
|
|
50911
|
+
start: parseNumeric(startStr) ?? 0,
|
|
50910
50912
|
duration,
|
|
50911
50913
|
mediaStart: readMediaStart(attrReader),
|
|
50912
50914
|
playbackRate: readElementPlaybackRate(attrReader),
|
|
@@ -50920,9 +50922,10 @@ function clampDurations(html, clamps) {
|
|
|
50920
50922
|
const idPattern = new RegExp(`(<[^>]*id=["']${escapeRegex2(id)}["'][^>]*>)`, "gi");
|
|
50921
50923
|
html = html.replace(idPattern, (tag) => {
|
|
50922
50924
|
tag = tag.replace(/data-duration=["'][^"']*["']/, `data-duration="${duration}"`);
|
|
50923
|
-
const
|
|
50924
|
-
|
|
50925
|
-
|
|
50925
|
+
const start = parseNumeric(getAttr(tag, "data-start"));
|
|
50926
|
+
if (start != null) {
|
|
50927
|
+
tag = tag.replace(/data-end=["'][^"']*["']/, `data-end="${start + duration}"`);
|
|
50928
|
+
}
|
|
50926
50929
|
return tag;
|
|
50927
50930
|
});
|
|
50928
50931
|
}
|
|
@@ -50932,6 +50935,7 @@ var MEDIA_DURATION_CLAMP_EPSILON_SECONDS, INERT_REGION_RE;
|
|
|
50932
50935
|
var init_timingCompiler = __esm({
|
|
50933
50936
|
"../core/dist/compiler/timingCompiler.js"() {
|
|
50934
50937
|
"use strict";
|
|
50938
|
+
init_compositionContract();
|
|
50935
50939
|
init_playbackRate();
|
|
50936
50940
|
MEDIA_DURATION_CLAMP_EPSILON_SECONDS = 0.05;
|
|
50937
50941
|
INERT_REGION_RE = /<!--[\s\S]*?-->|<script\b[\s\S]*?<\/script\s*>|<style\b[\s\S]*?<\/style\s*>/gi;
|
|
@@ -50939,16 +50943,6 @@ var init_timingCompiler = __esm({
|
|
|
50939
50943
|
});
|
|
50940
50944
|
|
|
50941
50945
|
// ../core/dist/compiler/mediaRenderIds.js
|
|
50942
|
-
function hasPlayableSource(el) {
|
|
50943
|
-
if (el.getAttribute("src"))
|
|
50944
|
-
return true;
|
|
50945
|
-
const sources = el.querySelectorAll?.("source[src]");
|
|
50946
|
-
if (!sources)
|
|
50947
|
-
return false;
|
|
50948
|
-
for (const _ of sources)
|
|
50949
|
-
return true;
|
|
50950
|
-
return false;
|
|
50951
|
-
}
|
|
50952
50946
|
function uniqueRenderId(baseId, taken) {
|
|
50953
50947
|
if (!taken.has(baseId))
|
|
50954
50948
|
return baseId;
|
|
@@ -50961,8 +50955,6 @@ function assignMediaRenderIds(document2) {
|
|
|
50961
50955
|
const taken = /* @__PURE__ */ new Set();
|
|
50962
50956
|
const pending = [];
|
|
50963
50957
|
for (const el of document2.querySelectorAll(MEDIA_SELECTOR)) {
|
|
50964
|
-
if (!hasPlayableSource(el))
|
|
50965
|
-
continue;
|
|
50966
50958
|
const existing = el.getAttribute(MEDIA_RENDER_ID_ATTR);
|
|
50967
50959
|
if (existing) {
|
|
50968
50960
|
taken.add(existing);
|
|
@@ -56094,7 +56086,12 @@ async function captureDrawElementFrame(page, width, height, format = "jpeg", qua
|
|
|
56094
56086
|
}) => {
|
|
56095
56087
|
const canvas = document.getElementById("__hf_de_canvas");
|
|
56096
56088
|
const root = document.querySelector("[data-composition-id]");
|
|
56097
|
-
if (!
|
|
56089
|
+
if (!root) {
|
|
56090
|
+
throw new Error("HF_DE_COMPOSITION_ROOT_MISSING: drawElement composition root not found");
|
|
56091
|
+
}
|
|
56092
|
+
if (!canvas) {
|
|
56093
|
+
throw new Error("HF_DE_CANVAS_NOT_INITIALIZED: drawElement canvas not initialized");
|
|
56094
|
+
}
|
|
56098
56095
|
const ctx = canvas.getContext("2d");
|
|
56099
56096
|
if (!ctx) throw new Error("drawElement: 2d context unavailable");
|
|
56100
56097
|
const aw = window;
|
|
@@ -56341,7 +56338,12 @@ async function produceDrawElementFrame(page, width, height, quality = 80, syncTo
|
|
|
56341
56338
|
({ w, h, q, sync, fid }) => {
|
|
56342
56339
|
const canvas = document.getElementById("__hf_de_canvas");
|
|
56343
56340
|
const root = document.querySelector("[data-composition-id]");
|
|
56344
|
-
if (!
|
|
56341
|
+
if (!root) {
|
|
56342
|
+
throw new Error("HF_DE_COMPOSITION_ROOT_MISSING: drawElement composition root not found");
|
|
56343
|
+
}
|
|
56344
|
+
if (!canvas) {
|
|
56345
|
+
throw new Error("HF_DE_CANVAS_NOT_INITIALIZED: drawElement canvas not initialized");
|
|
56346
|
+
}
|
|
56345
56347
|
const ctx = canvas.getContext("2d");
|
|
56346
56348
|
if (!ctx) throw new Error("drawElement: 2d context unavailable");
|
|
56347
56349
|
const aw = window;
|
|
@@ -56508,7 +56510,18 @@ async function produceDrawElementFrameBatch(page, times, width, height, quality
|
|
|
56508
56510
|
}) => {
|
|
56509
56511
|
const canvas = document.getElementById("__hf_de_canvas");
|
|
56510
56512
|
const root = document.querySelector("[data-composition-id]");
|
|
56511
|
-
if (!
|
|
56513
|
+
if (!root) {
|
|
56514
|
+
return {
|
|
56515
|
+
failedAt: 0,
|
|
56516
|
+
error: "HF_DE_COMPOSITION_ROOT_MISSING: drawElement composition root not found"
|
|
56517
|
+
};
|
|
56518
|
+
}
|
|
56519
|
+
if (!canvas) {
|
|
56520
|
+
return {
|
|
56521
|
+
failedAt: 0,
|
|
56522
|
+
error: "HF_DE_CANVAS_NOT_INITIALIZED: drawElement canvas not initialized"
|
|
56523
|
+
};
|
|
56524
|
+
}
|
|
56512
56525
|
const ctx = canvas.getContext("2d");
|
|
56513
56526
|
if (!ctx) return { failedAt: 0, error: "drawElement: 2d context unavailable" };
|
|
56514
56527
|
const aw = window;
|
|
@@ -56647,10 +56660,11 @@ async function produceDrawElementFrameBatch(page, times, width, height, quality
|
|
|
56647
56660
|
}
|
|
56648
56661
|
return { encodeResults, failedAt: outcome.failedAt, error: outcome.error };
|
|
56649
56662
|
}
|
|
56650
|
-
var workerEncodeStates, workerEncodeBoundPages;
|
|
56663
|
+
var DE_CANVAS_NOT_INITIALIZED_CODE, workerEncodeStates, workerEncodeBoundPages;
|
|
56651
56664
|
var init_drawElementService = __esm({
|
|
56652
56665
|
"../engine/src/services/drawElementService.ts"() {
|
|
56653
56666
|
"use strict";
|
|
56667
|
+
DE_CANVAS_NOT_INITIALIZED_CODE = "HF_DE_CANVAS_NOT_INITIALIZED";
|
|
56654
56668
|
workerEncodeStates = /* @__PURE__ */ new WeakMap();
|
|
56655
56669
|
workerEncodeBoundPages = /* @__PURE__ */ new WeakSet();
|
|
56656
56670
|
}
|
|
@@ -58558,11 +58572,12 @@ function recordCaptureWarnings(session, warnings) {
|
|
|
58558
58572
|
function recordSubTimelineWarning(session, timeoutMs) {
|
|
58559
58573
|
if (session.subTimelineWaitOutcome === "ready" || !session.subTimelineWaitOutcome) return;
|
|
58560
58574
|
const scriptFailure = session.subTimelineWaitOutcome === "script_failure";
|
|
58575
|
+
const hasRuntimeErrors = session.scriptLoadFailures.some((f) => f.startsWith("runtime-error:"));
|
|
58561
58576
|
recordCaptureWarnings(session, [
|
|
58562
58577
|
{
|
|
58563
58578
|
code: scriptFailure ? "sub_timeline_script_failure" : "sub_timeline_readiness_timeout",
|
|
58564
|
-
message: scriptFailure ? "A sub-composition timeline script failed to load" : `Sub-composition timelines did not become ready within ${timeoutMs}ms`,
|
|
58565
|
-
details: { timeoutMs }
|
|
58579
|
+
message: scriptFailure ? hasRuntimeErrors ? `A sub-composition script threw during execution \u2014 timeline registration never arrived (${session.scriptLoadFailures.join(", ")})` : `A sub-composition timeline script failed to load (${session.scriptLoadFailures.join(", ")})` : `Sub-composition timelines did not become ready within ${timeoutMs}ms`,
|
|
58580
|
+
details: { timeoutMs, sources: [...session.scriptLoadFailures] }
|
|
58566
58581
|
}
|
|
58567
58582
|
]);
|
|
58568
58583
|
}
|
|
@@ -58646,6 +58661,11 @@ async function initializeSession(session) {
|
|
|
58646
58661
|
const diagnostic = formatConsoleDiagnostic(type, text, locationUrl);
|
|
58647
58662
|
if (!diagnostic.suppressHostLog) console.log(diagnostic.text);
|
|
58648
58663
|
appendBrowserDiagnostic(session, diagnostic.text);
|
|
58664
|
+
if (type === "error" && text.startsWith("[HyperFrames] composition script error:")) {
|
|
58665
|
+
const detail = text.slice("[HyperFrames] composition script error:".length).trim();
|
|
58666
|
+
const compId = detail.split(" ")[0] || "unknown";
|
|
58667
|
+
recordScriptLoadFailure(session, `runtime-error:${compId}`);
|
|
58668
|
+
}
|
|
58649
58669
|
});
|
|
58650
58670
|
page.on("pageerror", (err) => {
|
|
58651
58671
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -59417,7 +59437,14 @@ async function computeTimelineAtRiskFrames(page, fps) {
|
|
|
59417
59437
|
}
|
|
59418
59438
|
function isNoCachedPaintRecordError(err) {
|
|
59419
59439
|
const msg = err instanceof Error ? err.message : String(err);
|
|
59420
|
-
return msg.includes("No cached paint record");
|
|
59440
|
+
return msg.includes("No cached paint record for element");
|
|
59441
|
+
}
|
|
59442
|
+
function isCanvasNotInitializedError(err) {
|
|
59443
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
59444
|
+
return msg.includes(DE_CANVAS_NOT_INITIALIZED_CODE);
|
|
59445
|
+
}
|
|
59446
|
+
function isRecoverableDrawElementError(err) {
|
|
59447
|
+
return isNoCachedPaintRecordError(err) || isCanvasNotInitializedError(err);
|
|
59421
59448
|
}
|
|
59422
59449
|
async function captureFrameCore(session, frameIndex, time) {
|
|
59423
59450
|
const { page, options } = session;
|
|
@@ -59491,10 +59518,11 @@ async function captureFrameCore(session, frameIndex, time) {
|
|
|
59491
59518
|
}
|
|
59492
59519
|
}
|
|
59493
59520
|
} catch (err) {
|
|
59494
|
-
if (
|
|
59521
|
+
if (isRecoverableDrawElementError(err)) {
|
|
59495
59522
|
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
59523
|
+
const reason = isCanvasNotInitializedError(err) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
59496
59524
|
console.log(
|
|
59497
|
-
`[engine] fast capture: frame ${frameIndex} \u2014
|
|
59525
|
+
`[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
|
|
59498
59526
|
);
|
|
59499
59527
|
screenshotBuffer = await pageScreenshotCapture(page, options);
|
|
59500
59528
|
} else {
|
|
@@ -59611,10 +59639,11 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
59611
59639
|
}
|
|
59612
59640
|
return { encodeResult, captureTimeMs };
|
|
59613
59641
|
} catch (captureError) {
|
|
59614
|
-
if (
|
|
59642
|
+
if (isRecoverableDrawElementError(captureError)) {
|
|
59615
59643
|
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
59644
|
+
const reason = isCanvasNotInitializedError(captureError) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
59616
59645
|
console.log(
|
|
59617
|
-
`[engine] fast capture: frame ${frameIndex} \u2014
|
|
59646
|
+
`[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
|
|
59618
59647
|
);
|
|
59619
59648
|
const buffer = await pageScreenshotCapture(page, options);
|
|
59620
59649
|
return { encodeResult: Promise.resolve(buffer), captureTimeMs: Date.now() - startTime };
|
|
@@ -59677,15 +59706,36 @@ async function captureFramesBatchPipelined(session, frameIndices, times) {
|
|
|
59677
59706
|
results.push({ frameIndex, encodeResult });
|
|
59678
59707
|
}
|
|
59679
59708
|
if (failedAt !== null) {
|
|
59680
|
-
|
|
59681
|
-
|
|
59682
|
-
|
|
59683
|
-
|
|
59684
|
-
|
|
59685
|
-
|
|
59686
|
-
|
|
59687
|
-
|
|
59688
|
-
|
|
59709
|
+
if (isRecoverableDrawElementError(error)) {
|
|
59710
|
+
const reason = isCanvasNotInitializedError(error) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
59711
|
+
console.log(
|
|
59712
|
+
`[engine] fast capture: batch produce failed at frame ${frameIndices[failedAt] ?? "?"} (${reason}); screenshot fallback for ${frameIndices.length - failedAt} frame(s) (see fast-capture-limitations.md)`
|
|
59713
|
+
);
|
|
59714
|
+
for (let i = failedAt; i < frameIndices.length; i++) {
|
|
59715
|
+
const frameIndex = frameIndices[i];
|
|
59716
|
+
const time = times[i];
|
|
59717
|
+
if (frameIndex === void 0 || time === void 0) break;
|
|
59718
|
+
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
59719
|
+
await prepareFrameForCapture(session, frameIndex, time);
|
|
59720
|
+
const buffer = await pageScreenshotCapture(page, options);
|
|
59721
|
+
const encodeResult = Promise.resolve(buffer);
|
|
59722
|
+
if (session.staticFrames) {
|
|
59723
|
+
session.lastEncodeResult = encodeResult;
|
|
59724
|
+
session.lastEncodeResultFrame = frameIndex;
|
|
59725
|
+
}
|
|
59726
|
+
results.push({ frameIndex, encodeResult });
|
|
59727
|
+
}
|
|
59728
|
+
} else {
|
|
59729
|
+
console.log(
|
|
59730
|
+
`[engine] fast capture: batch produce failed at frame ${frameIndices[failedAt] ?? "?"} (${error ?? "?"}); re-capturing ${frameIndices.length - failedAt} frame(s) per-frame`
|
|
59731
|
+
);
|
|
59732
|
+
for (let i = failedAt; i < frameIndices.length; i++) {
|
|
59733
|
+
const frameIndex = frameIndices[i];
|
|
59734
|
+
const time = times[i];
|
|
59735
|
+
if (frameIndex === void 0 || time === void 0) break;
|
|
59736
|
+
const { encodeResult } = await captureFrameToBufferPipelined(session, frameIndex, time);
|
|
59737
|
+
results.push({ frameIndex, encodeResult });
|
|
59738
|
+
}
|
|
59689
59739
|
}
|
|
59690
59740
|
}
|
|
59691
59741
|
const last = results[results.length - 1];
|
|
@@ -59843,6 +59893,13 @@ function percentileOf(samples, p) {
|
|
|
59843
59893
|
}
|
|
59844
59894
|
function getCapturePerfSummary(session) {
|
|
59845
59895
|
const frames = Math.max(1, session.capturePerf.frames);
|
|
59896
|
+
const ncprFallbacks = session.deNcprFallbacks ?? 0;
|
|
59897
|
+
if (frames > 0 && ncprFallbacks / frames > DE_FALLBACK_RATIO_WARN_THRESHOLD) {
|
|
59898
|
+
const pct = Math.round(ncprFallbacks / frames * 100);
|
|
59899
|
+
console.warn(
|
|
59900
|
+
`[engine] fast capture: ${ncprFallbacks}/${frames} frame(s) (${pct}%) fell back to screenshot capture (canvas-not-initialized / no-cached-paint-record) \u2014 drawElement likely failed to engage for this render rather than recovering a few edge-case frames; see fast-capture-limitations.md.`
|
|
59901
|
+
);
|
|
59902
|
+
}
|
|
59846
59903
|
return {
|
|
59847
59904
|
frames: session.capturePerf.frames,
|
|
59848
59905
|
avgTotalMs: Math.round(session.capturePerf.totalMs / frames),
|
|
@@ -59881,10 +59938,10 @@ function getCapturePerfSummary(session) {
|
|
|
59881
59938
|
deVerifyArmed: session.deVerifyFrames?.size ?? 0,
|
|
59882
59939
|
deVerifyInitMs: session.deVerifyInitMs ?? 0,
|
|
59883
59940
|
deBoundaryFrames: session.clipBoundaryFrames?.size ?? 0,
|
|
59884
|
-
deNcprFallbacks:
|
|
59941
|
+
deNcprFallbacks: ncprFallbacks
|
|
59885
59942
|
};
|
|
59886
59943
|
}
|
|
59887
|
-
var DrawElementVerificationError, BROWSER_CONSOLE_BUFFER_SIZE, CAPTURE_SESSION_CLOSE_TIMEOUT_MS, LOCKED_WARMUP_TICKS, realSleep, BEGIN_FRAME_CAPTURE_HEADROOM_INTERVALS, BEGIN_FRAME_COMMIT_LEAD_INTERVALS, BEGIN_FRAME_PROBE_LEAD_INTERVALS, HF_READY_DIAGNOSTIC_EXPR, LIVE_MAP_MARKERS, MAX_STATIC_DEDUP_ANALYSIS_FRAMES, STATIC_VERIFY_REFERENCE_STRIDE, STATIC_VERIFY_MAX_MS, STATIC_VERIFY_MIN_SCREENSHOT_CAP, STATIC_VERIFY_SAMPLE_CAP_MULTIPLIER, STATIC_VERIFY_MAX_GLOBAL_SAMPLE_FLOOR;
|
|
59944
|
+
var DrawElementVerificationError, BROWSER_CONSOLE_BUFFER_SIZE, CAPTURE_SESSION_CLOSE_TIMEOUT_MS, LOCKED_WARMUP_TICKS, realSleep, BEGIN_FRAME_CAPTURE_HEADROOM_INTERVALS, BEGIN_FRAME_COMMIT_LEAD_INTERVALS, BEGIN_FRAME_PROBE_LEAD_INTERVALS, HF_READY_DIAGNOSTIC_EXPR, LIVE_MAP_MARKERS, MAX_STATIC_DEDUP_ANALYSIS_FRAMES, STATIC_VERIFY_REFERENCE_STRIDE, STATIC_VERIFY_MAX_MS, STATIC_VERIFY_MIN_SCREENSHOT_CAP, STATIC_VERIFY_SAMPLE_CAP_MULTIPLIER, STATIC_VERIFY_MAX_GLOBAL_SAMPLE_FLOOR, DE_FALLBACK_RATIO_WARN_THRESHOLD;
|
|
59888
59945
|
var init_frameCapture = __esm({
|
|
59889
59946
|
"../engine/src/services/frameCapture.ts"() {
|
|
59890
59947
|
"use strict";
|
|
@@ -59952,6 +60009,7 @@ var init_frameCapture = __esm({
|
|
|
59952
60009
|
STATIC_VERIFY_MIN_SCREENSHOT_CAP = 400;
|
|
59953
60010
|
STATIC_VERIFY_SAMPLE_CAP_MULTIPLIER = 8;
|
|
59954
60011
|
STATIC_VERIFY_MAX_GLOBAL_SAMPLE_FLOOR = STATIC_VERIFY_MIN_SCREENSHOT_CAP / STATIC_VERIFY_SAMPLE_CAP_MULTIPLIER;
|
|
60012
|
+
DE_FALLBACK_RATIO_WARN_THRESHOLD = 0.5;
|
|
59955
60013
|
}
|
|
59956
60014
|
});
|
|
59957
60015
|
|
|
@@ -60799,7 +60857,8 @@ async function extractMediaMetadata(filePath) {
|
|
|
60799
60857
|
hasAudio: false,
|
|
60800
60858
|
isVFR: false,
|
|
60801
60859
|
hasAlpha: false,
|
|
60802
|
-
colorSpace: stillImageMeta.colorSpace
|
|
60860
|
+
colorSpace: stillImageMeta.colorSpace,
|
|
60861
|
+
frames: 1
|
|
60803
60862
|
};
|
|
60804
60863
|
}
|
|
60805
60864
|
throw new Error("[FFmpeg] No video stream found");
|
|
@@ -60825,6 +60884,8 @@ async function extractMediaMetadata(filePath) {
|
|
|
60825
60884
|
const streamDuration = videoStream.duration ? parseFloat(videoStream.duration) : 0;
|
|
60826
60885
|
const parsedStreamStart = videoStream.start_time ? parseFloat(videoStream.start_time) : 0;
|
|
60827
60886
|
const streamStart = Number.isFinite(parsedStreamStart) ? parsedStreamStart : 0;
|
|
60887
|
+
const parsedNbFrames = videoStream.nb_frames ? parseInt(videoStream.nb_frames, 10) : NaN;
|
|
60888
|
+
const frames = Number.isFinite(parsedNbFrames) && parsedNbFrames > 0 ? parsedNbFrames : void 0;
|
|
60828
60889
|
return {
|
|
60829
60890
|
durationSeconds: containerDuration,
|
|
60830
60891
|
videoStreamDurationSeconds: streamDuration > 0 ? streamDuration : containerDuration,
|
|
@@ -60836,7 +60897,8 @@ async function extractMediaMetadata(filePath) {
|
|
|
60836
60897
|
hasAudio: output?.streams.some((s) => s.codec_type === "audio") ?? false,
|
|
60837
60898
|
isVFR,
|
|
60838
60899
|
hasAlpha,
|
|
60839
|
-
colorSpace
|
|
60900
|
+
colorSpace,
|
|
60901
|
+
frames
|
|
60840
60902
|
};
|
|
60841
60903
|
})();
|
|
60842
60904
|
videoMetadataCache.set(filePath, probePromise);
|
|
@@ -61517,8 +61579,6 @@ async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, confi
|
|
|
61517
61579
|
args.push("-c:a", "aac", "-b:a", "192k", "-movflags", "+faststart");
|
|
61518
61580
|
}
|
|
61519
61581
|
}
|
|
61520
|
-
const copiesContainerizedAac = !isWebm && shouldCopyAudio && config?.preserveAudioPrimingEditList === true;
|
|
61521
|
-
if (!copiesContainerizedAac) args.push("-avoid_negative_ts", "make_zero");
|
|
61522
61582
|
appendRenderProvenanceArgs(args, outputPath);
|
|
61523
61583
|
if (fps !== void 0) {
|
|
61524
61584
|
args.push("-r", fpsToFfmpegArg(fps));
|
|
@@ -69775,6 +69835,14 @@ function hasAttrName(tagSource, attr) {
|
|
|
69775
69835
|
const attrs = tagSource.replace(/^<\s*[a-z][\w:-]*/i, "");
|
|
69776
69836
|
return new RegExp(`(?:^|\\s)${escaped}(?:\\s*=|\\s|/?>)`, "i").test(attrs);
|
|
69777
69837
|
}
|
|
69838
|
+
function mediaHasResolvableSrc(tag, tags) {
|
|
69839
|
+
if (readAttr(tag.raw, "src")) return true;
|
|
69840
|
+
const end = tag.closeIndex ?? tag.endIndex;
|
|
69841
|
+
if (end == null) return false;
|
|
69842
|
+
return tags.some(
|
|
69843
|
+
(child) => child.name === "source" && child.index > tag.index && child.index < end && Boolean(readAttr(child.raw, "src"))
|
|
69844
|
+
);
|
|
69845
|
+
}
|
|
69778
69846
|
function classNamesFromAttr(classAttr) {
|
|
69779
69847
|
if (!classAttr) return [];
|
|
69780
69848
|
return classAttr.split(/\s+/).filter(Boolean);
|
|
@@ -71707,7 +71775,7 @@ var init_dist3 = __esm({
|
|
|
71707
71775
|
if (tag.name !== "video" && tag.name !== "audio") continue;
|
|
71708
71776
|
const hasDataStart = readAttr(tag.raw, "data-start");
|
|
71709
71777
|
const hasId = readAttr(tag.raw, "id");
|
|
71710
|
-
const hasSrc =
|
|
71778
|
+
const hasSrc = mediaHasResolvableSrc(tag, tags);
|
|
71711
71779
|
if (hasSrc && !hasDataStart) {
|
|
71712
71780
|
findings.push({
|
|
71713
71781
|
code: "media_missing_data_start",
|
|
@@ -71742,9 +71810,9 @@ var init_dist3 = __esm({
|
|
|
71742
71810
|
findings.push({
|
|
71743
71811
|
code: "media_missing_src",
|
|
71744
71812
|
severity: "error",
|
|
71745
|
-
message: `<${tag.name} id="${hasId}"> has data-start but no src
|
|
71813
|
+
message: `<${tag.name} id="${hasId}"> has data-start but no src (on the element or a <source> child). The renderer cannot load this media.`,
|
|
71746
71814
|
elementId: hasId,
|
|
71747
|
-
fixHint: `Add
|
|
71815
|
+
fixHint: `Add src on the <${tag.name}> element, or a <source src="..."> child.`,
|
|
71748
71816
|
snippet: truncateSnippet(tag.raw)
|
|
71749
71817
|
});
|
|
71750
71818
|
}
|
|
@@ -74507,20 +74575,73 @@ var init_htmlTemplate = __esm({
|
|
|
74507
74575
|
}
|
|
74508
74576
|
});
|
|
74509
74577
|
|
|
74578
|
+
// ../engine/src/services/extractedFrameIndex.ts
|
|
74579
|
+
import { readdirSync as readdirSync4 } from "fs";
|
|
74580
|
+
import { join as join9 } from "path";
|
|
74581
|
+
function extractedFrameIndex(file, format) {
|
|
74582
|
+
const match = new RegExp(`^${FRAME_FILENAME_PREFIX}(\\d+)\\.${format}$`).exec(file);
|
|
74583
|
+
if (!match) {
|
|
74584
|
+
throw new ExtractedFrameSequenceError(`Invalid extracted frame filename: ${file}`);
|
|
74585
|
+
}
|
|
74586
|
+
const ordinal = Number.parseInt(match[1], 10);
|
|
74587
|
+
if (!Number.isSafeInteger(ordinal) || ordinal < 1) {
|
|
74588
|
+
throw new ExtractedFrameSequenceError(`Invalid extracted frame ordinal: ${file}`);
|
|
74589
|
+
}
|
|
74590
|
+
return ordinal - 1;
|
|
74591
|
+
}
|
|
74592
|
+
function framePathsFromDirectory(outputDir, format) {
|
|
74593
|
+
const suffix = `.${format}`;
|
|
74594
|
+
const indexed = /* @__PURE__ */ new Map();
|
|
74595
|
+
for (const file of readdirSync4(outputDir)) {
|
|
74596
|
+
if (!file.startsWith(FRAME_FILENAME_PREFIX) || !file.endsWith(suffix)) continue;
|
|
74597
|
+
const index = extractedFrameIndex(file, format);
|
|
74598
|
+
if (indexed.has(index)) {
|
|
74599
|
+
throw new ExtractedFrameSequenceError(
|
|
74600
|
+
`Duplicate extracted frame index ${index}: ${indexed.get(index)} and ${file}`
|
|
74601
|
+
);
|
|
74602
|
+
}
|
|
74603
|
+
indexed.set(index, join9(outputDir, file));
|
|
74604
|
+
}
|
|
74605
|
+
const ordered = /* @__PURE__ */ new Map();
|
|
74606
|
+
for (let index = 0; index < indexed.size; index += 1) {
|
|
74607
|
+
const path = indexed.get(index);
|
|
74608
|
+
if (!path) {
|
|
74609
|
+
throw new ExtractedFrameSequenceError(
|
|
74610
|
+
`Missing extracted frame index ${index} in ${outputDir}`
|
|
74611
|
+
);
|
|
74612
|
+
}
|
|
74613
|
+
ordered.set(index, path);
|
|
74614
|
+
}
|
|
74615
|
+
return ordered;
|
|
74616
|
+
}
|
|
74617
|
+
var FRAME_FILENAME_PREFIX, ExtractedFrameSequenceError;
|
|
74618
|
+
var init_extractedFrameIndex = __esm({
|
|
74619
|
+
"../engine/src/services/extractedFrameIndex.ts"() {
|
|
74620
|
+
"use strict";
|
|
74621
|
+
FRAME_FILENAME_PREFIX = "frame_";
|
|
74622
|
+
ExtractedFrameSequenceError = class extends Error {
|
|
74623
|
+
constructor(message) {
|
|
74624
|
+
super(message);
|
|
74625
|
+
this.name = "ExtractedFrameSequenceError";
|
|
74626
|
+
}
|
|
74627
|
+
};
|
|
74628
|
+
}
|
|
74629
|
+
});
|
|
74630
|
+
|
|
74510
74631
|
// ../engine/src/services/extractionCache.ts
|
|
74511
74632
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
74512
74633
|
import {
|
|
74513
74634
|
existsSync as existsSync9,
|
|
74514
74635
|
lstatSync as lstatSync2,
|
|
74515
74636
|
mkdirSync as mkdirSync5,
|
|
74516
|
-
readdirSync as
|
|
74637
|
+
readdirSync as readdirSync5,
|
|
74517
74638
|
renameSync,
|
|
74518
74639
|
rmSync as rmSync2,
|
|
74519
74640
|
statSync as statSync5,
|
|
74520
74641
|
utimesSync,
|
|
74521
74642
|
writeFileSync as writeFileSync3
|
|
74522
74643
|
} from "fs";
|
|
74523
|
-
import { join as
|
|
74644
|
+
import { join as join10 } from "path";
|
|
74524
74645
|
function readKeyStat(videoPath) {
|
|
74525
74646
|
try {
|
|
74526
74647
|
const stat = statSync5(videoPath);
|
|
@@ -74549,10 +74670,17 @@ function computeCacheKey(input) {
|
|
|
74549
74670
|
function cacheEntryDirName(keyHash) {
|
|
74550
74671
|
return SCHEMA_PREFIX + keyHash.slice(0, KEY_HEX_CHARS);
|
|
74551
74672
|
}
|
|
74673
|
+
function hasFrameFiles(dir) {
|
|
74674
|
+
try {
|
|
74675
|
+
return readdirSync5(dir).some((file) => file.startsWith(FRAME_FILENAME_PREFIX));
|
|
74676
|
+
} catch {
|
|
74677
|
+
return false;
|
|
74678
|
+
}
|
|
74679
|
+
}
|
|
74552
74680
|
function lookupCacheEntry(rootDir, input) {
|
|
74553
74681
|
const keyHash = computeCacheKey(input);
|
|
74554
|
-
const dir =
|
|
74555
|
-
const complete = existsSync9(
|
|
74682
|
+
const dir = join10(rootDir, cacheEntryDirName(keyHash));
|
|
74683
|
+
const complete = existsSync9(join10(dir, COMPLETE_SENTINEL)) && hasFrameFiles(dir);
|
|
74556
74684
|
return { entry: { dir, keyHash }, hit: complete };
|
|
74557
74685
|
}
|
|
74558
74686
|
function partialCacheEntryDir(entry) {
|
|
@@ -74563,13 +74691,13 @@ function isTargetExistsRenameError(err) {
|
|
|
74563
74691
|
return code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM";
|
|
74564
74692
|
}
|
|
74565
74693
|
function adoptPublishedWinner(entry, partialDir) {
|
|
74566
|
-
if (!existsSync9(
|
|
74694
|
+
if (!existsSync9(join10(entry.dir, COMPLETE_SENTINEL))) return null;
|
|
74567
74695
|
removeDir(partialDir);
|
|
74568
74696
|
return { dir: entry.dir, published: true };
|
|
74569
74697
|
}
|
|
74570
74698
|
function publishCacheEntry(entry, partialDir) {
|
|
74571
74699
|
try {
|
|
74572
|
-
writeFileSync3(
|
|
74700
|
+
writeFileSync3(join10(partialDir, COMPLETE_SENTINEL), "", "utf-8");
|
|
74573
74701
|
} catch {
|
|
74574
74702
|
return { dir: partialDir, published: false };
|
|
74575
74703
|
}
|
|
@@ -74596,7 +74724,7 @@ function publishCacheEntry(entry, partialDir) {
|
|
|
74596
74724
|
function touchCacheEntry(entry) {
|
|
74597
74725
|
try {
|
|
74598
74726
|
const now = /* @__PURE__ */ new Date();
|
|
74599
|
-
utimesSync(
|
|
74727
|
+
utimesSync(join10(entry.dir, COMPLETE_SENTINEL), now, now);
|
|
74600
74728
|
} catch {
|
|
74601
74729
|
}
|
|
74602
74730
|
}
|
|
@@ -74616,12 +74744,12 @@ function directorySizeBytes(path) {
|
|
|
74616
74744
|
let total = 0;
|
|
74617
74745
|
let children;
|
|
74618
74746
|
try {
|
|
74619
|
-
children =
|
|
74747
|
+
children = readdirSync5(path);
|
|
74620
74748
|
} catch {
|
|
74621
74749
|
return 0;
|
|
74622
74750
|
}
|
|
74623
74751
|
for (const child of children) {
|
|
74624
|
-
const childPath =
|
|
74752
|
+
const childPath = join10(path, child);
|
|
74625
74753
|
try {
|
|
74626
74754
|
const stat = lstatSync2(childPath);
|
|
74627
74755
|
if (stat.isDirectory()) {
|
|
@@ -74650,7 +74778,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
|
|
|
74650
74778
|
}
|
|
74651
74779
|
let lastUseMs = dirStat.mtimeMs;
|
|
74652
74780
|
try {
|
|
74653
|
-
lastUseMs = statSync5(
|
|
74781
|
+
lastUseMs = statSync5(join10(dir, COMPLETE_SENTINEL)).mtimeMs;
|
|
74654
74782
|
} catch {
|
|
74655
74783
|
}
|
|
74656
74784
|
return { dir, size: directorySizeBytes(dir), lastUseMs, ageMs: now - lastUseMs };
|
|
@@ -74660,7 +74788,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
|
|
|
74660
74788
|
}
|
|
74661
74789
|
function gcSweepDue(rootDir, maxAgeMs) {
|
|
74662
74790
|
try {
|
|
74663
|
-
return Date.now() - statSync5(
|
|
74791
|
+
return Date.now() - statSync5(join10(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
|
|
74664
74792
|
} catch {
|
|
74665
74793
|
return true;
|
|
74666
74794
|
}
|
|
@@ -74668,16 +74796,16 @@ function gcSweepDue(rootDir, maxAgeMs) {
|
|
|
74668
74796
|
function gcExtractionCache(rootDir, opts) {
|
|
74669
74797
|
const stats = { evictedEntries: 0, evictedBytes: 0, agedPartialsRemoved: 0 };
|
|
74670
74798
|
try {
|
|
74671
|
-
writeFileSync3(
|
|
74799
|
+
writeFileSync3(join10(rootDir, GC_MARKER), "", "utf-8");
|
|
74672
74800
|
} catch {
|
|
74673
74801
|
}
|
|
74674
74802
|
try {
|
|
74675
74803
|
const now = Date.now();
|
|
74676
74804
|
const entries2 = [];
|
|
74677
|
-
for (const child of
|
|
74805
|
+
for (const child of readdirSync5(rootDir, { withFileTypes: true })) {
|
|
74678
74806
|
if (!child.isDirectory() || !isCacheLikeChild(child.name)) continue;
|
|
74679
74807
|
const entry = collectGcEntry(
|
|
74680
|
-
|
|
74808
|
+
join10(rootDir, child.name),
|
|
74681
74809
|
child.name,
|
|
74682
74810
|
now,
|
|
74683
74811
|
opts.minAgeMs,
|
|
@@ -74702,12 +74830,7 @@ function gcExtractionCache(rootDir, opts) {
|
|
|
74702
74830
|
}
|
|
74703
74831
|
function rehydrateCacheEntry(entry, options) {
|
|
74704
74832
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
|
|
74705
|
-
const framePaths =
|
|
74706
|
-
const suffix = `.${options.format}`;
|
|
74707
|
-
const files = readdirSync4(entry.dir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(suffix)).sort();
|
|
74708
|
-
files.forEach((file, idx) => {
|
|
74709
|
-
framePaths.set(idx, join9(entry.dir, file));
|
|
74710
|
-
});
|
|
74833
|
+
const framePaths = framePathsFromDirectory(entry.dir, options.format);
|
|
74711
74834
|
return {
|
|
74712
74835
|
videoId: options.videoId,
|
|
74713
74836
|
srcPath: options.srcPath,
|
|
@@ -74719,11 +74842,12 @@ function rehydrateCacheEntry(entry, options) {
|
|
|
74719
74842
|
framePaths
|
|
74720
74843
|
};
|
|
74721
74844
|
}
|
|
74722
|
-
var
|
|
74845
|
+
var COMPLETE_SENTINEL, GC_MARKER, SCHEMA_PREFIX, KEY_HEX_CHARS, CACHE_GENERATION_PREFIX;
|
|
74723
74846
|
var init_extractionCache = __esm({
|
|
74724
74847
|
"../engine/src/services/extractionCache.ts"() {
|
|
74725
74848
|
"use strict";
|
|
74726
|
-
|
|
74849
|
+
init_extractedFrameIndex();
|
|
74850
|
+
init_extractedFrameIndex();
|
|
74727
74851
|
COMPLETE_SENTINEL = ".hf-complete";
|
|
74728
74852
|
GC_MARKER = ".hf-last-gc";
|
|
74729
74853
|
SCHEMA_PREFIX = "hfcache-v4-";
|
|
@@ -74733,8 +74857,8 @@ var init_extractionCache = __esm({
|
|
|
74733
74857
|
});
|
|
74734
74858
|
|
|
74735
74859
|
// ../engine/src/services/videoFrameExtractor.ts
|
|
74736
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync10, linkSync as linkSync2, mkdirSync as mkdirSync6,
|
|
74737
|
-
import { isAbsolute, join as
|
|
74860
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync10, linkSync as linkSync2, mkdirSync as mkdirSync6, rmSync as rmSync3 } from "fs";
|
|
74861
|
+
import { isAbsolute, join as join11, posix as posix2, resolve as resolve5, sep as sep2 } from "path";
|
|
74738
74862
|
function isVideoFrameFormat(value) {
|
|
74739
74863
|
return typeof value === "string" && VIDEO_FRAME_FORMATS.includes(value);
|
|
74740
74864
|
}
|
|
@@ -74956,15 +75080,27 @@ async function runVideoExtractionWithRetry(operation, options = {}) {
|
|
|
74956
75080
|
}
|
|
74957
75081
|
}
|
|
74958
75082
|
}
|
|
75083
|
+
function resolveMediaElementSrc(el) {
|
|
75084
|
+
const direct = el.getAttribute("src");
|
|
75085
|
+
if (direct) return direct;
|
|
75086
|
+
let remote = null;
|
|
75087
|
+
for (const source of el.querySelectorAll("source")) {
|
|
75088
|
+
const src = source.getAttribute("src");
|
|
75089
|
+
if (!src) continue;
|
|
75090
|
+
if (!/^https?:\/\//i.test(src)) return src;
|
|
75091
|
+
remote ??= src;
|
|
75092
|
+
}
|
|
75093
|
+
return remote;
|
|
75094
|
+
}
|
|
74959
75095
|
function parseVideoElements(html) {
|
|
74960
75096
|
const videos = [];
|
|
74961
75097
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
74962
75098
|
const startCache = /* @__PURE__ */ new Map();
|
|
74963
75099
|
const visiting = /* @__PURE__ */ new Set();
|
|
74964
|
-
const videoEls = document2.querySelectorAll("video
|
|
75100
|
+
const videoEls = document2.querySelectorAll("video");
|
|
74965
75101
|
let autoIdCounter = 0;
|
|
74966
75102
|
for (const el of videoEls) {
|
|
74967
|
-
const src = el
|
|
75103
|
+
const src = resolveMediaElementSrc(el);
|
|
74968
75104
|
if (!src) continue;
|
|
74969
75105
|
const id = el.getAttribute(MEDIA_RENDER_ID_ATTR) || el.getAttribute("id") || `hf-video-${autoIdCounter++}`;
|
|
74970
75106
|
if (!el.getAttribute("id")) {
|
|
@@ -75040,7 +75176,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
75040
75176
|
const normalizedFps = toFps(options.fps);
|
|
75041
75177
|
const fps = fpsToNumber(normalizedFps);
|
|
75042
75178
|
const ffmpegFps = fpsToFfmpegArg(normalizedFps);
|
|
75043
|
-
const videoOutputDir = outputDirOverride ??
|
|
75179
|
+
const videoOutputDir = outputDirOverride ?? join11(outputDir, videoId);
|
|
75044
75180
|
if (!existsSync10(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
|
|
75045
75181
|
let metadata;
|
|
75046
75182
|
try {
|
|
@@ -75067,7 +75203,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
75067
75203
|
}
|
|
75068
75204
|
const format = resolveFrameFormat(metadata, options.format);
|
|
75069
75205
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
|
|
75070
|
-
const outputPattern =
|
|
75206
|
+
const outputPattern = join11(videoOutputDir, framePattern);
|
|
75071
75207
|
const isHdr = isHdrColorSpace(metadata.colorSpace);
|
|
75072
75208
|
const isMacOS = process.platform === "darwin";
|
|
75073
75209
|
const args = [];
|
|
@@ -75129,11 +75265,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
75129
75265
|
diagnostic
|
|
75130
75266
|
);
|
|
75131
75267
|
}
|
|
75132
|
-
const framePaths =
|
|
75133
|
-
const files = readdirSync5(videoOutputDir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(`.${format}`)).sort();
|
|
75134
|
-
files.forEach((file, index) => {
|
|
75135
|
-
framePaths.set(index, join10(videoOutputDir, file));
|
|
75136
|
-
});
|
|
75268
|
+
const framePaths = framePathsFromDirectory(videoOutputDir, format);
|
|
75137
75269
|
if (framePaths.size === 0 && duration > 0) {
|
|
75138
75270
|
throw new VideoSourceExtractionError(
|
|
75139
75271
|
"zero_output",
|
|
@@ -75323,16 +75455,9 @@ function resolveFrameFormat(metadata, requested) {
|
|
|
75323
75455
|
if (requested === "png" || requested === "jpg") return requested;
|
|
75324
75456
|
return "jpg";
|
|
75325
75457
|
}
|
|
75326
|
-
function extractedFrameFileNames(outputDir, format) {
|
|
75327
|
-
const suffix = `.${format}`;
|
|
75328
|
-
return readdirSync5(outputDir).filter((file) => file.startsWith(FRAME_FILENAME_PREFIX) && file.endsWith(suffix)).sort();
|
|
75329
|
-
}
|
|
75330
75458
|
function extractedFramesFromDirectory(work, outputDir, srcPath, fps) {
|
|
75331
75459
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${work.format}`;
|
|
75332
|
-
const framePaths =
|
|
75333
|
-
extractedFrameFileNames(outputDir, work.format).forEach((file, index) => {
|
|
75334
|
-
framePaths.set(index, join10(outputDir, file));
|
|
75335
|
-
});
|
|
75460
|
+
const framePaths = framePathsFromDirectory(outputDir, work.format);
|
|
75336
75461
|
return {
|
|
75337
75462
|
videoId: work.video.id,
|
|
75338
75463
|
srcPath,
|
|
@@ -75452,7 +75577,7 @@ function sliceSupersetMember(member, superset, outputDir, fps, configuredFps) {
|
|
|
75452
75577
|
for (let i = 0; i < frameCount; i += 1) {
|
|
75453
75578
|
const sourceFrame = superset.framePaths.get(member.offsetFrames + i);
|
|
75454
75579
|
if (!sourceFrame) throw new Error(`superset frame ${member.offsetFrames + i} missing`);
|
|
75455
|
-
linkOrCopyFrame(sourceFrame,
|
|
75580
|
+
linkOrCopyFrame(sourceFrame, join11(outputDir, frameFileName(i + 1, work.format)));
|
|
75456
75581
|
}
|
|
75457
75582
|
return extractedFramesFromDirectory(work, outputDir, work.videoPath, fps);
|
|
75458
75583
|
}
|
|
@@ -75465,22 +75590,22 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
|
|
|
75465
75590
|
if (!candidates.includes(candidate)) candidates.push(candidate);
|
|
75466
75591
|
};
|
|
75467
75592
|
for (const variant of decodeUrlPathVariants(cleanSrc)) {
|
|
75468
|
-
const fromCompiled = compiledDir ?
|
|
75469
|
-
const fromBase =
|
|
75593
|
+
const fromCompiled = compiledDir ? join11(compiledDir, variant) : null;
|
|
75594
|
+
const fromBase = join11(baseDir, variant);
|
|
75470
75595
|
const baseAbs = resolve5(baseDir);
|
|
75471
75596
|
const fromBaseAbs = resolve5(fromBase);
|
|
75472
75597
|
if (!fromBaseAbs.startsWith(baseAbs + sep2) && fromBaseAbs !== baseAbs) {
|
|
75473
75598
|
const normalized = posix2.normalize(variant.replace(/\\/g, "/"));
|
|
75474
75599
|
const stripped = normalized.replace(/^(\.\.\/)+/, "");
|
|
75475
75600
|
if (stripped && stripped !== variant && !stripped.startsWith("..")) {
|
|
75476
|
-
if (compiledDir) addCandidate(
|
|
75477
|
-
addCandidate(
|
|
75601
|
+
if (compiledDir) addCandidate(join11(compiledDir, stripped));
|
|
75602
|
+
addCandidate(join11(baseDir, stripped));
|
|
75478
75603
|
}
|
|
75479
75604
|
}
|
|
75480
75605
|
if (fromCompiled) addCandidate(fromCompiled);
|
|
75481
75606
|
addCandidate(fromBase);
|
|
75482
75607
|
}
|
|
75483
|
-
return candidates.find(existsSync10) ??
|
|
75608
|
+
return candidates.find(existsSync10) ?? join11(baseDir, cleanSrc);
|
|
75484
75609
|
}
|
|
75485
75610
|
async function extractAllVideoFrames(videos, baseDir, options, signal, config, compiledDir) {
|
|
75486
75611
|
if (options.timelineEnd !== void 0 && !Number.isFinite(options.timelineEnd)) {
|
|
@@ -75527,7 +75652,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
75527
75652
|
videoPath = resolveProjectRelativeSrc(video.src, baseDir, compiledDir);
|
|
75528
75653
|
}
|
|
75529
75654
|
if (isHttpUrl(videoPath)) {
|
|
75530
|
-
const downloadDir =
|
|
75655
|
+
const downloadDir = join11(options.outputDir, "_downloads");
|
|
75531
75656
|
mkdirSync6(downloadDir, { recursive: true });
|
|
75532
75657
|
videoPath = await downloadToTemp(
|
|
75533
75658
|
videoPath,
|
|
@@ -75735,7 +75860,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
75735
75860
|
async function extractDirectMiss(miss, maxTransientRetries = options.maxTransientRetries ?? 0) {
|
|
75736
75861
|
const { work, cacheTarget } = miss;
|
|
75737
75862
|
if (!cacheTarget) {
|
|
75738
|
-
const outputDir =
|
|
75863
|
+
const outputDir = join11(options.outputDir, work.video.id);
|
|
75739
75864
|
const attempted2 = await runVideoExtractionWithRetry(
|
|
75740
75865
|
() => extractVideoFramesRange(
|
|
75741
75866
|
work.videoPath,
|
|
@@ -75803,7 +75928,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
75803
75928
|
return sliceSupersetMember(
|
|
75804
75929
|
member,
|
|
75805
75930
|
superset,
|
|
75806
|
-
|
|
75931
|
+
join11(options.outputDir, work.video.id),
|
|
75807
75932
|
fps,
|
|
75808
75933
|
configuredFps
|
|
75809
75934
|
);
|
|
@@ -75820,7 +75945,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
75820
75945
|
async function executeSupersetGroup(group) {
|
|
75821
75946
|
const first = group.members[0]?.miss.work;
|
|
75822
75947
|
if (!first) return [];
|
|
75823
|
-
const tempDir = cacheRootDir ?
|
|
75948
|
+
const tempDir = cacheRootDir ? join11(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join11(options.outputDir, group.groupId);
|
|
75824
75949
|
try {
|
|
75825
75950
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
75826
75951
|
const superset = await extractVideoFramesRange(
|
|
@@ -76051,6 +76176,7 @@ var init_videoFrameExtractor = __esm({
|
|
|
76051
76176
|
init_config();
|
|
76052
76177
|
init_htmlTemplate();
|
|
76053
76178
|
init_extractionCache();
|
|
76179
|
+
init_extractedFrameIndex();
|
|
76054
76180
|
VIDEO_FRAME_FORMATS = ["auto", "jpg", "png"];
|
|
76055
76181
|
EXTRACT_CACHE_MIN_AGE_MS = 60 * 60 * 1e3;
|
|
76056
76182
|
GC_STALENESS_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -76884,7 +77010,7 @@ var init_audio_fx_runtime_inline = __esm({
|
|
|
76884
77010
|
// ../engine/src/services/audioFxRender.ts
|
|
76885
77011
|
import { existsSync as existsSync11, mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
76886
77012
|
import { tmpdir as tmpdir2 } from "os";
|
|
76887
|
-
import { join as
|
|
77013
|
+
import { join as join12 } from "path";
|
|
76888
77014
|
import { pathToFileURL } from "url";
|
|
76889
77015
|
function readWavChunks(buf) {
|
|
76890
77016
|
const head = { format: 1, channels: 1, sampleRate: 48e3, bits: 16 };
|
|
@@ -76997,7 +77123,7 @@ async function applyAudioFxChain(inputWav, chain, outputWav, options) {
|
|
|
76997
77123
|
const { samples, sampleRate, channels, float } = readWav(inputWav);
|
|
76998
77124
|
const planes = deinterleave(samples, channels);
|
|
76999
77125
|
if ((planes[0]?.length ?? 0) === 0) return { path: inputWav, envelopeBaked: false };
|
|
77000
|
-
const hostDir = mkdtempSync2(
|
|
77126
|
+
const hostDir = mkdtempSync2(join12(tmpdir2(), "hf-fx-host-"));
|
|
77001
77127
|
let lease = null;
|
|
77002
77128
|
try {
|
|
77003
77129
|
if (options.signal?.aborted) {
|
|
@@ -77006,7 +77132,7 @@ async function applyAudioFxChain(inputWav, chain, outputWav, options) {
|
|
|
77006
77132
|
lease = await acquireBrowser(["--no-sandbox", "--autoplay-policy=no-user-gesture-required"]);
|
|
77007
77133
|
const page = await lease.browser.newPage();
|
|
77008
77134
|
try {
|
|
77009
|
-
const hostPage =
|
|
77135
|
+
const hostPage = join12(hostDir, "audio-fx.html");
|
|
77010
77136
|
writeFileSync5(hostPage, "<!doctype html><meta charset=utf-8><title>audio fx</title>");
|
|
77011
77137
|
await page.goto(pathToFileURL(hostPage).href, { waitUntil: "domcontentloaded" });
|
|
77012
77138
|
await page.addScriptTag({ content: getAudioFxRuntimeScript() });
|
|
@@ -77143,7 +77269,7 @@ var init_audioFxRender = __esm({
|
|
|
77143
77269
|
|
|
77144
77270
|
// ../engine/src/services/audioMixer.ts
|
|
77145
77271
|
import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync3, openSync as openSync2, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
77146
|
-
import { join as
|
|
77272
|
+
import { join as join13, dirname as dirname7 } from "path";
|
|
77147
77273
|
function memberGroupKey(el) {
|
|
77148
77274
|
return el.getAttribute(AUDIO_GROUP_RENDER_ID_ATTR) ?? el.getAttribute(HF_AUDIO_GROUP_ATTR);
|
|
77149
77275
|
}
|
|
@@ -77394,7 +77520,7 @@ function parseAudioElements(html) {
|
|
|
77394
77520
|
const groupId = memberGroupKey(el);
|
|
77395
77521
|
return groupId ? groupsById.get(groupId)?.hidden ?? false : false;
|
|
77396
77522
|
};
|
|
77397
|
-
const build = (el, id, type) => {
|
|
77523
|
+
const build = (el, id, src, type) => {
|
|
77398
77524
|
const playbackRateAttr = el.getAttribute("data-playback-rate");
|
|
77399
77525
|
const layerAttr = el.getAttribute("data-layer");
|
|
77400
77526
|
const volumeAttr = el.getAttribute("data-volume");
|
|
@@ -77404,7 +77530,7 @@ function parseAudioElements(html) {
|
|
|
77404
77530
|
const group = groupId ? groupsById.get(groupId) : void 0;
|
|
77405
77531
|
return {
|
|
77406
77532
|
id,
|
|
77407
|
-
src
|
|
77533
|
+
src,
|
|
77408
77534
|
start: resolveStart2(el),
|
|
77409
77535
|
end: parseEnd(el.getAttribute("data-end")),
|
|
77410
77536
|
mediaStart: readMediaStart(el),
|
|
@@ -77425,17 +77551,19 @@ function parseAudioElements(html) {
|
|
|
77425
77551
|
};
|
|
77426
77552
|
};
|
|
77427
77553
|
const trackId = (el) => el.getAttribute(MEDIA_RENDER_ID_ATTR) || el.getAttribute("id");
|
|
77428
|
-
for (const el of document2.querySelectorAll("audio[id]
|
|
77554
|
+
for (const el of document2.querySelectorAll("audio[id]")) {
|
|
77429
77555
|
const id = trackId(el);
|
|
77430
|
-
|
|
77556
|
+
const src = resolveMediaElementSrc(el);
|
|
77557
|
+
if (!id || !src || isHidden(el) || memberGroupHidden(el)) continue;
|
|
77431
77558
|
if (isKnownInactiveTimelineWindow(el, resolveStart2(el))) continue;
|
|
77432
|
-
elements.push(build(el, id, "audio"));
|
|
77559
|
+
elements.push(build(el, id, src, "audio"));
|
|
77433
77560
|
}
|
|
77434
|
-
for (const el of document2.querySelectorAll('video[id][
|
|
77561
|
+
for (const el of document2.querySelectorAll('video[id][data-has-audio="true"]')) {
|
|
77435
77562
|
const id = trackId(el);
|
|
77436
|
-
|
|
77563
|
+
const src = resolveMediaElementSrc(el);
|
|
77564
|
+
if (!id || !src || isHidden(el)) continue;
|
|
77437
77565
|
if (isKnownInactiveTimelineWindow(el, resolveStart2(el))) continue;
|
|
77438
|
-
elements.push(build(el, `${id}-audio`, "video"));
|
|
77566
|
+
elements.push(build(el, `${id}-audio`, src, "video"));
|
|
77439
77567
|
}
|
|
77440
77568
|
return elements;
|
|
77441
77569
|
}
|
|
@@ -77607,8 +77735,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
|
|
|
77607
77735
|
const runMix = async (ignoreAutomation) => {
|
|
77608
77736
|
const inputs = [];
|
|
77609
77737
|
tracks.forEach((track) => inputs.push("-i", track.srcPath));
|
|
77610
|
-
const scriptDir = mkdtempSync3(
|
|
77611
|
-
const scriptPath =
|
|
77738
|
+
const scriptDir = mkdtempSync3(join13(outputDir, ".filter-complex-"));
|
|
77739
|
+
const scriptPath = join13(scriptDir, "graph.txt");
|
|
77612
77740
|
const fd = openSync2(scriptPath, "wx", 384);
|
|
77613
77741
|
try {
|
|
77614
77742
|
writeFileSync6(fd, buildFilterComplex(ignoreAutomation));
|
|
@@ -77714,8 +77842,8 @@ async function mixGroupMembers(memberTracks, outputPath, totalDuration, signal,
|
|
|
77714
77842
|
`${mixInputs}amix=inputs=${memberTracks.length}:duration=longest:dropout_transition=0[mixed];[mixed]volume=${formatFilterNumber(memberTracks.length)}[out]`
|
|
77715
77843
|
);
|
|
77716
77844
|
const filterComplex = [...inputFilters, mixFilter].join(";");
|
|
77717
|
-
const scriptDir = mkdtempSync3(
|
|
77718
|
-
const scriptPath =
|
|
77845
|
+
const scriptDir = mkdtempSync3(join13(outputDir, ".group-filter-complex-"));
|
|
77846
|
+
const scriptPath = join13(scriptDir, "graph.txt");
|
|
77719
77847
|
const fd = openSync2(scriptPath, "wx", 384);
|
|
77720
77848
|
try {
|
|
77721
77849
|
writeFileSync6(fd, filterComplex);
|
|
@@ -77865,7 +77993,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
77865
77993
|
}
|
|
77866
77994
|
let audioSrcPath = srcPath;
|
|
77867
77995
|
if (element.type === "video") {
|
|
77868
|
-
const extractedPath =
|
|
77996
|
+
const extractedPath = join13(workDir, `${element.id}-extracted.wav`);
|
|
77869
77997
|
const extractResult = await extractAudioFromVideo(
|
|
77870
77998
|
srcPath,
|
|
77871
77999
|
extractedPath,
|
|
@@ -77892,7 +78020,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
77892
78020
|
}
|
|
77893
78021
|
audioSrcPath = extractedPath;
|
|
77894
78022
|
} else {
|
|
77895
|
-
const trimmedPath =
|
|
78023
|
+
const trimmedPath = join13(workDir, `${element.id}-trimmed.wav`);
|
|
77896
78024
|
const prepResult = await prepareAudioTrack(
|
|
77897
78025
|
srcPath,
|
|
77898
78026
|
trimmedPath,
|
|
@@ -77936,7 +78064,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
77936
78064
|
const fxResult = await applyAudioFxChain(
|
|
77937
78065
|
audioSrcPath,
|
|
77938
78066
|
chain,
|
|
77939
|
-
|
|
78067
|
+
join13(workDir, `${element.id}-fx.wav`),
|
|
77940
78068
|
{
|
|
77941
78069
|
trackId: element.id,
|
|
77942
78070
|
signal: effectiveSignal,
|
|
@@ -78027,7 +78155,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
78027
78155
|
const meta = groupMeta.get(groupId);
|
|
78028
78156
|
if (!meta) continue;
|
|
78029
78157
|
const pathId = safePathSegment(groupId, groupIndex);
|
|
78030
|
-
const groupWavPath =
|
|
78158
|
+
const groupWavPath = join13(workDir, `group-${pathId}.wav`);
|
|
78031
78159
|
try {
|
|
78032
78160
|
const subMix = await mixGroupMembers(
|
|
78033
78161
|
memberTracks,
|
|
@@ -78063,7 +78191,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
78063
78191
|
const fxResult = await applyAudioFxChain(
|
|
78064
78192
|
groupSrcPath,
|
|
78065
78193
|
chain,
|
|
78066
|
-
|
|
78194
|
+
join13(workDir, `group-${pathId}-fx.wav`),
|
|
78067
78195
|
{
|
|
78068
78196
|
trackId: groupId,
|
|
78069
78197
|
signal: effectiveSignal,
|
|
@@ -78161,14 +78289,14 @@ var init_audioMixer = __esm({
|
|
|
78161
78289
|
import { execFile as execFile2 } from "child_process";
|
|
78162
78290
|
import { mkdtemp, rm, writeFile } from "fs/promises";
|
|
78163
78291
|
import { tmpdir as tmpdir3 } from "os";
|
|
78164
|
-
import { join as
|
|
78292
|
+
import { join as join14 } from "path";
|
|
78165
78293
|
import { promisify as promisify2 } from "util";
|
|
78166
78294
|
async function psnrDb(a, b) {
|
|
78167
78295
|
const execFileP = promisify2(execFile2);
|
|
78168
|
-
const dir = await mkdtemp(
|
|
78296
|
+
const dir = await mkdtemp(join14(tmpdir3(), "hf-de-verify-"));
|
|
78169
78297
|
try {
|
|
78170
|
-
const pa =
|
|
78171
|
-
const pb =
|
|
78298
|
+
const pa = join14(dir, "a.jpg");
|
|
78299
|
+
const pb = join14(dir, "b.jpg");
|
|
78172
78300
|
await Promise.all([writeFile(pa, a), writeFile(pb, b)]);
|
|
78173
78301
|
const { stderr } = await execFileP(
|
|
78174
78302
|
getFfmpegBinary(),
|
|
@@ -78279,7 +78407,7 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
|
|
|
78279
78407
|
import { cpus, freemem } from "os";
|
|
78280
78408
|
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
|
|
78281
78409
|
import { copyFile, readFile, rename } from "fs/promises";
|
|
78282
|
-
import { join as
|
|
78410
|
+
import { join as join15 } from "path";
|
|
78283
78411
|
import { getHeapStatistics } from "v8";
|
|
78284
78412
|
function defaultSafeMaxWorkers() {
|
|
78285
78413
|
return Math.max(6, Math.min(16, Math.floor(cpus().length / 8)));
|
|
@@ -78408,7 +78536,7 @@ function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
|
|
|
78408
78536
|
workerId: i,
|
|
78409
78537
|
startFrame,
|
|
78410
78538
|
endFrame,
|
|
78411
|
-
outputDir:
|
|
78539
|
+
outputDir: join15(workDir, `worker-${i}`),
|
|
78412
78540
|
outputFrameOffset: rangeStart
|
|
78413
78541
|
});
|
|
78414
78542
|
}
|
|
@@ -78422,7 +78550,7 @@ function distributeFramesInterleaved(totalFrames, workerCount, workDir, rangeSta
|
|
|
78422
78550
|
startFrame: rangeStart + i,
|
|
78423
78551
|
endFrame: rangeStart + totalFrames,
|
|
78424
78552
|
frameStride: workerCount,
|
|
78425
|
-
outputDir:
|
|
78553
|
+
outputDir: join15(workDir, `worker-${i}`),
|
|
78426
78554
|
outputFrameOffset: rangeStart
|
|
78427
78555
|
});
|
|
78428
78556
|
}
|
|
@@ -78580,7 +78708,7 @@ async function verifyDiskDrawElementSamples(session, task, streaming) {
|
|
|
78580
78708
|
for (const idx of selectVerifySampleIndicesForTask(truths.keys(), task)) {
|
|
78581
78709
|
const truth = truths.get(idx);
|
|
78582
78710
|
if (!truth) continue;
|
|
78583
|
-
const framePath =
|
|
78711
|
+
const framePath = join15(task.outputDir, `frame_${String(idx - offset2).padStart(6, "0")}.${ext}`);
|
|
78584
78712
|
const db = await psnrForDiskSample(framePath, truth, task.workerId, idx);
|
|
78585
78713
|
if (db === null) continue;
|
|
78586
78714
|
assertDiskSampleAboveFloor(db, verifyMinDb, idx, task.workerId);
|
|
@@ -78746,8 +78874,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
|
|
|
78746
78874
|
}
|
|
78747
78875
|
const files = readdirSync6(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
|
|
78748
78876
|
const copyTasks = files.map(async (file) => {
|
|
78749
|
-
const sourcePath =
|
|
78750
|
-
const targetPath =
|
|
78877
|
+
const sourcePath = join15(task.outputDir, file);
|
|
78878
|
+
const targetPath = join15(outputDir, file);
|
|
78751
78879
|
try {
|
|
78752
78880
|
await rename(sourcePath, targetPath);
|
|
78753
78881
|
} catch {
|
|
@@ -78793,7 +78921,7 @@ var init_parallelCoordinator = __esm({
|
|
|
78793
78921
|
import { Hono } from "hono";
|
|
78794
78922
|
import { serve } from "@hono/node-server";
|
|
78795
78923
|
import { readFileSync as readFileSync5, existsSync as existsSync14, statSync as statSync6 } from "fs";
|
|
78796
|
-
import { join as
|
|
78924
|
+
import { join as join16, extname as extname3 } from "path";
|
|
78797
78925
|
function createFileServer(options) {
|
|
78798
78926
|
const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
|
|
78799
78927
|
const headScripts = options.headScripts ?? [];
|
|
@@ -78803,11 +78931,11 @@ function createFileServer(options) {
|
|
|
78803
78931
|
let requestPath = c.req.path;
|
|
78804
78932
|
if (requestPath === "/") requestPath = "/index.html";
|
|
78805
78933
|
const relativePath = requestPath.replace(/^\//, "");
|
|
78806
|
-
const compiledPath = compiledDir ?
|
|
78934
|
+
const compiledPath = compiledDir ? join16(compiledDir, relativePath) : null;
|
|
78807
78935
|
const hasCompiledFile = Boolean(
|
|
78808
78936
|
compiledPath && existsSync14(compiledPath) && statSync6(compiledPath).isFile()
|
|
78809
78937
|
);
|
|
78810
|
-
const filePath = hasCompiledFile ? compiledPath :
|
|
78938
|
+
const filePath = hasCompiledFile ? compiledPath : join16(projectDir, relativePath);
|
|
78811
78939
|
if (!existsSync14(filePath) || !statSync6(filePath).isFile()) {
|
|
78812
78940
|
return c.text("Not found", 404);
|
|
78813
78941
|
}
|
|
@@ -80260,7 +80388,7 @@ var init_shaderTransitions = __esm({
|
|
|
80260
80388
|
|
|
80261
80389
|
// ../engine/src/services/hdrCapture.ts
|
|
80262
80390
|
import { existsSync as existsSync15, readdirSync as readdirSync7 } from "fs";
|
|
80263
|
-
import { join as
|
|
80391
|
+
import { join as join17 } from "path";
|
|
80264
80392
|
import { homedir as homedir2 } from "os";
|
|
80265
80393
|
function linearToPQ(L) {
|
|
80266
80394
|
const Lp = Math.max(0, L * SDR_NITS / PQ_MAX_NITS);
|
|
@@ -80376,12 +80504,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
|
|
|
80376
80504
|
return output;
|
|
80377
80505
|
}
|
|
80378
80506
|
function resolveHeadedChromePath() {
|
|
80379
|
-
const baseDir =
|
|
80507
|
+
const baseDir = join17(homedir2(), ".cache", "puppeteer", "chrome");
|
|
80380
80508
|
if (!existsSync15(baseDir)) return void 0;
|
|
80381
80509
|
const versions = readdirSync7(baseDir).sort().reverse();
|
|
80382
80510
|
for (const version2 of versions) {
|
|
80383
80511
|
const candidates = [
|
|
80384
|
-
|
|
80512
|
+
join17(
|
|
80385
80513
|
baseDir,
|
|
80386
80514
|
version2,
|
|
80387
80515
|
"chrome-mac-arm64",
|
|
@@ -80390,7 +80518,7 @@ function resolveHeadedChromePath() {
|
|
|
80390
80518
|
"MacOS",
|
|
80391
80519
|
"Google Chrome for Testing"
|
|
80392
80520
|
),
|
|
80393
|
-
|
|
80521
|
+
join17(
|
|
80394
80522
|
baseDir,
|
|
80395
80523
|
version2,
|
|
80396
80524
|
"chrome-mac-x64",
|
|
@@ -80399,8 +80527,8 @@ function resolveHeadedChromePath() {
|
|
|
80399
80527
|
"MacOS",
|
|
80400
80528
|
"Google Chrome for Testing"
|
|
80401
80529
|
),
|
|
80402
|
-
|
|
80403
|
-
|
|
80530
|
+
join17(baseDir, version2, "chrome-linux64", "chrome"),
|
|
80531
|
+
join17(baseDir, version2, "chrome-win64", "chrome.exe")
|
|
80404
80532
|
];
|
|
80405
80533
|
for (const binary of candidates) {
|
|
80406
80534
|
if (existsSync15(binary)) return binary;
|
|
@@ -80643,6 +80771,7 @@ __export(src_exports, {
|
|
|
80643
80771
|
resolveHeadlessShellPath: () => resolveHeadlessShellPath,
|
|
80644
80772
|
resolvePlayableVideoDuration: () => resolvePlayableVideoDuration,
|
|
80645
80773
|
resolveProjectRelativeSrc: () => resolveProjectRelativeSrc,
|
|
80774
|
+
resolveReferencedStart: () => resolveReferencedStart,
|
|
80646
80775
|
resolveTimelineExtractionWindow: () => resolveTimelineExtractionWindow,
|
|
80647
80776
|
resolveVideoExtractionDuration: () => resolveVideoExtractionDuration,
|
|
80648
80777
|
resolveVideoExtractionWindow: () => resolveVideoExtractionWindow,
|
|
@@ -80680,6 +80809,7 @@ var init_src = __esm({
|
|
|
80680
80809
|
init_chunkEncoder();
|
|
80681
80810
|
init_streamingEncoder();
|
|
80682
80811
|
init_videoFrameExtractor();
|
|
80812
|
+
init_referenceResolver();
|
|
80683
80813
|
init_videoFrameInjector();
|
|
80684
80814
|
init_audioMixer();
|
|
80685
80815
|
init_captureWarning();
|
|
@@ -83875,7 +84005,7 @@ __export(fontCompression_exports, {
|
|
|
83875
84005
|
import { createHash as createHash6 } from "crypto";
|
|
83876
84006
|
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
83877
84007
|
import { homedir as homedir4, tmpdir as tmpdir4 } from "os";
|
|
83878
|
-
import { dirname as dirname11, join as
|
|
84008
|
+
import { dirname as dirname11, join as join24 } from "path";
|
|
83879
84009
|
async function compressToWoff2(input) {
|
|
83880
84010
|
return Buffer.from(await compress(input));
|
|
83881
84011
|
}
|
|
@@ -83883,12 +84013,12 @@ function rawMimeType(format) {
|
|
|
83883
84013
|
return RAW_MIME_TYPES[format] ?? "font/ttf";
|
|
83884
84014
|
}
|
|
83885
84015
|
function defaultCacheDir() {
|
|
83886
|
-
const root = process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ?
|
|
83887
|
-
return
|
|
84016
|
+
const root = process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join24(tmpdir4(), "hyperframes", "fonts") : join24(homedir4(), ".cache", "hyperframes", "fonts"));
|
|
84017
|
+
return join24(root, "local-compression-v1");
|
|
83888
84018
|
}
|
|
83889
84019
|
function cachedCompressionPath(input, originalFormat, cacheDir) {
|
|
83890
84020
|
const digest = createHash6("sha256").update("hyperframes-local-font-compression-v1\0").update(originalFormat).update("\0").update(input).digest("hex");
|
|
83891
|
-
return
|
|
84021
|
+
return join24(cacheDir, `${digest}.woff2`);
|
|
83892
84022
|
}
|
|
83893
84023
|
function readCachedCompression(path) {
|
|
83894
84024
|
try {
|
|
@@ -83968,7 +84098,7 @@ import {
|
|
|
83968
84098
|
appendFileSync
|
|
83969
84099
|
} from "fs";
|
|
83970
84100
|
import { tmpdir as tmpdir7 } from "os";
|
|
83971
|
-
import { join as
|
|
84101
|
+
import { join as join41, dirname as dirname16, resolve as resolve13 } from "path";
|
|
83972
84102
|
import { totalmem as totalmem3 } from "os";
|
|
83973
84103
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
83974
84104
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -83981,7 +84111,7 @@ import { serve as serve2 } from "@hono/node-server";
|
|
|
83981
84111
|
import { existsSync as existsSync17, realpathSync as realpathSync2, statSync as statSync7, createReadStream as createReadStream3 } from "fs";
|
|
83982
84112
|
import { readFile as readFile2 } from "fs/promises";
|
|
83983
84113
|
import { Readable as Readable2 } from "stream";
|
|
83984
|
-
import { join as
|
|
84114
|
+
import { join as join18, extname as extname4, resolve as resolve7, sep as sep3 } from "path";
|
|
83985
84115
|
|
|
83986
84116
|
// ../producer/src/services/hyperframeRuntimeLoader.ts
|
|
83987
84117
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -84571,13 +84701,13 @@ function createFileServer2(options) {
|
|
|
84571
84701
|
}).join("/");
|
|
84572
84702
|
let filePath = null;
|
|
84573
84703
|
if (compiledDir) {
|
|
84574
|
-
const candidate =
|
|
84704
|
+
const candidate = join18(compiledDir, relativePath);
|
|
84575
84705
|
if (existsSync17(candidate) && isPathInside2(candidate, compiledDir) && statSync7(candidate).isFile()) {
|
|
84576
84706
|
filePath = candidate;
|
|
84577
84707
|
}
|
|
84578
84708
|
}
|
|
84579
84709
|
if (!filePath) {
|
|
84580
|
-
const candidate =
|
|
84710
|
+
const candidate = join18(projectDir, relativePath);
|
|
84581
84711
|
if (existsSync17(candidate) && isPathInside2(candidate, projectDir) && statSync7(candidate).isFile()) {
|
|
84582
84712
|
filePath = candidate;
|
|
84583
84713
|
}
|
|
@@ -84682,12 +84812,12 @@ import {
|
|
|
84682
84812
|
symlinkSync,
|
|
84683
84813
|
writeFileSync as writeFileSync7
|
|
84684
84814
|
} from "fs";
|
|
84685
|
-
import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute2, join as
|
|
84815
|
+
import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute2, join as join20, relative, resolve as resolve8 } from "path";
|
|
84686
84816
|
|
|
84687
84817
|
// ../producer/src/utils/paths.ts
|
|
84688
84818
|
import {
|
|
84689
84819
|
basename as basename3,
|
|
84690
|
-
join as
|
|
84820
|
+
join as join19,
|
|
84691
84821
|
resolve as nodeResolve,
|
|
84692
84822
|
relative as nodeRelative,
|
|
84693
84823
|
isAbsolute as nodeIsAbsolute
|
|
@@ -84725,7 +84855,7 @@ function formatExportFrameName(index, ext) {
|
|
|
84725
84855
|
function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
|
|
84726
84856
|
const absoluteProjectDir = nodeResolve(projectDir);
|
|
84727
84857
|
const projectName = basename3(absoluteProjectDir);
|
|
84728
|
-
const resolvedOutputPath = outputPath ??
|
|
84858
|
+
const resolvedOutputPath = outputPath ?? join19(rendersDir, `${projectName}.mp4`);
|
|
84729
84859
|
const absoluteOutputPath = nodeResolve(resolvedOutputPath);
|
|
84730
84860
|
return { absoluteProjectDir, absoluteOutputPath };
|
|
84731
84861
|
}
|
|
@@ -84762,16 +84892,16 @@ function resolveDeviceScaleFactor(input) {
|
|
|
84762
84892
|
return target.width / input.compositionWidth;
|
|
84763
84893
|
}
|
|
84764
84894
|
function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
84765
|
-
const compileDir =
|
|
84895
|
+
const compileDir = join20(workDir, "compiled");
|
|
84766
84896
|
mkdirSync9(compileDir, { recursive: true });
|
|
84767
|
-
writeFileSync7(
|
|
84897
|
+
writeFileSync7(join20(compileDir, "index.html"), compiled.html, "utf-8");
|
|
84768
84898
|
for (const [srcPath, html] of compiled.subCompositions) {
|
|
84769
|
-
const outPath =
|
|
84899
|
+
const outPath = join20(compileDir, srcPath);
|
|
84770
84900
|
mkdirSync9(dirname9(outPath), { recursive: true });
|
|
84771
84901
|
writeFileSync7(outPath, html, "utf-8");
|
|
84772
84902
|
}
|
|
84773
84903
|
for (const [relativePath, absolutePath] of compiled.externalAssets) {
|
|
84774
|
-
const outPath = resolve8(
|
|
84904
|
+
const outPath = resolve8(join20(compileDir, relativePath));
|
|
84775
84905
|
if (!isPathInside3(outPath, compileDir)) {
|
|
84776
84906
|
console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
|
|
84777
84907
|
continue;
|
|
@@ -84802,7 +84932,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
84802
84932
|
renderModeHints: compiled.renderModeHints,
|
|
84803
84933
|
hasShaderTransitions: compiled.hasShaderTransitions
|
|
84804
84934
|
};
|
|
84805
|
-
writeFileSync7(
|
|
84935
|
+
writeFileSync7(join20(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
|
|
84806
84936
|
}
|
|
84807
84937
|
}
|
|
84808
84938
|
function applyRenderModeHints(alreadyForced, compiled, log = defaultLogger) {
|
|
@@ -84829,7 +84959,7 @@ function updateJobStatus(job, status, stage, progress, onProgress) {
|
|
|
84829
84959
|
}
|
|
84830
84960
|
var materializePathModule = {
|
|
84831
84961
|
resolve: resolve8,
|
|
84832
|
-
join:
|
|
84962
|
+
join: join20,
|
|
84833
84963
|
dirname: dirname9,
|
|
84834
84964
|
basename: basename4,
|
|
84835
84965
|
relative,
|
|
@@ -85097,17 +85227,29 @@ import {
|
|
|
85097
85227
|
renameSync as renameSync3,
|
|
85098
85228
|
rmSync as rmSync7
|
|
85099
85229
|
} from "fs";
|
|
85100
|
-
import { basename as basename5, dirname as dirname10, extname as extname5, join as
|
|
85230
|
+
import { basename as basename5, dirname as dirname10, extname as extname5, join as join21, resolve as resolve9 } from "path";
|
|
85231
|
+
|
|
85232
|
+
// ../producer/src/utils/ffprobe.ts
|
|
85233
|
+
init_src();
|
|
85234
|
+
|
|
85235
|
+
// ../producer/src/services/render/artifactTransaction.ts
|
|
85101
85236
|
var defaultFileSystem = {
|
|
85102
85237
|
existsSync: existsSync19,
|
|
85103
85238
|
renameSync: renameSync3,
|
|
85104
85239
|
rmSync: rmSync7
|
|
85105
85240
|
};
|
|
85241
|
+
async function defaultArtifactDurationProbe(path) {
|
|
85242
|
+
const meta = await extractMediaMetadata(path);
|
|
85243
|
+
return {
|
|
85244
|
+
durationSeconds: meta.durationSeconds,
|
|
85245
|
+
frames: meta.frames
|
|
85246
|
+
};
|
|
85247
|
+
}
|
|
85106
85248
|
function createSiblingTransactionDirectory(destination) {
|
|
85107
85249
|
const parent = dirname10(destination);
|
|
85108
85250
|
const extension = extname5(destination);
|
|
85109
85251
|
const stem = extension ? basename5(destination, extension) : basename5(destination);
|
|
85110
|
-
return mkdtempSync4(
|
|
85252
|
+
return mkdtempSync4(join21(parent, `.${stem}.hf-transaction-`));
|
|
85111
85253
|
}
|
|
85112
85254
|
function assertReadableNonEmptyFile(path) {
|
|
85113
85255
|
const fd = openSync3(path, "r");
|
|
@@ -85125,7 +85267,7 @@ function collectDirectoryFiles(root) {
|
|
|
85125
85267
|
const files = [];
|
|
85126
85268
|
const visit = (directory) => {
|
|
85127
85269
|
for (const entry of readdirSync8(directory, { withFileTypes: true })) {
|
|
85128
|
-
const path =
|
|
85270
|
+
const path = join21(directory, entry.name);
|
|
85129
85271
|
if (entry.isDirectory()) visit(path);
|
|
85130
85272
|
else if (entry.isFile()) files.push(path);
|
|
85131
85273
|
}
|
|
@@ -85133,14 +85275,44 @@ function collectDirectoryFiles(root) {
|
|
|
85133
85275
|
visit(root);
|
|
85134
85276
|
return files;
|
|
85135
85277
|
}
|
|
85278
|
+
function durationToleranceSeconds(expected) {
|
|
85279
|
+
if (expected.toleranceSeconds !== void 0) return expected.toleranceSeconds;
|
|
85280
|
+
const fps = expected.fps;
|
|
85281
|
+
return fps && fps > 0 ? 1 / fps : 0.02;
|
|
85282
|
+
}
|
|
85283
|
+
function assertUsableProbedDuration(probedSeconds, expectedSeconds, stagingPath) {
|
|
85284
|
+
if (!Number.isFinite(probedSeconds) || probedSeconds <= 0) {
|
|
85285
|
+
throw new Error(
|
|
85286
|
+
`Render artifact duration probe returned no usable duration for ${stagingPath} (got ${String(probedSeconds)}); expected ${expectedSeconds.toFixed(3)}s. Refusing to publish an artifact whose duration cannot be verified.`
|
|
85287
|
+
);
|
|
85288
|
+
}
|
|
85289
|
+
}
|
|
85290
|
+
function assertDurationWithinTolerance(expectedSeconds, probedSeconds, toleranceSeconds, stagingPath) {
|
|
85291
|
+
const deficit = expectedSeconds - probedSeconds;
|
|
85292
|
+
if (deficit <= toleranceSeconds) return;
|
|
85293
|
+
throw new Error(
|
|
85294
|
+
`Render artifact is truncated: expected ${expectedSeconds.toFixed(3)}s, probed ${probedSeconds.toFixed(3)}s (deficit ${deficit.toFixed(3)}s exceeds tolerance ${toleranceSeconds.toFixed(3)}s). Artifact: ${stagingPath}`
|
|
85295
|
+
);
|
|
85296
|
+
}
|
|
85297
|
+
function assertFrameCountWithinTolerance(expectedFrames, probedFrames, stagingPath) {
|
|
85298
|
+
if (probedFrames === void 0 || !Number.isFinite(probedFrames) || probedFrames <= 0) {
|
|
85299
|
+
return;
|
|
85300
|
+
}
|
|
85301
|
+
const shortfall = expectedFrames - probedFrames;
|
|
85302
|
+
if (shortfall <= 1) return;
|
|
85303
|
+
throw new Error(
|
|
85304
|
+
`Render artifact is truncated: expected ${expectedFrames} frames, probed ${probedFrames} frames (shortfall ${shortfall} frames). Artifact: ${stagingPath}`
|
|
85305
|
+
);
|
|
85306
|
+
}
|
|
85136
85307
|
var ArtifactTransaction = class {
|
|
85137
|
-
constructor(destinationPath, kind, fileSystem = defaultFileSystem) {
|
|
85308
|
+
constructor(destinationPath, kind, fileSystem = defaultFileSystem, durationProbe = defaultArtifactDurationProbe) {
|
|
85138
85309
|
this.kind = kind;
|
|
85139
85310
|
this.fileSystem = fileSystem;
|
|
85140
85311
|
this.destinationPath = resolve9(destinationPath);
|
|
85141
85312
|
this.transactionDirectory = createSiblingTransactionDirectory(this.destinationPath);
|
|
85142
|
-
this.stagingPath =
|
|
85143
|
-
this.backupPath =
|
|
85313
|
+
this.stagingPath = join21(this.transactionDirectory, basename5(this.destinationPath));
|
|
85314
|
+
this.backupPath = join21(this.transactionDirectory, "backup");
|
|
85315
|
+
this.durationProbe = durationProbe;
|
|
85144
85316
|
}
|
|
85145
85317
|
kind;
|
|
85146
85318
|
fileSystem;
|
|
@@ -85149,9 +85321,11 @@ var ArtifactTransaction = class {
|
|
|
85149
85321
|
transactionDirectory;
|
|
85150
85322
|
backupPath;
|
|
85151
85323
|
state = "active";
|
|
85152
|
-
|
|
85324
|
+
durationProbe;
|
|
85325
|
+
async validate(expected) {
|
|
85153
85326
|
if (this.kind === "file") {
|
|
85154
85327
|
assertReadableNonEmptyFile(this.stagingPath);
|
|
85328
|
+
if (expected) await this.assertArtifactDuration(expected);
|
|
85155
85329
|
return;
|
|
85156
85330
|
}
|
|
85157
85331
|
let files;
|
|
@@ -85167,11 +85341,37 @@ var ArtifactTransaction = class {
|
|
|
85167
85341
|
}
|
|
85168
85342
|
for (const file of files) assertReadableNonEmptyFile(file);
|
|
85169
85343
|
}
|
|
85170
|
-
|
|
85344
|
+
async assertArtifactDuration(expected) {
|
|
85345
|
+
const expectedSeconds = expected.expectedDurationSeconds;
|
|
85346
|
+
if (!Number.isFinite(expectedSeconds) || expectedSeconds <= 0) return;
|
|
85347
|
+
const probed = await this.runDurationProbe();
|
|
85348
|
+
assertUsableProbedDuration(probed.durationSeconds, expectedSeconds, this.stagingPath);
|
|
85349
|
+
const toleranceSeconds = durationToleranceSeconds(expected);
|
|
85350
|
+
assertDurationWithinTolerance(
|
|
85351
|
+
expectedSeconds,
|
|
85352
|
+
probed.durationSeconds,
|
|
85353
|
+
toleranceSeconds,
|
|
85354
|
+
this.stagingPath
|
|
85355
|
+
);
|
|
85356
|
+
if (expected.expectedFrames !== void 0) {
|
|
85357
|
+
assertFrameCountWithinTolerance(expected.expectedFrames, probed.frames, this.stagingPath);
|
|
85358
|
+
}
|
|
85359
|
+
}
|
|
85360
|
+
async runDurationProbe() {
|
|
85361
|
+
try {
|
|
85362
|
+
return await this.durationProbe(this.stagingPath);
|
|
85363
|
+
} catch (error) {
|
|
85364
|
+
throw new Error(
|
|
85365
|
+
`Render artifact duration probe failed for ${this.stagingPath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
85366
|
+
{ cause: error }
|
|
85367
|
+
);
|
|
85368
|
+
}
|
|
85369
|
+
}
|
|
85370
|
+
async commit() {
|
|
85171
85371
|
if (this.state !== "active") {
|
|
85172
85372
|
throw new Error(`Cannot commit an artifact transaction in state ${this.state}`);
|
|
85173
85373
|
}
|
|
85174
|
-
this.validate();
|
|
85374
|
+
await this.validate();
|
|
85175
85375
|
const hadDestination = this.fileSystem.existsSync(this.destinationPath);
|
|
85176
85376
|
if (this.kind === "file" || !hadDestination) {
|
|
85177
85377
|
this.fileSystem.renameSync(this.stagingPath, this.destinationPath);
|
|
@@ -85676,7 +85876,7 @@ function resolveVideoCaptureBeyondViewport(videoCount) {
|
|
|
85676
85876
|
// ../producer/src/services/render/captureCost.ts
|
|
85677
85877
|
init_dist2();
|
|
85678
85878
|
init_src();
|
|
85679
|
-
import { join as
|
|
85879
|
+
import { join as join22 } from "path";
|
|
85680
85880
|
var CAPTURE_CALIBRATION_TARGET_MS = 600;
|
|
85681
85881
|
var MAX_MEASURED_CAPTURE_COST_MULTIPLIER = 8;
|
|
85682
85882
|
var CAPTURE_CALIBRATION_PROTOCOL_TIMEOUT_MS = 3e4;
|
|
@@ -85912,7 +86112,7 @@ async function runCaptureCalibration(input) {
|
|
|
85912
86112
|
});
|
|
85913
86113
|
let calibration;
|
|
85914
86114
|
try {
|
|
85915
|
-
calibration = await runOneCalibration(
|
|
86115
|
+
calibration = await runOneCalibration(join22(workDir, "capture-calibration"), calibrationCfg);
|
|
85916
86116
|
} catch (error) {
|
|
85917
86117
|
const shouldFallback = !forceScreenshot && shouldFallbackToScreenshotAfterCalibrationError(error);
|
|
85918
86118
|
if (!shouldFallback) {
|
|
@@ -85945,7 +86145,7 @@ async function runCaptureCalibration(input) {
|
|
|
85945
86145
|
const screenshotCfg = createCaptureCalibrationConfig({ ...cfg, forceScreenshot: true });
|
|
85946
86146
|
try {
|
|
85947
86147
|
calibration = await runOneCalibration(
|
|
85948
|
-
|
|
86148
|
+
join22(workDir, "capture-calibration-screenshot"),
|
|
85949
86149
|
screenshotCfg
|
|
85950
86150
|
);
|
|
85951
86151
|
} catch (fallbackError) {
|
|
@@ -86366,7 +86566,7 @@ function countAuthoredTimedClips(html) {
|
|
|
86366
86566
|
|
|
86367
86567
|
// ../producer/src/services/render/stages/compileStage.ts
|
|
86368
86568
|
init_dist2();
|
|
86369
|
-
import { join as
|
|
86569
|
+
import { join as join28 } from "path";
|
|
86370
86570
|
|
|
86371
86571
|
// ../producer/src/services/htmlCompiler.ts
|
|
86372
86572
|
init_esm10();
|
|
@@ -86376,10 +86576,7 @@ init_compiler();
|
|
|
86376
86576
|
init_subCompositionValidity();
|
|
86377
86577
|
init_assetResolution();
|
|
86378
86578
|
import { createReadStream as createReadStream4, existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync10 } from "fs";
|
|
86379
|
-
import { join as
|
|
86380
|
-
|
|
86381
|
-
// ../producer/src/utils/ffprobe.ts
|
|
86382
|
-
init_src();
|
|
86579
|
+
import { join as join27, dirname as dirname13, resolve as resolve12, basename as basename6 } from "path";
|
|
86383
86580
|
|
|
86384
86581
|
// ../producer/src/services/renderMediaCollector.ts
|
|
86385
86582
|
init_esm10();
|
|
@@ -86392,7 +86589,7 @@ function parseNumeric2(value) {
|
|
|
86392
86589
|
const parsed = Number.parseFloat(value);
|
|
86393
86590
|
return Number.isFinite(parsed) ? parsed : null;
|
|
86394
86591
|
}
|
|
86395
|
-
function resolveHostWindow(element) {
|
|
86592
|
+
function resolveHostWindow(element, document2, startCache, visiting) {
|
|
86396
86593
|
const hosts = [];
|
|
86397
86594
|
for (let ancestor2 = element.parentElement; ancestor2; ancestor2 = ancestor2.parentElement) {
|
|
86398
86595
|
if (ancestor2.hasAttribute(COMPOSITION_HOST_ATTR)) hosts.push(ancestor2);
|
|
@@ -86401,7 +86598,7 @@ function resolveHostWindow(element) {
|
|
|
86401
86598
|
let offset2 = 0;
|
|
86402
86599
|
let limit = Infinity;
|
|
86403
86600
|
for (const host of hosts.reverse()) {
|
|
86404
|
-
const hostStart =
|
|
86601
|
+
const hostStart = resolveReferencedStart(document2, host, startCache, visiting);
|
|
86405
86602
|
const hostEnd = parseNumeric2(host.getAttribute("data-end"));
|
|
86406
86603
|
if (hostEnd != null) limit = Math.min(limit, offset2 + hostEnd);
|
|
86407
86604
|
offset2 += hostStart;
|
|
@@ -86411,10 +86608,15 @@ function resolveHostWindow(element) {
|
|
|
86411
86608
|
function collectHostWindows(html) {
|
|
86412
86609
|
const { document: document2 } = parseHTML(html);
|
|
86413
86610
|
const windows = /* @__PURE__ */ new Map();
|
|
86611
|
+
const startCache = /* @__PURE__ */ new Map();
|
|
86612
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
86414
86613
|
for (const element of document2.querySelectorAll(`[${MEDIA_RENDER_ID_ATTR}]`)) {
|
|
86415
86614
|
const renderId = element.getAttribute(MEDIA_RENDER_ID_ATTR);
|
|
86416
86615
|
if (!renderId) continue;
|
|
86417
|
-
windows.set(
|
|
86616
|
+
windows.set(
|
|
86617
|
+
renderId,
|
|
86618
|
+
resolveHostWindow(element, document2, startCache, visiting)
|
|
86619
|
+
);
|
|
86418
86620
|
}
|
|
86419
86621
|
return windows;
|
|
86420
86622
|
}
|
|
@@ -86462,7 +86664,7 @@ init_src();
|
|
|
86462
86664
|
import { createHash as createHash7 } from "crypto";
|
|
86463
86665
|
import { existsSync as existsSync22, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
86464
86666
|
import { homedir as homedir5, tmpdir as tmpdir5 } from "os";
|
|
86465
|
-
import { join as
|
|
86667
|
+
import { join as join25 } from "path";
|
|
86466
86668
|
|
|
86467
86669
|
// ../core/dist/fonts/aliases.js
|
|
86468
86670
|
init_dist();
|
|
@@ -86471,7 +86673,7 @@ init_dist();
|
|
|
86471
86673
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
86472
86674
|
import { existsSync as existsSync20, lstatSync as lstatSync3, readdirSync as readdirSync9, realpathSync as realpathSync3 } from "fs";
|
|
86473
86675
|
import { homedir as homedir3, platform as platform2 } from "os";
|
|
86474
|
-
import { join as
|
|
86676
|
+
import { join as join23, resolve as resolve10 } from "path";
|
|
86475
86677
|
var SYSTEM_FONT_SIZE_LIMIT = 5 * 1024 * 1024;
|
|
86476
86678
|
var PROFILER_TIMEOUT_MS = 5e3;
|
|
86477
86679
|
var FONT_EXT_RE = /\.(otf|ttf|ttc|woff2?)$/i;
|
|
@@ -86568,7 +86770,7 @@ function fontDirectories() {
|
|
|
86568
86770
|
const home = homedir3();
|
|
86569
86771
|
if (platform2() === "darwin") {
|
|
86570
86772
|
return [
|
|
86571
|
-
|
|
86773
|
+
join23(home, "Library", "Fonts"),
|
|
86572
86774
|
"/Library/Fonts",
|
|
86573
86775
|
"/System/Library/Fonts",
|
|
86574
86776
|
"/System/Library/Fonts/Supplemental"
|
|
@@ -86576,13 +86778,13 @@ function fontDirectories() {
|
|
|
86576
86778
|
}
|
|
86577
86779
|
if (platform2() === "win32") {
|
|
86578
86780
|
return [
|
|
86579
|
-
|
|
86580
|
-
|
|
86781
|
+
join23(process.env.WINDIR || "C:\\Windows", "Fonts"),
|
|
86782
|
+
join23(process.env.LOCALAPPDATA || join23(homedir3(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
|
|
86581
86783
|
];
|
|
86582
86784
|
}
|
|
86583
86785
|
return [
|
|
86584
|
-
|
|
86585
|
-
|
|
86786
|
+
join23(home, ".fonts"),
|
|
86787
|
+
join23(home, ".local", "share", "fonts"),
|
|
86586
86788
|
"/usr/local/share/fonts",
|
|
86587
86789
|
"/usr/share/fonts"
|
|
86588
86790
|
];
|
|
@@ -86593,7 +86795,7 @@ function collectFontFileEntries(dir, depth = 0) {
|
|
|
86593
86795
|
const entries2 = [];
|
|
86594
86796
|
try {
|
|
86595
86797
|
for (const entry of readdirSync9(dir, { withFileTypes: true })) {
|
|
86596
|
-
const fullPath =
|
|
86798
|
+
const fullPath = join23(dir, entry.name);
|
|
86597
86799
|
if (entry.isDirectory()) {
|
|
86598
86800
|
entries2.push(...collectFontFileEntries(fullPath, depth + 1));
|
|
86599
86801
|
continue;
|
|
@@ -87241,17 +87443,17 @@ function resolveFontCacheRoot() {
|
|
|
87241
87443
|
return process.env.HYPERFRAMES_FONT_CACHE_DIR;
|
|
87242
87444
|
}
|
|
87243
87445
|
if (process.env.AWS_LAMBDA_FUNCTION_NAME) {
|
|
87244
|
-
lambdaFontCacheRoot ??= mkdtempSync5(
|
|
87446
|
+
lambdaFontCacheRoot ??= mkdtempSync5(join25(tmpdir5(), "hyperframes-fonts-"));
|
|
87245
87447
|
return lambdaFontCacheRoot;
|
|
87246
87448
|
}
|
|
87247
|
-
return
|
|
87449
|
+
return join25(homedir5(), ".cache", "hyperframes", "fonts");
|
|
87248
87450
|
}
|
|
87249
87451
|
var 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";
|
|
87250
87452
|
function fontSlug(familyName) {
|
|
87251
87453
|
return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
87252
87454
|
}
|
|
87253
87455
|
function fontCacheDir(slug) {
|
|
87254
|
-
const dir =
|
|
87456
|
+
const dir = join25(resolveFontCacheRoot(), slug);
|
|
87255
87457
|
if (!existsSync22(dir)) {
|
|
87256
87458
|
mkdirSync11(dir, { recursive: true });
|
|
87257
87459
|
}
|
|
@@ -87261,7 +87463,7 @@ function subsetToken(woff2Url) {
|
|
|
87261
87463
|
return createHash7("sha1").update(woff2Url).digest("hex").slice(0, 12);
|
|
87262
87464
|
}
|
|
87263
87465
|
function cachedWoff2Path(slug, weight, style, subset) {
|
|
87264
|
-
return
|
|
87466
|
+
return join25(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
|
|
87265
87467
|
}
|
|
87266
87468
|
var FONT_FETCH_FAILED = "FONT_FETCH_FAILED";
|
|
87267
87469
|
var FONT_FETCH_UNAVAILABLE = "FONT_FETCH_UNAVAILABLE";
|
|
@@ -87578,7 +87780,7 @@ import {
|
|
|
87578
87780
|
rmSync as rmSync9,
|
|
87579
87781
|
statSync as statSync8
|
|
87580
87782
|
} from "fs";
|
|
87581
|
-
import { dirname as dirname12, isAbsolute as isAbsolute3, join as
|
|
87783
|
+
import { dirname as dirname12, isAbsolute as isAbsolute3, join as join26, resolve as resolve11 } from "path";
|
|
87582
87784
|
var PREPARED_GIF_SUBDIR = "_animated_gif";
|
|
87583
87785
|
var CACHE_SCHEMA = "hfgif-v1";
|
|
87584
87786
|
function splitUrlSuffix(src) {
|
|
@@ -87812,7 +88014,7 @@ function replaceImageWithVideo(input) {
|
|
|
87812
88014
|
return video;
|
|
87813
88015
|
}
|
|
87814
88016
|
async function prepareAnimatedGifInputs(html, options) {
|
|
87815
|
-
const outputDir = options.outputDir ??
|
|
88017
|
+
const outputDir = options.outputDir ?? join26(options.downloadDir, PREPARED_GIF_SUBDIR);
|
|
87816
88018
|
const outputSrcPrefix = normalizeRelPath(options.outputSrcPrefix ?? PREPARED_GIF_SUBDIR);
|
|
87817
88019
|
const cacheDir = options.cacheDir ?? outputDir;
|
|
87818
88020
|
const { document: document2 } = parseHTML(html);
|
|
@@ -87834,8 +88036,8 @@ async function prepareAnimatedGifInputs(html, options) {
|
|
|
87834
88036
|
const { loopIterations, padSeconds } = resolvePreparedPlayback(metadata, loop, windowSeconds);
|
|
87835
88037
|
const hash2 = computePreparedGifHash(bytes, loopIterations, padSeconds);
|
|
87836
88038
|
const filename = `${CACHE_SCHEMA}-${hash2.slice(0, 24)}.webm`;
|
|
87837
|
-
const cachePath =
|
|
87838
|
-
const outputPath =
|
|
88039
|
+
const cachePath = join26(cacheDir, filename);
|
|
88040
|
+
const outputPath = join26(outputDir, filename);
|
|
87839
88041
|
const outputSrc = `${outputSrcPrefix}/${filename}`;
|
|
87840
88042
|
await ensurePreparedWebm({
|
|
87841
88043
|
sourcePath,
|
|
@@ -88504,7 +88706,7 @@ async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, down
|
|
|
88504
88706
|
return { duration: null, resolvedPath: src };
|
|
88505
88707
|
}
|
|
88506
88708
|
} else if (!filePath.startsWith("/")) {
|
|
88507
|
-
filePath =
|
|
88709
|
+
filePath = join27(baseDir, filePath);
|
|
88508
88710
|
}
|
|
88509
88711
|
if (!existsSync25(filePath)) {
|
|
88510
88712
|
return { duration: null, resolvedPath: filePath };
|
|
@@ -89036,6 +89238,7 @@ function collectExternalAssets(html, projectDir) {
|
|
|
89036
89238
|
}
|
|
89037
89239
|
var REMOTE_MEDIA_SUBDIR = "_remote_media";
|
|
89038
89240
|
var REMOTE_MEDIA_TAG_RE = /<(?:video|audio)\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
89241
|
+
var REMOTE_SOURCE_TAG_RE = /<source\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
89039
89242
|
var REMOTE_IMG_TAG_RE = /<img\b[^>]*?(?<![\w-])src\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
89040
89243
|
async function downloadAndRewriteUrls(urlSet, html, remoteDir, warnLabel, logLabel, extraRewrite) {
|
|
89041
89244
|
if (urlSet.size === 0) return { html, remoteMediaAssets: /* @__PURE__ */ new Map() };
|
|
@@ -89076,15 +89279,17 @@ async function downloadAndRewriteUrls(urlSet, html, remoteDir, warnLabel, logLab
|
|
|
89076
89279
|
}
|
|
89077
89280
|
async function localizeRemoteMediaSources(html, downloadDir) {
|
|
89078
89281
|
const urlSet = /* @__PURE__ */ new Set();
|
|
89079
|
-
const
|
|
89080
|
-
|
|
89081
|
-
|
|
89082
|
-
|
|
89282
|
+
for (const tagRe of [REMOTE_MEDIA_TAG_RE, REMOTE_SOURCE_TAG_RE]) {
|
|
89283
|
+
const re = new RegExp(tagRe.source, tagRe.flags);
|
|
89284
|
+
let m;
|
|
89285
|
+
while ((m = re.exec(html)) !== null) {
|
|
89286
|
+
if (m[1]) urlSet.add(m[1]);
|
|
89287
|
+
}
|
|
89083
89288
|
}
|
|
89084
89289
|
return downloadAndRewriteUrls(
|
|
89085
89290
|
urlSet,
|
|
89086
89291
|
html,
|
|
89087
|
-
|
|
89292
|
+
join27(downloadDir, REMOTE_MEDIA_SUBDIR),
|
|
89088
89293
|
"Remote media download failed",
|
|
89089
89294
|
"Localized remote media source(s)"
|
|
89090
89295
|
);
|
|
@@ -89099,7 +89304,7 @@ async function localizeRemoteImageSources(html, downloadDir) {
|
|
|
89099
89304
|
return downloadAndRewriteUrls(
|
|
89100
89305
|
urlSet,
|
|
89101
89306
|
html,
|
|
89102
|
-
|
|
89307
|
+
join27(downloadDir, REMOTE_MEDIA_SUBDIR),
|
|
89103
89308
|
"Remote image download failed",
|
|
89104
89309
|
"Localized remote image source(s)"
|
|
89105
89310
|
);
|
|
@@ -89115,7 +89320,7 @@ async function localizeRemoteBackgroundImages(html, downloadDir) {
|
|
|
89115
89320
|
return downloadAndRewriteUrls(
|
|
89116
89321
|
urlSet,
|
|
89117
89322
|
html,
|
|
89118
|
-
|
|
89323
|
+
join27(downloadDir, REMOTE_MEDIA_SUBDIR),
|
|
89119
89324
|
"Remote background-image download failed",
|
|
89120
89325
|
"Localized remote background-image(s)",
|
|
89121
89326
|
// Quoted url('..')/url("..") are rewritten by downloadAndRewriteUrls' default
|
|
@@ -89250,7 +89455,7 @@ async function localizeRemoteFontFaces(html, downloadDir) {
|
|
|
89250
89455
|
return downloadAndRewriteUrls(
|
|
89251
89456
|
urlSet,
|
|
89252
89457
|
processed,
|
|
89253
|
-
|
|
89458
|
+
join27(downloadDir, REMOTE_MEDIA_SUBDIR),
|
|
89254
89459
|
"Remote font download failed",
|
|
89255
89460
|
"Localized remote font face(s)",
|
|
89256
89461
|
(h, url, relPath) => h.replaceAll(`url(${url})`, `url("${relPath}")`)
|
|
@@ -89499,7 +89704,7 @@ async function discoverMediaFromBrowser(page) {
|
|
|
89499
89704
|
const htmlEl = el;
|
|
89500
89705
|
const isImage = htmlEl.tagName.toLowerCase() === "img";
|
|
89501
89706
|
const tagName19 = isImage ? "image" : htmlEl.tagName.toLowerCase() === "video" ? "video" : "audio";
|
|
89502
|
-
const id = htmlEl.id || (isImage ? autoImageIds.get(htmlEl) : void 0);
|
|
89707
|
+
const id = htmlEl.getAttribute("data-hf-render-id") || htmlEl.id || (isImage ? autoImageIds.get(htmlEl) : void 0);
|
|
89503
89708
|
if (!id) return;
|
|
89504
89709
|
const src = htmlEl.currentSrc || htmlEl.src || htmlEl.getAttribute("src") || "";
|
|
89505
89710
|
const start = parseFloat(htmlEl.getAttribute("data-start") || "0");
|
|
@@ -89546,7 +89751,7 @@ async function discoverAudioVolumeAutomationFromTimeline(page, audioIds, composi
|
|
|
89546
89751
|
const sampleStep = 1 / Math.min(60, Math.max(1, sampleFps));
|
|
89547
89752
|
const rawWindows = await page.evaluate((ids) => {
|
|
89548
89753
|
return ids.flatMap((id) => {
|
|
89549
|
-
const el = document.getElementById(id) ?? document.getElementById(id.replace(/-audio$/, ""));
|
|
89754
|
+
const el = window.__hfMediaEl?.(id) ?? document.getElementById(id) ?? document.getElementById(id.replace(/-audio$/, ""));
|
|
89550
89755
|
if (!(el instanceof HTMLAudioElement) && !(el instanceof HTMLVideoElement)) return [];
|
|
89551
89756
|
return [
|
|
89552
89757
|
{
|
|
@@ -89605,7 +89810,7 @@ async function discoverAudioVolumeAutomationFromTimeline(page, audioIds, composi
|
|
|
89605
89810
|
}
|
|
89606
89811
|
};
|
|
89607
89812
|
for (const { id, start, end } of clips2) {
|
|
89608
|
-
const el = document.getElementById(id) ?? document.getElementById(id.replace(/-audio$/, ""));
|
|
89813
|
+
const el = window.__hfMediaEl?.(id) ?? document.getElementById(id) ?? document.getElementById(id.replace(/-audio$/, ""));
|
|
89609
89814
|
if (!(el instanceof HTMLAudioElement) && !(el instanceof HTMLVideoElement)) continue;
|
|
89610
89815
|
const sampleStart = Math.max(0, start);
|
|
89611
89816
|
const sampleEnd = Math.min(duration, end);
|
|
@@ -89681,7 +89886,7 @@ async function discoverVideoVisibilityFromTimeline(page, compositionDuration) {
|
|
|
89681
89886
|
const BINARY_PRECISION = 1 / 60;
|
|
89682
89887
|
const entries2 = [];
|
|
89683
89888
|
for (const videoEl of videos) {
|
|
89684
|
-
const id = videoEl.id;
|
|
89889
|
+
const id = videoEl.getAttribute?.("data-hf-render-id") || videoEl.id;
|
|
89685
89890
|
if (!id) continue;
|
|
89686
89891
|
entries2.push({
|
|
89687
89892
|
id,
|
|
@@ -89828,13 +90033,13 @@ async function runCompileStage(input) {
|
|
|
89828
90033
|
abortSignal
|
|
89829
90034
|
} = input;
|
|
89830
90035
|
const compileStart = Date.now();
|
|
89831
|
-
const compiled = await compileForRender(projectDir, htmlPath,
|
|
90036
|
+
const compiled = await compileForRender(projectDir, htmlPath, join28(workDir, "downloads"), {
|
|
89832
90037
|
log,
|
|
89833
90038
|
failClosedFontFetch: failClosedFontFetch === true,
|
|
89834
90039
|
allowSystemFontCapture,
|
|
89835
90040
|
abortSignal,
|
|
89836
90041
|
variables: input.variables,
|
|
89837
|
-
animatedGifCacheDir: cfg.extractCacheDir ?
|
|
90042
|
+
animatedGifCacheDir: cfg.extractCacheDir ? join28(cfg.extractCacheDir, "animated-gif") : void 0,
|
|
89838
90043
|
ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
|
|
89839
90044
|
});
|
|
89840
90045
|
assertNotAborted();
|
|
@@ -89896,7 +90101,7 @@ async function runCompileStage(input) {
|
|
|
89896
90101
|
};
|
|
89897
90102
|
await preflightCompositionAssetMediaTypes({
|
|
89898
90103
|
projectDir,
|
|
89899
|
-
compiledDir:
|
|
90104
|
+
compiledDir: join28(workDir, "compiled"),
|
|
89900
90105
|
composition,
|
|
89901
90106
|
signal: abortSignal
|
|
89902
90107
|
});
|
|
@@ -89944,7 +90149,7 @@ async function runCompileStage(input) {
|
|
|
89944
90149
|
init_esm10();
|
|
89945
90150
|
init_src();
|
|
89946
90151
|
init_dist2();
|
|
89947
|
-
import { join as
|
|
90152
|
+
import { join as join29 } from "path";
|
|
89948
90153
|
|
|
89949
90154
|
// ../producer/src/services/render/stages/probeFailures.ts
|
|
89950
90155
|
var NETWORK_FAILURE_PATTERN = /404|ERR_NAME_NOT_RESOLVED|ERR_CONNECTION_REFUSED|net::ERR_/i;
|
|
@@ -90045,7 +90250,7 @@ async function runProbeStage(input) {
|
|
|
90045
90250
|
});
|
|
90046
90251
|
fileServer = await createFileServer2({
|
|
90047
90252
|
projectDir,
|
|
90048
|
-
compiledDir:
|
|
90253
|
+
compiledDir: join29(workDir, "compiled"),
|
|
90049
90254
|
port: 0,
|
|
90050
90255
|
preHeadScripts: [VIRTUAL_TIME_SHIM],
|
|
90051
90256
|
fps: job.config.fps
|
|
@@ -90067,7 +90272,7 @@ async function runProbeStage(input) {
|
|
|
90067
90272
|
log.info("Creating capture session...", { attempt, maxAttempts: PROBE_MAX_ATTEMPTS });
|
|
90068
90273
|
probeSession = await createCaptureSession(
|
|
90069
90274
|
fileServer.url,
|
|
90070
|
-
|
|
90275
|
+
join29(workDir, "probe"),
|
|
90071
90276
|
captureOpts,
|
|
90072
90277
|
null,
|
|
90073
90278
|
probeCfg
|
|
@@ -90152,7 +90357,7 @@ async function runProbeStage(input) {
|
|
|
90152
90357
|
});
|
|
90153
90358
|
probeSession = await createCaptureSession(
|
|
90154
90359
|
fileServer.url,
|
|
90155
|
-
|
|
90360
|
+
join29(workDir, "probe-screenshot"),
|
|
90156
90361
|
captureOpts,
|
|
90157
90362
|
null,
|
|
90158
90363
|
{ ...probeCfg, forceScreenshot: true }
|
|
@@ -90188,7 +90393,7 @@ async function runProbeStage(input) {
|
|
|
90188
90393
|
compiled,
|
|
90189
90394
|
resolutions,
|
|
90190
90395
|
projectDir,
|
|
90191
|
-
|
|
90396
|
+
join29(workDir, "downloads")
|
|
90192
90397
|
);
|
|
90193
90398
|
assertNotAborted();
|
|
90194
90399
|
composition.videos = compiled.videos;
|
|
@@ -90359,7 +90564,7 @@ async function runProbeStage(input) {
|
|
|
90359
90564
|
try {
|
|
90360
90565
|
await preflightCompositionAssetMediaTypes({
|
|
90361
90566
|
projectDir,
|
|
90362
|
-
compiledDir:
|
|
90567
|
+
compiledDir: join29(workDir, "compiled"),
|
|
90363
90568
|
composition,
|
|
90364
90569
|
signal: abortSignal
|
|
90365
90570
|
});
|
|
@@ -90487,13 +90692,13 @@ function validateRenderDuration(input) {
|
|
|
90487
90692
|
// ../producer/src/services/render/stages/extractVideosStage.ts
|
|
90488
90693
|
init_src();
|
|
90489
90694
|
import { existsSync as existsSync26 } from "fs";
|
|
90490
|
-
import { join as
|
|
90695
|
+
import { join as join30 } from "path";
|
|
90491
90696
|
function shouldCopyExtractedFrames(platform3) {
|
|
90492
90697
|
return platform3 === "win32";
|
|
90493
90698
|
}
|
|
90494
90699
|
function resolveVideoExtractionPolicy(env = process.env) {
|
|
90495
90700
|
const rawMode = env.HF_VIDEO_EXTRACTION_FAILURE_MODE?.trim().toLowerCase();
|
|
90496
|
-
const failureMode = rawMode === "observe" || rawMode === "
|
|
90701
|
+
const failureMode = rawMode === "observe" || rawMode === "off" ? rawMode : "enforce";
|
|
90497
90702
|
const maxTransientRetries = failureMode !== "off" && env.HF_VIDEO_EXTRACTION_MAX_RETRIES?.trim() === "1" ? 1 : 0;
|
|
90498
90703
|
return { failureMode, maxTransientRetries };
|
|
90499
90704
|
}
|
|
@@ -90668,7 +90873,7 @@ async function runExtractVideosStage(input) {
|
|
|
90668
90873
|
// because short boundary counts can differ by one frame.
|
|
90669
90874
|
{
|
|
90670
90875
|
fps: job.config.fps,
|
|
90671
|
-
outputDir:
|
|
90876
|
+
outputDir: join30(compiledDir, "__hyperframes_video_frames"),
|
|
90672
90877
|
format: job.config.videoFrameFormat ?? "auto",
|
|
90673
90878
|
timelineEnd: composition.duration,
|
|
90674
90879
|
maxTransientRetries: extractionPolicy.maxTransientRetries,
|
|
@@ -90732,7 +90937,7 @@ function appendAutoDetectedVideoAudio(composition, extracted) {
|
|
|
90732
90937
|
|
|
90733
90938
|
// ../producer/src/services/render/stages/audioStage.ts
|
|
90734
90939
|
init_src();
|
|
90735
|
-
import { join as
|
|
90940
|
+
import { join as join31 } from "path";
|
|
90736
90941
|
async function runAudioStage(input) {
|
|
90737
90942
|
const {
|
|
90738
90943
|
projectDir,
|
|
@@ -90747,7 +90952,7 @@ async function runAudioStage(input) {
|
|
|
90747
90952
|
log
|
|
90748
90953
|
} = input;
|
|
90749
90954
|
const stage3Start = Date.now();
|
|
90750
|
-
const audioOutputPath =
|
|
90955
|
+
const audioOutputPath = join31(workDir, MIXED_AUDIO_FILENAME);
|
|
90751
90956
|
let hasAudio = false;
|
|
90752
90957
|
let audioError;
|
|
90753
90958
|
let audioFailures;
|
|
@@ -90757,7 +90962,7 @@ async function runAudioStage(input) {
|
|
|
90757
90962
|
audioResult = await processCompositionAudio(
|
|
90758
90963
|
audios,
|
|
90759
90964
|
projectDir,
|
|
90760
|
-
|
|
90965
|
+
join31(workDir, "audio-work"),
|
|
90761
90966
|
audioOutputPath,
|
|
90762
90967
|
duration,
|
|
90763
90968
|
abortSignal,
|
|
@@ -90991,7 +91196,7 @@ async function runCaptureStage(input) {
|
|
|
90991
91196
|
init_src();
|
|
90992
91197
|
import { mkdtemp as mkdtemp2, writeFile as writeFile2 } from "fs/promises";
|
|
90993
91198
|
import { tmpdir as tmpdir6 } from "os";
|
|
90994
|
-
import { join as
|
|
91199
|
+
import { join as join34 } from "path";
|
|
90995
91200
|
|
|
90996
91201
|
// ../producer/src/services/render/stages/captureHdrFrameShared.ts
|
|
90997
91202
|
init_src();
|
|
@@ -90999,7 +91204,7 @@ init_src();
|
|
|
90999
91204
|
// ../producer/src/services/hdrCompositor.ts
|
|
91000
91205
|
init_src();
|
|
91001
91206
|
import { readSync as readSync2, closeSync as closeSync4 } from "fs";
|
|
91002
|
-
import { join as
|
|
91207
|
+
import { join as join32 } from "path";
|
|
91003
91208
|
function countNonZeroAlpha(rgba) {
|
|
91004
91209
|
let n = 0;
|
|
91005
91210
|
for (let p = 3; p < rgba.length; p += 4) {
|
|
@@ -91405,7 +91610,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
|
|
|
91405
91610
|
if (shouldLog && debugDumpDir) {
|
|
91406
91611
|
const after2 = countNonZeroRgb48(canvas);
|
|
91407
91612
|
const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
|
|
91408
|
-
const dumpPath =
|
|
91613
|
+
const dumpPath = join32(debugDumpDir, dumpName);
|
|
91409
91614
|
writeFileExclusiveSync(dumpPath, domPng);
|
|
91410
91615
|
log.info("[diag] dom layer blit", {
|
|
91411
91616
|
frame: debugFrameIndex,
|
|
@@ -91453,7 +91658,7 @@ import {
|
|
|
91453
91658
|
rmSync as rmSync10,
|
|
91454
91659
|
statfsSync
|
|
91455
91660
|
} from "fs";
|
|
91456
|
-
import { join as
|
|
91661
|
+
import { join as join33 } from "path";
|
|
91457
91662
|
var NO_FOLLOW_FLAG = constants2.O_NOFOLLOW ?? 0;
|
|
91458
91663
|
function tempDirSafePrefix(id) {
|
|
91459
91664
|
const safe = id.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
|
|
@@ -91697,10 +91902,10 @@ async function extractHdrVideoFrames(args) {
|
|
|
91697
91902
|
const window3 = extractionWindows.get(videoId);
|
|
91698
91903
|
if (!video || !window3) continue;
|
|
91699
91904
|
mkdirSync14(framesDir, { recursive: true });
|
|
91700
|
-
const frameDir = mkdtempSync6(
|
|
91905
|
+
const frameDir = mkdtempSync6(join33(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
|
|
91701
91906
|
createdFrameDirs.add(frameDir);
|
|
91702
91907
|
const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
|
|
91703
|
-
const rawPath =
|
|
91908
|
+
const rawPath = join33(frameDir, "frames.rgb48le");
|
|
91704
91909
|
const extractionStart = String(window3.extractionMediaStart ?? window3.mediaStart);
|
|
91705
91910
|
const ffmpegArgs = [];
|
|
91706
91911
|
if (window3.finalFrameOnly) {
|
|
@@ -92161,11 +92366,11 @@ function createDrainFrameGuard(args) {
|
|
|
92161
92366
|
return buf;
|
|
92162
92367
|
}
|
|
92163
92368
|
if (db < verifyMinDb) {
|
|
92164
|
-
const dumpDir = await mkdtemp2(
|
|
92369
|
+
const dumpDir = await mkdtemp2(join34(tmpdir6(), "hf-de-verify-fail-")).catch(() => null);
|
|
92165
92370
|
if (dumpDir) {
|
|
92166
92371
|
await Promise.all([
|
|
92167
|
-
writeFile2(
|
|
92168
|
-
writeFile2(
|
|
92372
|
+
writeFile2(join34(dumpDir, `frame-${idx}-de.jpg`), buf),
|
|
92373
|
+
writeFile2(join34(dumpDir, `frame-${idx}-truth.jpg`), truth)
|
|
92169
92374
|
]).catch(() => {
|
|
92170
92375
|
});
|
|
92171
92376
|
}
|
|
@@ -92560,7 +92765,7 @@ async function runCaptureStreamingStage(input) {
|
|
|
92560
92765
|
init_src();
|
|
92561
92766
|
init_dist2();
|
|
92562
92767
|
import { existsSync as existsSync28, mkdirSync as mkdirSync15 } from "fs";
|
|
92563
|
-
import { join as
|
|
92768
|
+
import { join as join38 } from "path";
|
|
92564
92769
|
|
|
92565
92770
|
// ../producer/src/services/hdrImageTransferCache.ts
|
|
92566
92771
|
init_src();
|
|
@@ -92624,7 +92829,7 @@ function createHdrImageTransferCache(options = {}) {
|
|
|
92624
92829
|
|
|
92625
92830
|
// ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
|
|
92626
92831
|
init_src();
|
|
92627
|
-
import { join as
|
|
92832
|
+
import { join as join35 } from "path";
|
|
92628
92833
|
async function runSequentialLayeredFrameLoop(input) {
|
|
92629
92834
|
const {
|
|
92630
92835
|
job,
|
|
@@ -92745,7 +92950,7 @@ async function runSequentialLayeredFrameLoop(input) {
|
|
|
92745
92950
|
);
|
|
92746
92951
|
if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
|
|
92747
92952
|
writeFileExclusiveSync(
|
|
92748
|
-
|
|
92953
|
+
join35(debugDumpDir, `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`),
|
|
92749
92954
|
normalCanvas
|
|
92750
92955
|
);
|
|
92751
92956
|
}
|
|
@@ -92780,12 +92985,12 @@ async function runSequentialLayeredFrameLoop(input) {
|
|
|
92780
92985
|
|
|
92781
92986
|
// ../producer/src/services/render/stages/captureHdrHybridLoop.ts
|
|
92782
92987
|
init_src();
|
|
92783
|
-
import { join as
|
|
92988
|
+
import { join as join37 } from "path";
|
|
92784
92989
|
|
|
92785
92990
|
// ../producer/src/services/shaderTransitionWorkerPool.ts
|
|
92786
92991
|
import { Worker as Worker2 } from "worker_threads";
|
|
92787
92992
|
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL2 } from "url";
|
|
92788
|
-
import { dirname as dirname14, join as
|
|
92993
|
+
import { dirname as dirname14, join as join36 } from "path";
|
|
92789
92994
|
import { createRequire as createRequire2 } from "module";
|
|
92790
92995
|
import { existsSync as existsSync27 } from "fs";
|
|
92791
92996
|
import { cpus as cpus3 } from "os";
|
|
@@ -92799,9 +93004,9 @@ function resolveWorkerEntry(explicit) {
|
|
|
92799
93004
|
return { path: override, isTs };
|
|
92800
93005
|
}
|
|
92801
93006
|
const moduleDir = dirname14(fileURLToPath4(import.meta.url));
|
|
92802
|
-
const jsPath =
|
|
93007
|
+
const jsPath = join36(moduleDir, "shaderTransitionWorker.js");
|
|
92803
93008
|
if (existsSync27(jsPath)) return { path: jsPath, isTs: false };
|
|
92804
|
-
const tsPath =
|
|
93009
|
+
const tsPath = join36(moduleDir, "shaderTransitionWorker.ts");
|
|
92805
93010
|
return { path: tsPath, isTs: true };
|
|
92806
93011
|
}
|
|
92807
93012
|
function buildExecArgv(entryIsTs) {
|
|
@@ -93171,7 +93376,7 @@ async function runHybridLayeredFrameLoop(input) {
|
|
|
93171
93376
|
);
|
|
93172
93377
|
if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
|
|
93173
93378
|
writeFileExclusiveSync(
|
|
93174
|
-
|
|
93379
|
+
join37(debugDumpDir, `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`),
|
|
93175
93380
|
canvas
|
|
93176
93381
|
);
|
|
93177
93382
|
}
|
|
@@ -93357,7 +93562,7 @@ async function runCaptureHdrStage(input) {
|
|
|
93357
93562
|
if (hdrVideoFrameSources.has(v.id)) hdrVideoEndTimes.set(v.id, v.end);
|
|
93358
93563
|
}
|
|
93359
93564
|
const debugDumpEnabled = process.env.KEEP_TEMP === "1";
|
|
93360
|
-
const debugDumpDir = debugDumpEnabled ?
|
|
93565
|
+
const debugDumpDir = debugDumpEnabled ? join38(framesDir, "debug-composite") : null;
|
|
93361
93566
|
if (debugDumpDir && !existsSync28(debugDumpDir)) {
|
|
93362
93567
|
mkdirSync15(debugDumpDir, { recursive: true });
|
|
93363
93568
|
}
|
|
@@ -93509,10 +93714,10 @@ async function runCaptureHdrStage(input) {
|
|
|
93509
93714
|
// ../producer/src/services/render/stages/encodeStage.ts
|
|
93510
93715
|
init_src();
|
|
93511
93716
|
import { copyFileSync as copyFileSync5, existsSync as existsSync29, mkdirSync as mkdirSync16, readdirSync as readdirSync10, rmSync as rmSync11, statSync as statSync9 } from "fs";
|
|
93512
|
-
import { dirname as dirname15, join as
|
|
93717
|
+
import { dirname as dirname15, join as join40 } from "path";
|
|
93513
93718
|
|
|
93514
93719
|
// ../producer/src/services/render/stages/gifEncodeArgs.ts
|
|
93515
|
-
import { join as
|
|
93720
|
+
import { join as join39 } from "path";
|
|
93516
93721
|
function fpsToFfmpegArg2(fps) {
|
|
93517
93722
|
return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
|
|
93518
93723
|
}
|
|
@@ -93524,7 +93729,7 @@ function buildGifPalettegenArgs(input) {
|
|
|
93524
93729
|
"-framerate",
|
|
93525
93730
|
fpsArg,
|
|
93526
93731
|
"-i",
|
|
93527
|
-
|
|
93732
|
+
join39(input.framesDir, input.framePattern),
|
|
93528
93733
|
"-vf",
|
|
93529
93734
|
`fps=${fpsArg},palettegen=stats_mode=diff${transparency}`,
|
|
93530
93735
|
input.palettePath
|
|
@@ -93538,7 +93743,7 @@ function buildGifPaletteuseArgs(input) {
|
|
|
93538
93743
|
"-framerate",
|
|
93539
93744
|
fpsArg,
|
|
93540
93745
|
"-i",
|
|
93541
|
-
|
|
93746
|
+
join39(input.framesDir, input.framePattern),
|
|
93542
93747
|
"-i",
|
|
93543
93748
|
input.palettePath,
|
|
93544
93749
|
"-lavfi",
|
|
@@ -93655,11 +93860,11 @@ async function runEncodeStage(input) {
|
|
|
93655
93860
|
);
|
|
93656
93861
|
}
|
|
93657
93862
|
captured.forEach((name, i) => {
|
|
93658
|
-
const dst =
|
|
93659
|
-
copyFileSync5(
|
|
93863
|
+
const dst = join40(outputPath, formatExportFrameName(i, "png"));
|
|
93864
|
+
copyFileSync5(join40(framesDir, name), dst);
|
|
93660
93865
|
});
|
|
93661
93866
|
if (hasAudio && audioOutputPath && existsSync29(audioOutputPath)) {
|
|
93662
|
-
copyFileSync5(audioOutputPath,
|
|
93867
|
+
copyFileSync5(audioOutputPath, join40(outputPath, MIXED_AUDIO_FILENAME));
|
|
93663
93868
|
log.info(
|
|
93664
93869
|
`[Render] png-sequence: ${MIXED_AUDIO_FILENAME} sidecar written to ${outputPath}/${MIXED_AUDIO_FILENAME}`
|
|
93665
93870
|
);
|
|
@@ -93678,7 +93883,7 @@ async function runEncodeStage(input) {
|
|
|
93678
93883
|
const encodeResult2 = await encodeGifFromDir(framesDir, framePattern2, outputPath, {
|
|
93679
93884
|
fps: job.config.fps,
|
|
93680
93885
|
loop,
|
|
93681
|
-
palettePath:
|
|
93886
|
+
palettePath: join40(dirname15(videoOnlyPath), "gif-palette.png"),
|
|
93682
93887
|
preserveAlpha: needsAlpha,
|
|
93683
93888
|
signal: abortSignal,
|
|
93684
93889
|
timeout: engineCfg.ffmpegEncodeTimeout
|
|
@@ -94044,8 +94249,7 @@ async function runAssembleStage(input) {
|
|
|
94044
94249
|
outputPath,
|
|
94045
94250
|
abortSignal,
|
|
94046
94251
|
{
|
|
94047
|
-
audioCodec: "aac"
|
|
94048
|
-
preserveAudioPrimingEditList: normalizeResult.operation !== "copy"
|
|
94252
|
+
audioCodec: "aac"
|
|
94049
94253
|
},
|
|
94050
94254
|
job.config.fps
|
|
94051
94255
|
);
|
|
@@ -94083,7 +94287,7 @@ function sampleDirectoryBytes(dir) {
|
|
|
94083
94287
|
continue;
|
|
94084
94288
|
}
|
|
94085
94289
|
for (const name of entries2) {
|
|
94086
|
-
const full =
|
|
94290
|
+
const full = join41(current2, name);
|
|
94087
94291
|
try {
|
|
94088
94292
|
const st = statSync10(full);
|
|
94089
94293
|
if (st.isDirectory()) {
|
|
@@ -94166,7 +94370,10 @@ function applyRenderWarningPolicy(job, captureWarnings, log = defaultLogger) {
|
|
|
94166
94370
|
const hasAudioProcessingFailure = job.warnings.some(
|
|
94167
94371
|
(warning) => warning.code === "audio_processing_failed"
|
|
94168
94372
|
);
|
|
94169
|
-
|
|
94373
|
+
const hasSubTimelineScriptFailure = job.warnings.some(
|
|
94374
|
+
(warning) => warning.code === "sub_timeline_script_failure"
|
|
94375
|
+
);
|
|
94376
|
+
if (strictness === "strict" || hasAudioProcessingFailure || hasSubTimelineScriptFailure) {
|
|
94170
94377
|
throw new RenderQualityError(job.warnings);
|
|
94171
94378
|
}
|
|
94172
94379
|
}
|
|
@@ -94228,7 +94435,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
|
|
|
94228
94435
|
const ranges = [];
|
|
94229
94436
|
let rangeStart = null;
|
|
94230
94437
|
for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
|
|
94231
|
-
const framePath =
|
|
94438
|
+
const framePath = join41(framesDir, formatCaptureFrameName(frameIndex, frameExt));
|
|
94232
94439
|
const missing = !existsSync30(framePath) || statSync10(framePath).size <= 8;
|
|
94233
94440
|
if (missing && rangeStart === null) {
|
|
94234
94441
|
rangeStart = frameIndex;
|
|
@@ -94251,7 +94458,7 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
|
|
|
94251
94458
|
workerId,
|
|
94252
94459
|
startFrame: rangeStart + range.startFrame,
|
|
94253
94460
|
endFrame: rangeStart + range.endFrame,
|
|
94254
|
-
outputDir:
|
|
94461
|
+
outputDir: join41(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
|
|
94255
94462
|
outputFrameOffset: rangeStart
|
|
94256
94463
|
}));
|
|
94257
94464
|
batches.push(batch);
|
|
@@ -94274,8 +94481,8 @@ function getNextRetryWorkerCount(currentWorkers) {
|
|
|
94274
94481
|
return Math.max(1, Math.floor(currentWorkers / 2));
|
|
94275
94482
|
}
|
|
94276
94483
|
function resolveRenderWorkDirPrefix(outputPath, jobId, platform3 = process.platform, systemTempDir = tmpdir7()) {
|
|
94277
|
-
if (platform3 === "win32") return
|
|
94278
|
-
return
|
|
94484
|
+
if (platform3 === "win32") return join41(systemTempDir, "hf-render-");
|
|
94485
|
+
return join41(dirname16(outputPath), `work-${jobId}-`);
|
|
94279
94486
|
}
|
|
94280
94487
|
var MAX_TRANSIENT_CAPTURE_RETRIES = 1;
|
|
94281
94488
|
function captureAttemptMadeProgress(attemptTargetFrameCount, remainingFrameCount) {
|
|
@@ -94304,7 +94511,7 @@ The composition is too large for the available memory. To reduce memory pressure
|
|
|
94304
94511
|
function countCapturedFrames(totalFrames, framesDir, frameExt) {
|
|
94305
94512
|
let captured = 0;
|
|
94306
94513
|
for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
|
|
94307
|
-
const framePath =
|
|
94514
|
+
const framePath = join41(framesDir, formatCaptureFrameName(frameIndex, frameExt));
|
|
94308
94515
|
if (existsSync30(framePath)) captured++;
|
|
94309
94516
|
}
|
|
94310
94517
|
return captured;
|
|
@@ -94329,7 +94536,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
|
|
|
94329
94536
|
reason: attempt === 0 ? "initial" : pendingTransientRetry ? "transient-retry" : "retry"
|
|
94330
94537
|
});
|
|
94331
94538
|
pendingTransientRetry = false;
|
|
94332
|
-
const attemptWorkDir =
|
|
94539
|
+
const attemptWorkDir = join41(options.workDir, `capture-attempt-${attempt}`);
|
|
94333
94540
|
const batches = missingRanges ? buildMissingFrameRetryBatches(
|
|
94334
94541
|
missingRanges,
|
|
94335
94542
|
currentWorkers,
|
|
@@ -94668,13 +94875,13 @@ function deVerifyFallbackTelemetry(err) {
|
|
|
94668
94875
|
async function executeRenderJob(job, projectDir, outputPath, progressSink, abortSignal) {
|
|
94669
94876
|
const moduleDir = dirname16(fileURLToPath5(import.meta.url));
|
|
94670
94877
|
const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve13(process.env.PRODUCER_RENDERS_DIR, "..") : resolve13(moduleDir, "../..");
|
|
94671
|
-
const debugDir =
|
|
94878
|
+
const debugDir = join41(producerRoot, ".debug");
|
|
94672
94879
|
const outputDir = dirname16(outputPath);
|
|
94673
94880
|
if (!existsSync30(outputDir)) mkdirSync17(outputDir, { recursive: true });
|
|
94674
|
-
const workDir = job.config.debug ?
|
|
94881
|
+
const workDir = job.config.debug ? join41(debugDir, job.id) : mkdtempSync7(resolveRenderWorkDirPrefix(outputPath, job.id));
|
|
94675
94882
|
const pipelineStart = Date.now();
|
|
94676
94883
|
const baseLog = job.config.logger ?? defaultLogger;
|
|
94677
|
-
const logPath = job.config.debug ?
|
|
94884
|
+
const logPath = job.config.debug ? join41(workDir, "render.log") : null;
|
|
94678
94885
|
const execution = new RenderExecutionContext({
|
|
94679
94886
|
request: { renderJobId: job.id, projectDir, outputPath },
|
|
94680
94887
|
logger: logPath ? createRenderFileLogger(logPath, baseLog) : baseLog,
|
|
@@ -94722,7 +94929,7 @@ async function executeRenderPipeline(input) {
|
|
|
94722
94929
|
imageDecodeFailures: 0
|
|
94723
94930
|
};
|
|
94724
94931
|
let hdrPerf;
|
|
94725
|
-
const perfOutputPath =
|
|
94932
|
+
const perfOutputPath = join41(workDir, "perf-summary.json");
|
|
94726
94933
|
const cfg = { ...job.config.producerConfig ?? resolveConfig() };
|
|
94727
94934
|
const observability = new RenderObservabilityRecorder({
|
|
94728
94935
|
pipelineStartMs: pipelineStart,
|
|
@@ -94814,15 +95021,15 @@ async function executeRenderPipeline(input) {
|
|
|
94814
95021
|
requestedWorkers: job.config.workers ?? "auto"
|
|
94815
95022
|
});
|
|
94816
95023
|
const entryFile = job.config.entryFile || "index.html";
|
|
94817
|
-
let htmlPath =
|
|
95024
|
+
let htmlPath = join41(projectDir, entryFile);
|
|
94818
95025
|
if (!existsSync30(htmlPath)) {
|
|
94819
95026
|
throw new Error(`Entry file not found: ${htmlPath}`);
|
|
94820
95027
|
}
|
|
94821
95028
|
assertNotAborted();
|
|
94822
95029
|
const rawEntry = readFileSync12(htmlPath, "utf-8");
|
|
94823
95030
|
if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
|
|
94824
|
-
const wrapperPath =
|
|
94825
|
-
const projectIndexPath =
|
|
95031
|
+
const wrapperPath = join41(workDir, "standalone-entry.html");
|
|
95032
|
+
const projectIndexPath = join41(projectDir, "index.html");
|
|
94826
95033
|
if (!existsSync30(projectIndexPath)) {
|
|
94827
95034
|
throw new Error(
|
|
94828
95035
|
`Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
|
|
@@ -94977,7 +95184,7 @@ async function executeRenderPipeline(input) {
|
|
|
94977
95184
|
beginFrameStalled: probeResult.beginFrameStalled
|
|
94978
95185
|
});
|
|
94979
95186
|
updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
|
|
94980
|
-
const compiledDir =
|
|
95187
|
+
const compiledDir = join41(workDir, "compiled");
|
|
94981
95188
|
const extractResult = await observeRenderStage(
|
|
94982
95189
|
observability,
|
|
94983
95190
|
"video_extract",
|
|
@@ -95097,7 +95304,7 @@ async function executeRenderPipeline(input) {
|
|
|
95097
95304
|
try {
|
|
95098
95305
|
fileServer = await createFileServer2({
|
|
95099
95306
|
projectDir,
|
|
95100
|
-
compiledDir:
|
|
95307
|
+
compiledDir: join41(workDir, "compiled"),
|
|
95101
95308
|
port: 0,
|
|
95102
95309
|
preHeadScripts: [VIRTUAL_TIME_SHIM],
|
|
95103
95310
|
fps: job.config.fps
|
|
@@ -95115,7 +95322,7 @@ async function executeRenderPipeline(input) {
|
|
|
95115
95322
|
if (!activeFileServer) {
|
|
95116
95323
|
throw new Error("File server failed to initialize before frame capture");
|
|
95117
95324
|
}
|
|
95118
|
-
const framesDir =
|
|
95325
|
+
const framesDir = join41(workDir, "captured-frames");
|
|
95119
95326
|
if (!existsSync30(framesDir)) mkdirSync17(framesDir, { recursive: true });
|
|
95120
95327
|
const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
|
|
95121
95328
|
chromePath: resolveHeadlessShellPath(cfg),
|
|
@@ -95440,7 +95647,7 @@ async function executeRenderPipeline(input) {
|
|
|
95440
95647
|
gif: ".gif"
|
|
95441
95648
|
};
|
|
95442
95649
|
const videoExt = FORMAT_EXT[outputFormat] ?? ".mp4";
|
|
95443
|
-
const videoOnlyPath =
|
|
95650
|
+
const videoOnlyPath = join41(workDir, `video-only${videoExt}`);
|
|
95444
95651
|
const usePageSideCompositingForTransitions = (cfg.enablePageSideCompositing || isGif) && compiled.hasShaderTransitions && !hasHdrContent && outputSupportsPageSideShaderCompositing(outputFormat);
|
|
95445
95652
|
if (usePageSideCompositingForTransitions) {
|
|
95446
95653
|
activeFileServer.addPreHeadScript(HF_PAGE_SIDE_COMPOSITING_STUB);
|
|
@@ -95958,7 +96165,13 @@ async function executeRenderPipeline(input) {
|
|
|
95958
96165
|
} else {
|
|
95959
96166
|
observability.checkpoint("assemble", `skipped for ${outputFormat}`);
|
|
95960
96167
|
}
|
|
95961
|
-
artifactTransaction.validate(
|
|
96168
|
+
await artifactTransaction.validate(
|
|
96169
|
+
!isPngSequence && !isGif && Number.isFinite(job.duration) && job.duration > 0 ? {
|
|
96170
|
+
expectedDurationSeconds: job.duration,
|
|
96171
|
+
fps: fpsToNumber(job.config.fps),
|
|
96172
|
+
expectedFrames: captureTotalFrames
|
|
96173
|
+
} : void 0
|
|
96174
|
+
);
|
|
95962
96175
|
const totalElapsed = Date.now() - pipelineStart;
|
|
95963
96176
|
const tmpPeakBytes = existsSync30(workDir) ? sampleDirectoryBytes(workDir) : 0;
|
|
95964
96177
|
recordTransientRetryObservability();
|
|
@@ -96026,11 +96239,11 @@ async function executeRenderPipeline(input) {
|
|
|
96026
96239
|
}
|
|
96027
96240
|
if (job.config.debug) {
|
|
96028
96241
|
if (!isPngSequence && existsSync30(stagedOutputPath)) {
|
|
96029
|
-
const debugOutput =
|
|
96242
|
+
const debugOutput = join41(workDir, `output${videoExt}`);
|
|
96030
96243
|
copyFileSync6(stagedOutputPath, debugOutput);
|
|
96031
96244
|
}
|
|
96032
96245
|
}
|
|
96033
|
-
artifactTransaction.commit();
|
|
96246
|
+
await artifactTransaction.commit();
|
|
96034
96247
|
job.outputPath = outputPath;
|
|
96035
96248
|
updateJobStatus(job, "complete", "Render complete", 100, onProgress);
|
|
96036
96249
|
await eventPublisher.flush();
|
|
@@ -96363,7 +96576,7 @@ import {
|
|
|
96363
96576
|
rmSync as rmSync14,
|
|
96364
96577
|
createReadStream as createReadStream5
|
|
96365
96578
|
} from "fs";
|
|
96366
|
-
import { resolve as resolve15, dirname as dirname18, join as
|
|
96579
|
+
import { resolve as resolve15, dirname as dirname18, join as join44 } from "path";
|
|
96367
96580
|
import { tmpdir as tmpdir8 } from "os";
|
|
96368
96581
|
import { parseArgs } from "util";
|
|
96369
96582
|
import crypto from "crypto";
|
|
@@ -96374,7 +96587,7 @@ import { serve as serve3 } from "@hono/node-server";
|
|
|
96374
96587
|
// ../producer/src/services/hyperframeLint.ts
|
|
96375
96588
|
init_dist3();
|
|
96376
96589
|
import { existsSync as existsSync31, readFileSync as readFileSync13, statSync as statSync11 } from "fs";
|
|
96377
|
-
import { resolve as resolve14, join as
|
|
96590
|
+
import { resolve as resolve14, join as join42 } from "path";
|
|
96378
96591
|
function isStringRecord(value) {
|
|
96379
96592
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
96380
96593
|
return false;
|
|
@@ -96422,7 +96635,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
|
|
|
96422
96635
|
}
|
|
96423
96636
|
}
|
|
96424
96637
|
return {
|
|
96425
|
-
error: `No HTML entry file found in project directory: ${
|
|
96638
|
+
error: `No HTML entry file found in project directory: ${join42(absProjectDir, preferredEntryFile || "index.html")}`
|
|
96426
96639
|
};
|
|
96427
96640
|
}
|
|
96428
96641
|
function prepareHyperframeLintBody(body) {
|
|
@@ -96465,7 +96678,7 @@ async function runHyperframeLint(prepared) {
|
|
|
96465
96678
|
// ../producer/src/services/healthWorker.ts
|
|
96466
96679
|
import { Worker as Worker3 } from "worker_threads";
|
|
96467
96680
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
96468
|
-
import { dirname as dirname17, join as
|
|
96681
|
+
import { dirname as dirname17, join as join43 } from "path";
|
|
96469
96682
|
import { existsSync as existsSync32 } from "fs";
|
|
96470
96683
|
var DEFAULT_HEALTH_PORT = 9848;
|
|
96471
96684
|
async function startHealthWorker(options = {}) {
|
|
@@ -96541,7 +96754,7 @@ function defaultLogger2() {
|
|
|
96541
96754
|
}
|
|
96542
96755
|
function resolveWorkerEntry2() {
|
|
96543
96756
|
const here = dirname17(fileURLToPath6(import.meta.url));
|
|
96544
|
-
const candidates = [
|
|
96757
|
+
const candidates = [join43(here, "healthWorkerThread.js"), join43(here, "healthWorkerThread.ts")];
|
|
96545
96758
|
for (const candidate of candidates) {
|
|
96546
96759
|
if (existsSync32(candidate)) return candidate;
|
|
96547
96760
|
}
|
|
@@ -96743,8 +96956,8 @@ async function resolveInlineRenderHtml(body) {
|
|
|
96743
96956
|
}
|
|
96744
96957
|
function materializeInlineProject(html, options) {
|
|
96745
96958
|
const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir8();
|
|
96746
|
-
const tempProjectDir = mkdtempSync8(
|
|
96747
|
-
writeFileSync11(
|
|
96959
|
+
const tempProjectDir = mkdtempSync8(join44(tempRoot, "producer-project-"));
|
|
96960
|
+
writeFileSync11(join44(tempProjectDir, "index.html"), html, "utf-8");
|
|
96748
96961
|
return {
|
|
96749
96962
|
prepared: {
|
|
96750
96963
|
input: { projectDir: tempProjectDir, ...options },
|
|
@@ -97193,11 +97406,11 @@ init_src();
|
|
|
97193
97406
|
init_dist2();
|
|
97194
97407
|
init_src();
|
|
97195
97408
|
import { cpSync as cpSync2, existsSync as existsSync36, mkdirSync as mkdirSync20, renameSync as renameSync6, rmSync as rmSync15, writeFileSync as writeFileSync13 } from "fs";
|
|
97196
|
-
import { join as
|
|
97409
|
+
import { join as join48, relative as relative4, sep as sep4 } from "path";
|
|
97197
97410
|
|
|
97198
97411
|
// ../producer/src/services/render/stages/freezePlan.ts
|
|
97199
97412
|
import { existsSync as existsSync34, mkdirSync as mkdirSync19, readFileSync as readFileSync14, readdirSync as readdirSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
97200
|
-
import { join as
|
|
97413
|
+
import { join as join45, relative as relative2, resolve as resolve16 } from "path";
|
|
97201
97414
|
|
|
97202
97415
|
// ../producer/src/services/distributed/planProtocol.ts
|
|
97203
97416
|
var PLAN_SCHEMA_VERSION = 1;
|
|
@@ -97239,7 +97452,7 @@ var FIELD_DELIMITER = Buffer.from([0]);
|
|
|
97239
97452
|
// ../producer/src/services/distributed/shared.ts
|
|
97240
97453
|
init_src();
|
|
97241
97454
|
import { execFile as execFileCallback } from "child_process";
|
|
97242
|
-
import { dirname as dirname19, join as
|
|
97455
|
+
import { dirname as dirname19, join as join46 } from "path";
|
|
97243
97456
|
import { existsSync as existsSync35, readFileSync as readFileSync15 } from "fs";
|
|
97244
97457
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
97245
97458
|
import { promisify as promisify3 } from "util";
|
|
@@ -97249,7 +97462,7 @@ var execFile3 = promisify3(execFileCallback);
|
|
|
97249
97462
|
// ../producer/src/services/distributed/planSize.ts
|
|
97250
97463
|
import { createHash as createHash10 } from "crypto";
|
|
97251
97464
|
import { lstatSync as lstatSync4, readdirSync as readdirSync13 } from "fs";
|
|
97252
|
-
import { extname as extname7, join as
|
|
97465
|
+
import { extname as extname7, join as join47, relative as relative3 } from "path";
|
|
97253
97466
|
var PLAN_ROOT_CATEGORY = {
|
|
97254
97467
|
compiled: "compiled",
|
|
97255
97468
|
[PLAN_AUDIO_RELATIVE_PATH]: "audio",
|
|
@@ -97261,9 +97474,9 @@ var PLAN_ROOT_CATEGORY = {
|
|
|
97261
97474
|
var PLAN_DIR_SIZE_LIMIT_BYTES = 2 * 1024 * 1024 * 1024;
|
|
97262
97475
|
var FREEZE_OWNED_PLAN_FILES = [
|
|
97263
97476
|
"plan.json",
|
|
97264
|
-
|
|
97265
|
-
|
|
97266
|
-
|
|
97477
|
+
join48("meta", "composition.json"),
|
|
97478
|
+
join48("meta", "encoder.json"),
|
|
97479
|
+
join48("meta", "chunks.json")
|
|
97267
97480
|
];
|
|
97268
97481
|
|
|
97269
97482
|
// ../producer/src/services/distributed/planV2.ts
|
|
@@ -97286,7 +97499,7 @@ import {
|
|
|
97286
97499
|
} from "fs";
|
|
97287
97500
|
import { createHash as createHash11 } from "crypto";
|
|
97288
97501
|
import { tmpdir as tmpdir9 } from "os";
|
|
97289
|
-
import { dirname as dirname21, isAbsolute as isAbsolute4, join as
|
|
97502
|
+
import { dirname as dirname21, isAbsolute as isAbsolute4, join as join51, relative as relative5, resolve as resolve17, sep as sep5 } from "path";
|
|
97290
97503
|
|
|
97291
97504
|
// ../producer/src/services/distributed/planV2Publisher.ts
|
|
97292
97505
|
import {
|
|
@@ -97300,15 +97513,15 @@ import {
|
|
|
97300
97513
|
statSync as statSync13,
|
|
97301
97514
|
writeFileSync as writeFileSync14
|
|
97302
97515
|
} from "fs";
|
|
97303
|
-
import { dirname as dirname20, join as
|
|
97516
|
+
import { dirname as dirname20, join as join50 } from "path";
|
|
97304
97517
|
|
|
97305
97518
|
// ../producer/src/services/distributed/planV2Layout.ts
|
|
97306
|
-
import { join as
|
|
97519
|
+
import { join as join49 } from "path";
|
|
97307
97520
|
|
|
97308
97521
|
// ../producer/src/services/distributed/planV2Execution.ts
|
|
97309
97522
|
import { mkdtempSync as mkdtempSync11, rmSync as rmSync20 } from "fs";
|
|
97310
97523
|
import { tmpdir as tmpdir10 } from "os";
|
|
97311
|
-
import { join as
|
|
97524
|
+
import { join as join54 } from "path";
|
|
97312
97525
|
|
|
97313
97526
|
// ../producer/src/services/distributed/assemble.ts
|
|
97314
97527
|
init_src();
|
|
@@ -97323,19 +97536,19 @@ import {
|
|
|
97323
97536
|
statSync as statSync15,
|
|
97324
97537
|
writeFileSync as writeFileSync16
|
|
97325
97538
|
} from "fs";
|
|
97326
|
-
import { dirname as dirname22, join as
|
|
97539
|
+
import { dirname as dirname22, join as join52 } from "path";
|
|
97327
97540
|
|
|
97328
97541
|
// ../producer/src/services/distributed/renderChunk.ts
|
|
97329
97542
|
init_src();
|
|
97330
97543
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
97331
97544
|
import { existsSync as existsSync40, mkdirSync as mkdirSync24, readFileSync as readFileSync18, readdirSync as readdirSync16, rmSync as rmSync19, writeFileSync as writeFileSync17 } from "fs";
|
|
97332
|
-
import { extname as extname8, join as
|
|
97545
|
+
import { extname as extname8, join as join53 } from "path";
|
|
97333
97546
|
init_src();
|
|
97334
97547
|
|
|
97335
97548
|
// ../producer/src/services/distributed/projectHash.ts
|
|
97336
97549
|
import { readdirSync as readdirSync17, readFileSync as readFileSync19 } from "fs";
|
|
97337
97550
|
import { createHash as createHash12 } from "crypto";
|
|
97338
|
-
import { join as
|
|
97551
|
+
import { join as join55, relative as relative6 } from "path";
|
|
97339
97552
|
|
|
97340
97553
|
// src/fontLocalize.ts
|
|
97341
97554
|
function safeVersion(version2) {
|
|
@@ -97376,8 +97589,8 @@ async function runFontLocalize(io, localize) {
|
|
|
97376
97589
|
}
|
|
97377
97590
|
|
|
97378
97591
|
// src/version.ts
|
|
97379
|
-
var VERSION = true ? "0.8.
|
|
97380
|
-
var PRODUCER_VERSION = true ? "0.8.
|
|
97592
|
+
var VERSION = true ? "0.8.17" : "0.0.0-dev";
|
|
97593
|
+
var PRODUCER_VERSION = true ? "0.8.17" : "0.0.0-dev";
|
|
97381
97594
|
|
|
97382
97595
|
// src/fontLocalizeCli.ts
|
|
97383
97596
|
async function readStdin() {
|