hyperframes 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ var VERSION;
|
|
|
54
54
|
var init_version = __esm({
|
|
55
55
|
"src/version.ts"() {
|
|
56
56
|
"use strict";
|
|
57
|
-
VERSION = true ? "0.4.
|
|
57
|
+
VERSION = true ? "0.4.6" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -20938,6 +20938,15 @@ function isFontResourceError(type, text, locationUrl) {
|
|
|
20938
20938
|
`${locationUrl} ${text}`
|
|
20939
20939
|
);
|
|
20940
20940
|
}
|
|
20941
|
+
async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100) {
|
|
20942
|
+
const deadline = Date.now() + timeoutMs;
|
|
20943
|
+
while (Date.now() < deadline) {
|
|
20944
|
+
const ready = Boolean(await page.evaluate(expression));
|
|
20945
|
+
if (ready) return true;
|
|
20946
|
+
await new Promise((resolve35) => setTimeout(resolve35, intervalMs));
|
|
20947
|
+
}
|
|
20948
|
+
return Boolean(await page.evaluate(expression));
|
|
20949
|
+
}
|
|
20941
20950
|
async function initializeSession(session) {
|
|
20942
20951
|
const { page, serverUrl } = session;
|
|
20943
20952
|
page.on("console", (msg) => {
|
|
@@ -20967,14 +20976,26 @@ async function initializeSession(session) {
|
|
|
20967
20976
|
if (session.captureMode === "screenshot") {
|
|
20968
20977
|
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
20969
20978
|
const pageReadyTimeout2 = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout;
|
|
20970
|
-
await
|
|
20979
|
+
const pageReady2 = await pollPageExpression(
|
|
20980
|
+
page,
|
|
20971
20981
|
`!!(window.__hf && typeof window.__hf.seek === "function" && window.__hf.duration > 0)`,
|
|
20972
|
-
|
|
20982
|
+
pageReadyTimeout2
|
|
20973
20983
|
);
|
|
20974
|
-
|
|
20984
|
+
if (!pageReady2) {
|
|
20985
|
+
throw new Error(
|
|
20986
|
+
`[FrameCapture] window.__hf not ready after ${pageReadyTimeout2}ms. Page must expose window.__hf = { duration, seek }.`
|
|
20987
|
+
);
|
|
20988
|
+
}
|
|
20989
|
+
const videosReady = await pollPageExpression(
|
|
20990
|
+
page,
|
|
20975
20991
|
`document.querySelectorAll("video").length === 0 || Array.from(document.querySelectorAll("video")).every(v => v.readyState >= 1)`,
|
|
20976
|
-
|
|
20992
|
+
pageReadyTimeout2
|
|
20977
20993
|
);
|
|
20994
|
+
if (!videosReady) {
|
|
20995
|
+
throw new Error(
|
|
20996
|
+
`[FrameCapture] video metadata not ready after ${pageReadyTimeout2}ms. Video elements must load metadata before capture starts.`
|
|
20997
|
+
);
|
|
20998
|
+
}
|
|
20978
20999
|
await page.evaluate(`document.fonts?.ready`);
|
|
20979
21000
|
session.isInitialized = true;
|
|
20980
21001
|
return;
|
|
@@ -24079,8 +24100,22 @@ function injectScriptsIntoHtml2(html, headScripts, bodyScripts, stripEmbedded) {
|
|
|
24079
24100
|
}
|
|
24080
24101
|
return html;
|
|
24081
24102
|
}
|
|
24103
|
+
function injectScriptsAtHeadStart(html, scripts) {
|
|
24104
|
+
if (scripts.length === 0) return html;
|
|
24105
|
+
const headTags = scripts.map((src) => `<script>${src}</script>`).join("\n");
|
|
24106
|
+
if (html.includes("<head")) {
|
|
24107
|
+
return html.replace(/<head\b[^>]*>/i, (match) => `${match}
|
|
24108
|
+
${headTags}`);
|
|
24109
|
+
}
|
|
24110
|
+
if (html.includes("<body")) {
|
|
24111
|
+
return html.replace("<body", () => `${headTags}
|
|
24112
|
+
<body`);
|
|
24113
|
+
}
|
|
24114
|
+
return headTags + "\n" + html;
|
|
24115
|
+
}
|
|
24082
24116
|
function createFileServer2(options) {
|
|
24083
24117
|
const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
|
|
24118
|
+
const preHeadScripts = options.preHeadScripts ?? [];
|
|
24084
24119
|
const headScripts = options.headScripts ?? [getVerifiedHyperframeRuntimeSource()];
|
|
24085
24120
|
const bodyScripts = options.bodyScripts ?? [RENDER_MODE_SCRIPT, HF_BRIDGE_SCRIPT];
|
|
24086
24121
|
const app = new Hono3();
|
|
@@ -24104,7 +24139,11 @@ function createFileServer2(options) {
|
|
|
24104
24139
|
if (ext === ".html") {
|
|
24105
24140
|
const rawHtml = readFileSync17(filePath, "utf-8");
|
|
24106
24141
|
const isIndex = relativePath === "index.html";
|
|
24107
|
-
|
|
24142
|
+
let html = rawHtml;
|
|
24143
|
+
if (preHeadScripts.length > 0) {
|
|
24144
|
+
html = injectScriptsAtHeadStart(html, preHeadScripts);
|
|
24145
|
+
}
|
|
24146
|
+
html = isIndex ? injectScriptsIntoHtml2(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
|
|
24108
24147
|
return c2.text(html, 200, { "Content-Type": contentType });
|
|
24109
24148
|
}
|
|
24110
24149
|
const content = readFileSync17(filePath);
|
|
@@ -24132,7 +24171,7 @@ function createFileServer2(options) {
|
|
|
24132
24171
|
});
|
|
24133
24172
|
});
|
|
24134
24173
|
}
|
|
24135
|
-
var MIME_TYPES3, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_BRIDGE_SCRIPT;
|
|
24174
|
+
var MIME_TYPES3, VIRTUAL_TIME_SHIM, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_BRIDGE_SCRIPT;
|
|
24136
24175
|
var init_fileServer2 = __esm({
|
|
24137
24176
|
"../producer/src/services/fileServer.ts"() {
|
|
24138
24177
|
"use strict";
|
|
@@ -24159,6 +24198,102 @@ var init_fileServer2 = __esm({
|
|
|
24159
24198
|
".ttf": "font/ttf",
|
|
24160
24199
|
".otf": "font/otf"
|
|
24161
24200
|
};
|
|
24201
|
+
VIRTUAL_TIME_SHIM = String.raw`(function() {
|
|
24202
|
+
if (window.__HF_VIRTUAL_TIME__) return;
|
|
24203
|
+
|
|
24204
|
+
var virtualNowMs = 0;
|
|
24205
|
+
var rafId = 1;
|
|
24206
|
+
var rafQueue = [];
|
|
24207
|
+
var OriginalDate = Date;
|
|
24208
|
+
var originalSetTimeout = window.setTimeout.bind(window);
|
|
24209
|
+
var originalClearTimeout = window.clearTimeout.bind(window);
|
|
24210
|
+
var originalSetInterval = window.setInterval.bind(window);
|
|
24211
|
+
var originalClearInterval = window.clearInterval.bind(window);
|
|
24212
|
+
var originalRequestAnimationFrame = window.requestAnimationFrame
|
|
24213
|
+
? window.requestAnimationFrame.bind(window)
|
|
24214
|
+
: null;
|
|
24215
|
+
var originalCancelAnimationFrame = window.cancelAnimationFrame
|
|
24216
|
+
? window.cancelAnimationFrame.bind(window)
|
|
24217
|
+
: null;
|
|
24218
|
+
|
|
24219
|
+
function flushAnimationFrame() {
|
|
24220
|
+
if (!rafQueue.length) return;
|
|
24221
|
+
var current = rafQueue.slice();
|
|
24222
|
+
rafQueue.length = 0;
|
|
24223
|
+
for (var i = 0; i < current.length; i++) {
|
|
24224
|
+
var entry = current[i];
|
|
24225
|
+
if (entry.cancelled) continue;
|
|
24226
|
+
try {
|
|
24227
|
+
entry.callback(virtualNowMs);
|
|
24228
|
+
} catch {}
|
|
24229
|
+
}
|
|
24230
|
+
}
|
|
24231
|
+
|
|
24232
|
+
function VirtualDate() {
|
|
24233
|
+
var args = Array.prototype.slice.call(arguments);
|
|
24234
|
+
if (!(this instanceof VirtualDate)) {
|
|
24235
|
+
return OriginalDate.apply(null, args.length ? args : [virtualNowMs]);
|
|
24236
|
+
}
|
|
24237
|
+
var instance = args.length ? new (Function.prototype.bind.apply(OriginalDate, [null].concat(args)))() : new OriginalDate(virtualNowMs);
|
|
24238
|
+
Object.setPrototypeOf(instance, VirtualDate.prototype);
|
|
24239
|
+
return instance;
|
|
24240
|
+
}
|
|
24241
|
+
|
|
24242
|
+
VirtualDate.prototype = OriginalDate.prototype;
|
|
24243
|
+
Object.setPrototypeOf(VirtualDate, OriginalDate);
|
|
24244
|
+
VirtualDate.now = function() { return virtualNowMs; };
|
|
24245
|
+
VirtualDate.parse = OriginalDate.parse.bind(OriginalDate);
|
|
24246
|
+
VirtualDate.UTC = OriginalDate.UTC.bind(OriginalDate);
|
|
24247
|
+
|
|
24248
|
+
try {
|
|
24249
|
+
Object.defineProperty(window, "Date", {
|
|
24250
|
+
configurable: true,
|
|
24251
|
+
writable: true,
|
|
24252
|
+
value: VirtualDate,
|
|
24253
|
+
});
|
|
24254
|
+
} catch {}
|
|
24255
|
+
|
|
24256
|
+
if (window.performance && typeof window.performance.now === "function") {
|
|
24257
|
+
try {
|
|
24258
|
+
Object.defineProperty(window.performance, "now", {
|
|
24259
|
+
configurable: true,
|
|
24260
|
+
value: function() { return virtualNowMs; },
|
|
24261
|
+
});
|
|
24262
|
+
} catch {}
|
|
24263
|
+
}
|
|
24264
|
+
|
|
24265
|
+
window.requestAnimationFrame = function(callback) {
|
|
24266
|
+
if (typeof callback !== "function") return 0;
|
|
24267
|
+
var entry = { id: rafId++, callback: callback, cancelled: false };
|
|
24268
|
+
rafQueue.push(entry);
|
|
24269
|
+
return entry.id;
|
|
24270
|
+
};
|
|
24271
|
+
window.cancelAnimationFrame = function(id) {
|
|
24272
|
+
for (var i = 0; i < rafQueue.length; i++) {
|
|
24273
|
+
if (rafQueue[i].id === id) {
|
|
24274
|
+
rafQueue[i].cancelled = true;
|
|
24275
|
+
}
|
|
24276
|
+
}
|
|
24277
|
+
};
|
|
24278
|
+
|
|
24279
|
+
window.__HF_VIRTUAL_TIME__ = {
|
|
24280
|
+
originalSetTimeout: originalSetTimeout,
|
|
24281
|
+
originalClearTimeout: originalClearTimeout,
|
|
24282
|
+
originalSetInterval: originalSetInterval,
|
|
24283
|
+
originalClearInterval: originalClearInterval,
|
|
24284
|
+
originalRequestAnimationFrame: originalRequestAnimationFrame,
|
|
24285
|
+
originalCancelAnimationFrame: originalCancelAnimationFrame,
|
|
24286
|
+
seekToTime: function(nextTimeMs) {
|
|
24287
|
+
var safeTimeMs = Math.max(0, Number(nextTimeMs) || 0);
|
|
24288
|
+
virtualNowMs = safeTimeMs;
|
|
24289
|
+
flushAnimationFrame();
|
|
24290
|
+
return virtualNowMs;
|
|
24291
|
+
},
|
|
24292
|
+
getTime: function() {
|
|
24293
|
+
return virtualNowMs;
|
|
24294
|
+
},
|
|
24295
|
+
};
|
|
24296
|
+
})();`;
|
|
24162
24297
|
RENDER_SEEK_MODE = process.env.PRODUCER_RUNTIME_RENDER_SEEK_MODE === "strict-boundary" ? "strict-boundary" : "preview-phase";
|
|
24163
24298
|
RENDER_SEEK_DIAGNOSTICS = process.env.PRODUCER_DEBUG_SEEK_DIAGNOSTICS === "true";
|
|
24164
24299
|
RENDER_SEEK_STEP = Math.max(
|
|
@@ -24170,6 +24305,10 @@ var init_fileServer2 = __esm({
|
|
|
24170
24305
|
Math.min(0.95, Number(process.env.PRODUCER_RUNTIME_RENDER_SEEK_OFFSET_FRACTION || 0.5))
|
|
24171
24306
|
);
|
|
24172
24307
|
RENDER_MODE_SCRIPT = `(function() {
|
|
24308
|
+
var __realSetTimeout =
|
|
24309
|
+
window.__HF_VIRTUAL_TIME__ && typeof window.__HF_VIRTUAL_TIME__.originalSetTimeout === "function"
|
|
24310
|
+
? window.__HF_VIRTUAL_TIME__.originalSetTimeout
|
|
24311
|
+
: window.setTimeout.bind(window);
|
|
24173
24312
|
var __seekMode = ${JSON.stringify(RENDER_SEEK_MODE)};
|
|
24174
24313
|
var __seekDiagnostics = ${RENDER_SEEK_DIAGNOSTICS ? "true" : "false"};
|
|
24175
24314
|
var __seekStep = ${RENDER_SEEK_STEP};
|
|
@@ -24263,23 +24402,56 @@ var init_fileServer2 = __esm({
|
|
|
24263
24402
|
window.__renderReady = true;
|
|
24264
24403
|
return;
|
|
24265
24404
|
}
|
|
24266
|
-
|
|
24405
|
+
__realSetTimeout(waitForPlayer, 50);
|
|
24267
24406
|
return;
|
|
24268
24407
|
}
|
|
24269
24408
|
if (installMediaFallbackPlayer()) {
|
|
24270
24409
|
return;
|
|
24271
24410
|
}
|
|
24272
|
-
|
|
24411
|
+
__realSetTimeout(waitForPlayer, 50);
|
|
24273
24412
|
}
|
|
24274
24413
|
waitForPlayer();
|
|
24275
24414
|
})();`;
|
|
24276
24415
|
HF_BRIDGE_SCRIPT = `(function() {
|
|
24416
|
+
var __realSetInterval =
|
|
24417
|
+
window.__HF_VIRTUAL_TIME__ && typeof window.__HF_VIRTUAL_TIME__.originalSetInterval === "function"
|
|
24418
|
+
? window.__HF_VIRTUAL_TIME__.originalSetInterval
|
|
24419
|
+
: window.setInterval.bind(window);
|
|
24420
|
+
var __realClearInterval =
|
|
24421
|
+
window.__HF_VIRTUAL_TIME__ && typeof window.__HF_VIRTUAL_TIME__.originalClearInterval === "function"
|
|
24422
|
+
? window.__HF_VIRTUAL_TIME__.originalClearInterval
|
|
24423
|
+
: window.clearInterval.bind(window);
|
|
24277
24424
|
function getDeclaredDuration() {
|
|
24278
24425
|
var root = document.querySelector('[data-composition-id]');
|
|
24279
24426
|
if (!root) return 0;
|
|
24280
24427
|
var d = Number(root.getAttribute('data-duration'));
|
|
24281
24428
|
return Number.isFinite(d) && d > 0 ? d : 0;
|
|
24282
24429
|
}
|
|
24430
|
+
function seekSameOriginChildFrames(frameWindow, nextTimeMs) {
|
|
24431
|
+
var frames;
|
|
24432
|
+
try {
|
|
24433
|
+
frames = frameWindow.frames;
|
|
24434
|
+
} catch (_error) {
|
|
24435
|
+
return;
|
|
24436
|
+
}
|
|
24437
|
+
if (!frames || typeof frames.length !== "number") return;
|
|
24438
|
+
for (var i = 0; i < frames.length; i++) {
|
|
24439
|
+
var childWindow = null;
|
|
24440
|
+
try {
|
|
24441
|
+
childWindow = frames[i];
|
|
24442
|
+
if (!childWindow || childWindow === frameWindow) continue;
|
|
24443
|
+
if (
|
|
24444
|
+
childWindow.__HF_VIRTUAL_TIME__ &&
|
|
24445
|
+
typeof childWindow.__HF_VIRTUAL_TIME__.seekToTime === "function"
|
|
24446
|
+
) {
|
|
24447
|
+
childWindow.__HF_VIRTUAL_TIME__.seekToTime(nextTimeMs);
|
|
24448
|
+
}
|
|
24449
|
+
} catch (_error) {
|
|
24450
|
+
continue;
|
|
24451
|
+
}
|
|
24452
|
+
seekSameOriginChildFrames(childWindow, nextTimeMs);
|
|
24453
|
+
}
|
|
24454
|
+
}
|
|
24283
24455
|
function bridge() {
|
|
24284
24456
|
var p = window.__player;
|
|
24285
24457
|
if (!p || typeof p.renderSeek !== "function" || typeof p.getDuration !== "function") {
|
|
@@ -24290,13 +24462,20 @@ var init_fileServer2 = __esm({
|
|
|
24290
24462
|
var d = p.getDuration();
|
|
24291
24463
|
return d > 0 ? d : getDeclaredDuration();
|
|
24292
24464
|
},
|
|
24293
|
-
seek: function(t) {
|
|
24465
|
+
seek: function(t) {
|
|
24466
|
+
p.renderSeek(t);
|
|
24467
|
+
var nextTimeMs = (Math.max(0, Number(t) || 0)) * 1000;
|
|
24468
|
+
if (window.__HF_VIRTUAL_TIME__ && typeof window.__HF_VIRTUAL_TIME__.seekToTime === "function") {
|
|
24469
|
+
window.__HF_VIRTUAL_TIME__.seekToTime(nextTimeMs);
|
|
24470
|
+
}
|
|
24471
|
+
seekSameOriginChildFrames(window, nextTimeMs);
|
|
24472
|
+
},
|
|
24294
24473
|
};
|
|
24295
24474
|
return true;
|
|
24296
24475
|
}
|
|
24297
24476
|
if (bridge()) return;
|
|
24298
|
-
var iv =
|
|
24299
|
-
if (bridge())
|
|
24477
|
+
var iv = __realSetInterval(function() {
|
|
24478
|
+
if (bridge()) __realClearInterval(iv);
|
|
24300
24479
|
}, 50);
|
|
24301
24480
|
})();`;
|
|
24302
24481
|
}
|
|
@@ -24753,6 +24932,36 @@ function dedupeElementsById(elements) {
|
|
|
24753
24932
|
}
|
|
24754
24933
|
return Array.from(deduped.values());
|
|
24755
24934
|
}
|
|
24935
|
+
function stripJsComments(source) {
|
|
24936
|
+
return source.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
24937
|
+
}
|
|
24938
|
+
function detectRenderModeHints(html) {
|
|
24939
|
+
const reasons = [];
|
|
24940
|
+
const { document: document2 } = parseHTML(html);
|
|
24941
|
+
if (document2.querySelector("iframe")) {
|
|
24942
|
+
reasons.push({
|
|
24943
|
+
code: "iframe",
|
|
24944
|
+
message: "Detected <iframe> in the composition DOM. Nested iframe animation is routed through screenshot capture mode for compatibility."
|
|
24945
|
+
});
|
|
24946
|
+
}
|
|
24947
|
+
let scriptMatch;
|
|
24948
|
+
const scriptPattern = new RegExp(INLINE_SCRIPT_PATTERN.source, INLINE_SCRIPT_PATTERN.flags);
|
|
24949
|
+
while ((scriptMatch = scriptPattern.exec(html)) !== null) {
|
|
24950
|
+
const attrs = scriptMatch[1] || "";
|
|
24951
|
+
if (/\bsrc\s*=/i.test(attrs)) continue;
|
|
24952
|
+
const content = stripJsComments(scriptMatch[2] || "");
|
|
24953
|
+
if (!/requestAnimationFrame\s*\(/.test(content)) continue;
|
|
24954
|
+
reasons.push({
|
|
24955
|
+
code: "requestAnimationFrame",
|
|
24956
|
+
message: "Detected raw requestAnimationFrame() in an inline script. This render is routed through screenshot capture mode with virtual time enabled."
|
|
24957
|
+
});
|
|
24958
|
+
break;
|
|
24959
|
+
}
|
|
24960
|
+
return {
|
|
24961
|
+
recommendScreenshot: reasons.length > 0,
|
|
24962
|
+
reasons
|
|
24963
|
+
};
|
|
24964
|
+
}
|
|
24756
24965
|
async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
|
|
24757
24966
|
let filePath = src;
|
|
24758
24967
|
if (isHttpUrl(src)) {
|
|
@@ -25316,6 +25525,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
|
|
|
25316
25525
|
/(<(?:video|audio)\b[^>]*?)\s+preload\s*=\s*["']none["']/gi,
|
|
25317
25526
|
"$1"
|
|
25318
25527
|
);
|
|
25528
|
+
const renderModeHints = detectRenderModeHints(sanitizedHtml);
|
|
25319
25529
|
const coalescedHtml = await injectDeterministicFontFaces(
|
|
25320
25530
|
coalesceHeadStylesAndBodyScripts2(promoteCssImportsToLinkTags(sanitizedHtml))
|
|
25321
25531
|
);
|
|
@@ -25359,7 +25569,8 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
|
|
|
25359
25569
|
externalAssets,
|
|
25360
25570
|
width,
|
|
25361
25571
|
height,
|
|
25362
|
-
staticDuration
|
|
25572
|
+
staticDuration,
|
|
25573
|
+
renderModeHints
|
|
25363
25574
|
};
|
|
25364
25575
|
}
|
|
25365
25576
|
async function discoverMediaFromBrowser(page) {
|
|
@@ -25453,9 +25664,11 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
|
|
|
25453
25664
|
subCompositions,
|
|
25454
25665
|
videos,
|
|
25455
25666
|
audios,
|
|
25456
|
-
unresolvedCompositions: remaining
|
|
25667
|
+
unresolvedCompositions: remaining,
|
|
25668
|
+
renderModeHints: compiled.renderModeHints
|
|
25457
25669
|
};
|
|
25458
25670
|
}
|
|
25671
|
+
var INLINE_SCRIPT_PATTERN;
|
|
25459
25672
|
var init_htmlCompiler2 = __esm({
|
|
25460
25673
|
"../producer/src/services/htmlCompiler.ts"() {
|
|
25461
25674
|
"use strict";
|
|
@@ -25466,6 +25679,7 @@ var init_htmlCompiler2 = __esm({
|
|
|
25466
25679
|
init_src2();
|
|
25467
25680
|
init_urlDownloader2();
|
|
25468
25681
|
init_deterministicFonts();
|
|
25682
|
+
INLINE_SCRIPT_PATTERN = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
|
25469
25683
|
}
|
|
25470
25684
|
});
|
|
25471
25685
|
|
|
@@ -25613,11 +25827,20 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
25613
25827
|
end: a.end,
|
|
25614
25828
|
mediaStart: a.mediaStart
|
|
25615
25829
|
})),
|
|
25616
|
-
subCompositions: Array.from(compiled.subCompositions.keys())
|
|
25830
|
+
subCompositions: Array.from(compiled.subCompositions.keys()),
|
|
25831
|
+
renderModeHints: compiled.renderModeHints
|
|
25617
25832
|
};
|
|
25618
25833
|
writeFileSync10(join30(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
|
|
25619
25834
|
}
|
|
25620
25835
|
}
|
|
25836
|
+
function applyRenderModeHints(cfg, compiled, log = defaultLogger) {
|
|
25837
|
+
if (cfg.forceScreenshot || !compiled.renderModeHints.recommendScreenshot) return;
|
|
25838
|
+
cfg.forceScreenshot = true;
|
|
25839
|
+
log.warn("Auto-selected screenshot capture mode for render compatibility", {
|
|
25840
|
+
reasonCodes: compiled.renderModeHints.reasons.map((reason) => reason.code),
|
|
25841
|
+
reasons: compiled.renderModeHints.reasons.map((reason) => reason.message)
|
|
25842
|
+
});
|
|
25843
|
+
}
|
|
25621
25844
|
function createRenderJob(config) {
|
|
25622
25845
|
return {
|
|
25623
25846
|
id: randomUUID2(),
|
|
@@ -25730,6 +25953,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
25730
25953
|
let compiled = await compileForRender(projectDir, htmlPath, join30(workDir, "downloads"));
|
|
25731
25954
|
assertNotAborted();
|
|
25732
25955
|
perfStages.compileOnlyMs = Date.now() - compileStart;
|
|
25956
|
+
applyRenderModeHints(cfg, compiled, log);
|
|
25733
25957
|
writeCompiledArtifacts(compiled, workDir, Boolean(job.config.debug));
|
|
25734
25958
|
log.info("Compiled composition metadata", {
|
|
25735
25959
|
entryFile,
|
|
@@ -25737,7 +25961,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
25737
25961
|
width: compiled.width,
|
|
25738
25962
|
height: compiled.height,
|
|
25739
25963
|
videoCount: compiled.videos.length,
|
|
25740
|
-
audioCount: compiled.audios.length
|
|
25964
|
+
audioCount: compiled.audios.length,
|
|
25965
|
+
renderModeHints: compiled.renderModeHints
|
|
25741
25966
|
});
|
|
25742
25967
|
const composition = {
|
|
25743
25968
|
duration: compiled.staticDuration,
|
|
@@ -25757,7 +25982,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
25757
25982
|
fileServer = await createFileServer2({
|
|
25758
25983
|
projectDir,
|
|
25759
25984
|
compiledDir: join30(workDir, "compiled"),
|
|
25760
|
-
port: 0
|
|
25985
|
+
port: 0,
|
|
25986
|
+
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
25761
25987
|
});
|
|
25762
25988
|
assertNotAborted();
|
|
25763
25989
|
const captureOpts = {
|
|
@@ -26000,7 +26226,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
26000
26226
|
fileServer = await createFileServer2({
|
|
26001
26227
|
projectDir,
|
|
26002
26228
|
compiledDir: join30(workDir, "compiled"),
|
|
26003
|
-
port: 0
|
|
26229
|
+
port: 0,
|
|
26230
|
+
preHeadScripts: [VIRTUAL_TIME_SHIM]
|
|
26004
26231
|
});
|
|
26005
26232
|
assertNotAborted();
|
|
26006
26233
|
}
|