@hyperframes/producer 0.8.193 → 0.8.195
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/distributed.js +86 -25
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +72 -66
- package/dist/index.js +139 -35
- package/dist/public-server.js +139 -35
- package/dist/services/htmlCompiler.d.ts +2 -1
- package/dist/services/render/artifactTransaction.d.ts +3 -1
- package/dist/services/renderOrchestrator.d.ts +4 -2
- package/package.json +7 -7
package/dist/public-server.js
CHANGED
|
@@ -1583,8 +1583,11 @@ function assertDurationWithinTolerance(expectedSeconds, probedSeconds, tolerance
|
|
|
1583
1583
|
`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}`
|
|
1584
1584
|
);
|
|
1585
1585
|
}
|
|
1586
|
+
function hasUsableFrameCount(frames) {
|
|
1587
|
+
return frames !== void 0 && Number.isFinite(frames) && frames > 0;
|
|
1588
|
+
}
|
|
1586
1589
|
function assertFrameCountWithinTolerance(expectedFrames, probedFrames, stagingPath, toleranceFrames = 1) {
|
|
1587
|
-
if (
|
|
1590
|
+
if (!hasUsableFrameCount(probedFrames)) {
|
|
1588
1591
|
return;
|
|
1589
1592
|
}
|
|
1590
1593
|
const shortfall = expectedFrames - probedFrames;
|
|
@@ -1604,9 +1607,10 @@ function assertSizeMatches(expected, probed, stagingPath) {
|
|
|
1604
1607
|
);
|
|
1605
1608
|
}
|
|
1606
1609
|
var ArtifactTransaction = class {
|
|
1607
|
-
constructor(destinationPath, kind, fileSystem = defaultFileSystem, durationProbe = defaultArtifactDurationProbe) {
|
|
1610
|
+
constructor(destinationPath, kind, fileSystem = defaultFileSystem, durationProbe = defaultArtifactDurationProbe, logger = defaultLogger) {
|
|
1608
1611
|
this.kind = kind;
|
|
1609
1612
|
this.fileSystem = fileSystem;
|
|
1613
|
+
this.logger = logger;
|
|
1610
1614
|
this.destinationPath = resolve4(destinationPath);
|
|
1611
1615
|
this.transactionDirectory = createSiblingTransactionDirectory(this.destinationPath);
|
|
1612
1616
|
this.stagingPath = join5(this.transactionDirectory, basename3(this.destinationPath));
|
|
@@ -1689,6 +1693,19 @@ var ArtifactTransaction = class {
|
|
|
1689
1693
|
probePath
|
|
1690
1694
|
);
|
|
1691
1695
|
if (expected.expectedFrames !== void 0) {
|
|
1696
|
+
if (!hasUsableFrameCount(probed.frames)) {
|
|
1697
|
+
try {
|
|
1698
|
+
this.logger.debug(
|
|
1699
|
+
"[Render] Frame-count validation skipped: no usable frame count was reported.",
|
|
1700
|
+
{
|
|
1701
|
+
event: "artifact_frame_count_unavailable",
|
|
1702
|
+
artifact: this.destinationPath,
|
|
1703
|
+
expectedFrames: expected.expectedFrames
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
} catch {
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1692
1709
|
assertFrameCountWithinTolerance(expected.expectedFrames, probed.frames, probePath);
|
|
1693
1710
|
}
|
|
1694
1711
|
assertSizeMatches(expected, probed, probePath);
|
|
@@ -5271,12 +5288,15 @@ import {
|
|
|
5271
5288
|
readMediaStart,
|
|
5272
5289
|
redactTelemetryString as redactTelemetryString2,
|
|
5273
5290
|
resolveNaturalMediaTimelineDurationFromValues,
|
|
5291
|
+
rewriteAssetPath,
|
|
5274
5292
|
rewriteAssetPaths,
|
|
5275
5293
|
rewriteCssAssetUrls,
|
|
5276
5294
|
rewriteInlineStyleAssetUrls
|
|
5277
5295
|
} from "@hyperframes/core";
|
|
5278
5296
|
import { MAX_AUDIO_GAIN } from "@hyperframes/core/audio-gain";
|
|
5279
|
-
import {
|
|
5297
|
+
import { readPlaybackRate } from "@hyperframes/parsers/media-duration";
|
|
5298
|
+
import { resolveRateSpec } from "@hyperframes/core/speed-ramp";
|
|
5299
|
+
import { gsapCdnDist, normalizeGsapBaseUrl } from "@hyperframes/core/gsap-cdn";
|
|
5280
5300
|
import {
|
|
5281
5301
|
assignBundledRuntimeCompositionIds,
|
|
5282
5302
|
assignMediaRenderIds,
|
|
@@ -6309,7 +6329,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, visited = /*
|
|
|
6309
6329
|
const results = await Promise.all(
|
|
6310
6330
|
workItems.map(async (item) => {
|
|
6311
6331
|
const { html: compiledSub } = await compileHtmlFile(
|
|
6312
|
-
item.rawSubHtml,
|
|
6332
|
+
rewriteUnresolvableGsapToCdn(item.rawSubHtml, projectDir, item.srcPath),
|
|
6313
6333
|
dirname6(item.filePath),
|
|
6314
6334
|
downloadDir,
|
|
6315
6335
|
void 0,
|
|
@@ -6483,7 +6503,9 @@ function inlineSubCompositions(html, subCompositions, projectDir, variableOverri
|
|
|
6483
6503
|
let compHtml = subCompositions.get(srcPath) || null;
|
|
6484
6504
|
if (!compHtml) {
|
|
6485
6505
|
const read = readProjectFile(resolve6(projectDir, srcPath));
|
|
6486
|
-
if (read.kind === "file")
|
|
6506
|
+
if (read.kind === "file") {
|
|
6507
|
+
compHtml = rewriteUnresolvableGsapToCdn(read.text, projectDir, srcPath);
|
|
6508
|
+
}
|
|
6487
6509
|
}
|
|
6488
6510
|
return compHtml;
|
|
6489
6511
|
},
|
|
@@ -7026,18 +7048,27 @@ async function embedLocalFontFaces(html, projectDir) {
|
|
|
7026
7048
|
}
|
|
7027
7049
|
return result;
|
|
7028
7050
|
}
|
|
7029
|
-
|
|
7030
|
-
|
|
7051
|
+
function renderGsapDist() {
|
|
7052
|
+
try {
|
|
7053
|
+
return gsapCdnDist(void 0, normalizeGsapBaseUrl(process.env.HYPERFRAMES_GSAP_BASE_URL));
|
|
7054
|
+
} catch (cause) {
|
|
7055
|
+
throw new Error(
|
|
7056
|
+
"Invalid HYPERFRAMES_GSAP_BASE_URL: use an absolute HTTPS npm mirror root (plain HTTP only for localhost) without credentials, query, or fragment",
|
|
7057
|
+
{ cause }
|
|
7058
|
+
);
|
|
7059
|
+
}
|
|
7060
|
+
}
|
|
7061
|
+
function rewriteUnresolvableGsapToCdn(html, projectDir, compSrcPath) {
|
|
7062
|
+
let gsapDist;
|
|
7063
|
+
const exists = (path) => existsSync10(resolve6(projectDir, path));
|
|
7031
7064
|
return html.replace(
|
|
7032
7065
|
/(<script\b[^>]*\bsrc=["'])([^"']*gsap[^"']*\/dist\/([^"']+))(["'][^>]*>)/gi,
|
|
7033
7066
|
(full, prefix, src, file, suffix) => {
|
|
7034
7067
|
if (/^https?:\/\//i.test(src)) return full;
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
defaultLogger.info(
|
|
7038
|
-
|
|
7039
|
-
);
|
|
7040
|
-
return `${prefix}${GSAP_CDN_BASE}${file}${suffix}`;
|
|
7068
|
+
if (exists(compSrcPath ? rewriteAssetPath(compSrcPath, src, exists) : src)) return full;
|
|
7069
|
+
gsapDist ??= renderGsapDist();
|
|
7070
|
+
defaultLogger.info(`[Compiler] Rewriting missing gsap script: ${src} \u2192 ${gsapDist}${file}`);
|
|
7071
|
+
return `${prefix}${gsapDist}${file}${suffix}`;
|
|
7041
7072
|
}
|
|
7042
7073
|
);
|
|
7043
7074
|
}
|
|
@@ -7251,6 +7282,9 @@ async function discoverMediaFromBrowser(page) {
|
|
|
7251
7282
|
const intrinsicDuration = isImage ? 0 : htmlEl.duration;
|
|
7252
7283
|
const playbackStartRaw = htmlEl.getAttribute("data-playback-start");
|
|
7253
7284
|
const mediaStartRaw = htmlEl.getAttribute("data-media-start");
|
|
7285
|
+
const playbackRateRaw = htmlEl.getAttribute("data-playback-rate");
|
|
7286
|
+
const automationRaw = htmlEl.getAttribute("data-automation");
|
|
7287
|
+
const defaultPlaybackRate = isImage ? 1 : htmlEl.defaultPlaybackRate;
|
|
7254
7288
|
const loop = htmlEl.hasAttribute("loop");
|
|
7255
7289
|
const hasAudio = htmlEl.getAttribute("data-has-audio") === "true";
|
|
7256
7290
|
const volume = parseFloat(htmlEl.getAttribute("data-volume") || "1");
|
|
@@ -7266,6 +7300,9 @@ async function discoverMediaFromBrowser(page) {
|
|
|
7266
7300
|
durationInferred,
|
|
7267
7301
|
playbackStartRaw,
|
|
7268
7302
|
mediaStartRaw,
|
|
7303
|
+
playbackRateRaw,
|
|
7304
|
+
automationRaw,
|
|
7305
|
+
defaultPlaybackRate,
|
|
7269
7306
|
loop,
|
|
7270
7307
|
hasAudio,
|
|
7271
7308
|
volume,
|
|
@@ -7275,7 +7312,17 @@ async function discoverMediaFromBrowser(page) {
|
|
|
7275
7312
|
return results;
|
|
7276
7313
|
});
|
|
7277
7314
|
return elements.map(
|
|
7278
|
-
({
|
|
7315
|
+
({
|
|
7316
|
+
endRaw,
|
|
7317
|
+
durationRaw,
|
|
7318
|
+
intrinsicDuration,
|
|
7319
|
+
playbackStartRaw,
|
|
7320
|
+
mediaStartRaw,
|
|
7321
|
+
playbackRateRaw,
|
|
7322
|
+
automationRaw,
|
|
7323
|
+
defaultPlaybackRate,
|
|
7324
|
+
...element
|
|
7325
|
+
}) => ({
|
|
7279
7326
|
...element,
|
|
7280
7327
|
end: parseStrictFiniteTimingNumber(endRaw) ?? 0,
|
|
7281
7328
|
duration: element.durationInferred && Number.isFinite(intrinsicDuration) && intrinsicDuration > 0 ? intrinsicDuration : parseStrictFiniteTimingNumber(durationRaw) ?? 0,
|
|
@@ -7285,7 +7332,14 @@ async function discoverMediaFromBrowser(page) {
|
|
|
7285
7332
|
if (name === "data-media-start") return mediaStartRaw;
|
|
7286
7333
|
return null;
|
|
7287
7334
|
}
|
|
7288
|
-
})
|
|
7335
|
+
}),
|
|
7336
|
+
playbackRate: resolveRateSpec(
|
|
7337
|
+
automationRaw,
|
|
7338
|
+
readPlaybackRate(
|
|
7339
|
+
(name) => name === "data-playback-rate" ? playbackRateRaw : null,
|
|
7340
|
+
defaultPlaybackRate
|
|
7341
|
+
)
|
|
7342
|
+
)
|
|
7289
7343
|
})
|
|
7290
7344
|
);
|
|
7291
7345
|
}
|
|
@@ -7705,9 +7759,18 @@ import {
|
|
|
7705
7759
|
getCompositionDuration,
|
|
7706
7760
|
initializeSession as initializeSession4,
|
|
7707
7761
|
isTransientBrowserError,
|
|
7708
|
-
probeBeginFrameLiveness
|
|
7762
|
+
probeBeginFrameLiveness,
|
|
7763
|
+
videoAudioId
|
|
7709
7764
|
} from "@hyperframes/engine";
|
|
7710
|
-
import {
|
|
7765
|
+
import {
|
|
7766
|
+
MEDIA_RENDER_ID_ATTR as MEDIA_RENDER_ID_ATTR2,
|
|
7767
|
+
fpsToNumber as fpsToNumber7,
|
|
7768
|
+
normalizeRateSpec as normalizeRateSpec3,
|
|
7769
|
+
readMediaStart as readMediaStart2,
|
|
7770
|
+
shiftRateLane as shiftRateLane2,
|
|
7771
|
+
sourceTimeAt as sourceTimeAt3,
|
|
7772
|
+
timeAtSourceTime
|
|
7773
|
+
} from "@hyperframes/core";
|
|
7711
7774
|
import { extractMediaSrcMutations } from "@hyperframes/parsers";
|
|
7712
7775
|
|
|
7713
7776
|
// src/services/render/stages/probeFailures.ts
|
|
@@ -7766,16 +7829,28 @@ function authoredMediaStarts(html) {
|
|
|
7766
7829
|
}
|
|
7767
7830
|
return starts;
|
|
7768
7831
|
}
|
|
7769
|
-
function
|
|
7832
|
+
function isVideoAudio(audio, videoId) {
|
|
7833
|
+
return audio.type === "video" && audio.id === videoAudioId(videoId);
|
|
7834
|
+
}
|
|
7835
|
+
function adoptRuntimeMediaTiming(composition, el, authored) {
|
|
7770
7836
|
const shift = el.mediaStart - authored;
|
|
7771
|
-
if (el.mediaStart <= 0 || Math.abs(shift) <= BROWSER_MEDIA_EPSILON) return;
|
|
7772
7837
|
const entries = el.tagName === "video" ? [
|
|
7773
7838
|
...composition.videos.filter((video) => video.id === el.id),
|
|
7774
|
-
...composition.audios.filter(
|
|
7775
|
-
(audio) => audio.type === "video" && audio.id === `${el.id}-audio`
|
|
7776
|
-
)
|
|
7839
|
+
...composition.audios.filter((audio) => isVideoAudio(audio, el.id))
|
|
7777
7840
|
] : composition.audios.filter((audio) => audio.type !== "video" && audio.id === el.id);
|
|
7778
|
-
for (const entry of entries)
|
|
7841
|
+
for (const entry of entries) {
|
|
7842
|
+
if (typeof entry.playbackRate !== "object") {
|
|
7843
|
+
if (typeof el.playbackRate === "object") {
|
|
7844
|
+
const consumed = Math.max(0, entry.mediaStart - authored);
|
|
7845
|
+
const head = timeAtSourceTime(normalizeRateSpec3(entry.playbackRate), consumed);
|
|
7846
|
+
entry.mediaStart += sourceTimeAt3(el.playbackRate, head) - consumed;
|
|
7847
|
+
entry.playbackRate = shiftRateLane2(el.playbackRate, head);
|
|
7848
|
+
} else {
|
|
7849
|
+
entry.playbackRate = el.playbackRate;
|
|
7850
|
+
}
|
|
7851
|
+
}
|
|
7852
|
+
if (el.mediaStart > 0 && Math.abs(shift) > BROWSER_MEDIA_EPSILON) entry.mediaStart += shift;
|
|
7853
|
+
}
|
|
7779
7854
|
}
|
|
7780
7855
|
function reconcileBrowserMediaEnd(existingEnd, projectedEnd, sourceChanged, durationInferred) {
|
|
7781
7856
|
if (projectedEnd <= 0) return existingEnd;
|
|
@@ -8059,7 +8134,7 @@ async function runProbeStage(input) {
|
|
|
8059
8134
|
sourceChanged,
|
|
8060
8135
|
el.durationInferred
|
|
8061
8136
|
);
|
|
8062
|
-
|
|
8137
|
+
adoptRuntimeMediaTiming(
|
|
8063
8138
|
composition,
|
|
8064
8139
|
el,
|
|
8065
8140
|
authoredStarts.get(el.id) ?? existing.mediaStart
|
|
@@ -8082,6 +8157,7 @@ async function runProbeStage(input) {
|
|
|
8082
8157
|
start: el.start,
|
|
8083
8158
|
end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
|
|
8084
8159
|
mediaStart: el.mediaStart,
|
|
8160
|
+
playbackRate: el.playbackRate,
|
|
8085
8161
|
loop: el.loop,
|
|
8086
8162
|
hasAudio: el.hasAudio && !el.muted
|
|
8087
8163
|
});
|
|
@@ -8106,7 +8182,7 @@ async function runProbeStage(input) {
|
|
|
8106
8182
|
sourceChanged,
|
|
8107
8183
|
el.durationInferred
|
|
8108
8184
|
);
|
|
8109
|
-
|
|
8185
|
+
adoptRuntimeMediaTiming(
|
|
8110
8186
|
composition,
|
|
8111
8187
|
el,
|
|
8112
8188
|
authoredStarts.get(el.id) ?? existing.mediaStart
|
|
@@ -8124,6 +8200,7 @@ async function runProbeStage(input) {
|
|
|
8124
8200
|
end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
|
|
8125
8201
|
mediaStart: el.mediaStart,
|
|
8126
8202
|
loop: el.loop,
|
|
8203
|
+
playbackRate: el.playbackRate,
|
|
8127
8204
|
layer: 0,
|
|
8128
8205
|
volume: el.volume,
|
|
8129
8206
|
type: "audio"
|
|
@@ -8353,7 +8430,8 @@ import {
|
|
|
8353
8430
|
isHttpUrl as isHttpUrl2,
|
|
8354
8431
|
resolveProjectRelativeSrc as resolveProjectRelativeSrc3,
|
|
8355
8432
|
runVideoExtractionWithRetry,
|
|
8356
|
-
safeVideoExtractionSourceIdentity
|
|
8433
|
+
safeVideoExtractionSourceIdentity,
|
|
8434
|
+
videoAudioId as videoAudioId2
|
|
8357
8435
|
} from "@hyperframes/engine";
|
|
8358
8436
|
|
|
8359
8437
|
// src/services/render/extractionFailureMetadata.ts
|
|
@@ -8706,7 +8784,7 @@ function appendAutoDetectedVideoAudio(composition, extracted) {
|
|
|
8706
8784
|
const video = composition.videos.find((v) => v.id === ext.videoId);
|
|
8707
8785
|
if (!video || !video.hasAudio || video.hidden || existingAudioSrcs.has(video.src)) continue;
|
|
8708
8786
|
composition.audios.push({
|
|
8709
|
-
id:
|
|
8787
|
+
id: videoAudioId2(video.id),
|
|
8710
8788
|
src: video.src,
|
|
8711
8789
|
start: video.start,
|
|
8712
8790
|
end: video.end,
|
|
@@ -11732,13 +11810,36 @@ function colorGradingValueHasLut(rawAttributeValue) {
|
|
|
11732
11810
|
return false;
|
|
11733
11811
|
}
|
|
11734
11812
|
}
|
|
11735
|
-
|
|
11813
|
+
var PROBE_READ_TIMEOUT_MS = 5e3;
|
|
11814
|
+
async function evaluateWithinBound(page, fn, what, log) {
|
|
11815
|
+
let timer;
|
|
11816
|
+
const timedOut = new Promise((_, reject) => {
|
|
11817
|
+
timer = setTimeout(
|
|
11818
|
+
() => reject(new Error(`no answer within ${PROBE_READ_TIMEOUT_MS} ms (page busy)`)),
|
|
11819
|
+
PROBE_READ_TIMEOUT_MS
|
|
11820
|
+
);
|
|
11821
|
+
});
|
|
11822
|
+
try {
|
|
11823
|
+
return await Promise.race([page.evaluate(fn), timedOut]);
|
|
11824
|
+
} catch (err) {
|
|
11825
|
+
log.warn(`[Render] live ${what} read skipped; using the static answer`, {
|
|
11826
|
+
error: err instanceof Error ? err.message : String(err)
|
|
11827
|
+
});
|
|
11828
|
+
throw err;
|
|
11829
|
+
} finally {
|
|
11830
|
+
clearTimeout(timer);
|
|
11831
|
+
}
|
|
11832
|
+
}
|
|
11833
|
+
async function resolveCompositionElementCount(probeSession, html, log = defaultLogger) {
|
|
11736
11834
|
if (probeSession?.isInitialized) {
|
|
11737
11835
|
try {
|
|
11738
|
-
const liveCount = await
|
|
11836
|
+
const liveCount = await evaluateWithinBound(
|
|
11837
|
+
probeSession.page,
|
|
11739
11838
|
// Live HTMLCollection length — avoids materializing a static NodeList
|
|
11740
11839
|
// on the large-DOM comps this gate exists to catch (review nit).
|
|
11741
|
-
() => document.getElementsByTagName("*").length
|
|
11840
|
+
() => document.getElementsByTagName("*").length,
|
|
11841
|
+
"element count",
|
|
11842
|
+
log
|
|
11742
11843
|
);
|
|
11743
11844
|
if (typeof liveCount === "number" && Number.isFinite(liveCount)) {
|
|
11744
11845
|
return { count: liveCount, source: "live" };
|
|
@@ -11826,11 +11927,11 @@ function probeAdaptersUsed() {
|
|
|
11826
11927
|
}
|
|
11827
11928
|
return used;
|
|
11828
11929
|
}
|
|
11829
|
-
async function resolveAdaptersUsed(probeSession, html) {
|
|
11930
|
+
async function resolveAdaptersUsed(probeSession, html, log = defaultLogger) {
|
|
11830
11931
|
const staticAdapters = detectAdaptersStatic(html);
|
|
11831
11932
|
if (!probeSession?.isInitialized) return staticAdapters;
|
|
11832
11933
|
try {
|
|
11833
|
-
const live = await probeSession.page
|
|
11934
|
+
const live = await evaluateWithinBound(probeSession.page, probeAdaptersUsed, "adapters", log);
|
|
11834
11935
|
if (!Array.isArray(live)) return staticAdapters;
|
|
11835
11936
|
const detected = /* @__PURE__ */ new Set([...staticAdapters, ...live]);
|
|
11836
11937
|
return KNOWN_RUNTIME_ADAPTERS.filter((name) => detected.has(name));
|
|
@@ -12088,7 +12189,10 @@ async function executeRenderPipeline(input) {
|
|
|
12088
12189
|
);
|
|
12089
12190
|
const artifactTransaction = new ArtifactTransaction(
|
|
12090
12191
|
outputPath,
|
|
12091
|
-
isPngSequence || isHls ? "directory" : "file"
|
|
12192
|
+
isPngSequence || isHls ? "directory" : "file",
|
|
12193
|
+
void 0,
|
|
12194
|
+
void 0,
|
|
12195
|
+
log
|
|
12092
12196
|
);
|
|
12093
12197
|
const stagedOutputPath = artifactTransaction.stagingPath;
|
|
12094
12198
|
const needsAlpha = outputNeedsAlpha(outputFormat);
|
|
@@ -12587,8 +12691,8 @@ async function executeRenderPipeline(input) {
|
|
|
12587
12691
|
vfxHostCount,
|
|
12588
12692
|
vfxCapture,
|
|
12589
12693
|
vfxTypes
|
|
12590
|
-
} = await resolveCompositionElementCount(probeSession, compiled.html);
|
|
12591
|
-
const adaptersUsed = await resolveAdaptersUsed(probeSession, compiled.html);
|
|
12694
|
+
} = await resolveCompositionElementCount(probeSession, compiled.html, log);
|
|
12695
|
+
const adaptersUsed = await resolveAdaptersUsed(probeSession, compiled.html, log);
|
|
12592
12696
|
const deShortBandEnabled = deShortBandMaxElements > 0;
|
|
12593
12697
|
const deShortBandOpen = deShortBandEnabled && deShortBandMinFrames > 0 && compositionElementCountSource === "live" && compositionElementCount <= deShortBandMaxElements;
|
|
12594
12698
|
const deShortBandRoute = process.env.HF_DE_SHORT_BAND_ROUTE === "true";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ResolvedDuration, type UnresolvedElement } from "@hyperframes/core";
|
|
1
|
+
import { type RateSpec, type ResolvedDuration, type UnresolvedElement } from "@hyperframes/core";
|
|
2
2
|
import { type VideoElement, type ImageElement, type AudioElement, type AudioVolumeKeyframe } from "@hyperframes/engine";
|
|
3
3
|
import type { Page } from "puppeteer-core";
|
|
4
4
|
import { type ProducerLogger } from "../logger.js";
|
|
@@ -216,6 +216,7 @@ export interface BrowserMediaElement {
|
|
|
216
216
|
/** True when compilation inferred duration from the fallback source. */
|
|
217
217
|
durationInferred: boolean;
|
|
218
218
|
mediaStart: number;
|
|
219
|
+
playbackRate: RateSpec;
|
|
219
220
|
loop: boolean;
|
|
220
221
|
hasAudio: boolean;
|
|
221
222
|
volume: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProducerLogger } from "../../logger.js";
|
|
1
2
|
import type { RenderOutputFormat } from "./renderFormat.js";
|
|
2
3
|
export type ArtifactKind = "file" | "directory";
|
|
3
4
|
export interface ArtifactTransactionFileSystem {
|
|
@@ -113,13 +114,14 @@ export declare function buildArtifactExpectation(input: {
|
|
|
113
114
|
export declare class ArtifactTransaction {
|
|
114
115
|
private readonly kind;
|
|
115
116
|
private readonly fileSystem;
|
|
117
|
+
private readonly logger;
|
|
116
118
|
readonly destinationPath: string;
|
|
117
119
|
readonly stagingPath: string;
|
|
118
120
|
private readonly transactionDirectory;
|
|
119
121
|
private readonly backupPath;
|
|
120
122
|
private state;
|
|
121
123
|
private readonly durationProbe;
|
|
122
|
-
constructor(destinationPath: string, kind: ArtifactKind, fileSystem?: ArtifactTransactionFileSystem, durationProbe?: ArtifactDurationProbe);
|
|
124
|
+
constructor(destinationPath: string, kind: ArtifactKind, fileSystem?: ArtifactTransactionFileSystem, durationProbe?: ArtifactDurationProbe, logger?: Pick<ProducerLogger, "debug">);
|
|
123
125
|
validate(expected?: ArtifactValidationExpectation): Promise<void>;
|
|
124
126
|
private assertReadableNonEmptyDirectory;
|
|
125
127
|
/**
|
|
@@ -706,6 +706,8 @@ export interface ElementTagScan {
|
|
|
706
706
|
* live count and uses this only when no such session exists.
|
|
707
707
|
*/
|
|
708
708
|
export declare function scanElementTags(html: string): ElementTagScan;
|
|
709
|
+
/** Longest a live probe-page read may hold the render; a busy page otherwise waits out the CDP timeout. */
|
|
710
|
+
export declare const PROBE_READ_TIMEOUT_MS = 5000;
|
|
709
711
|
/**
|
|
710
712
|
* Element count for the short-comp band's gate, WITH PROVENANCE.
|
|
711
713
|
*
|
|
@@ -728,7 +730,7 @@ export declare function scanElementTags(html: string): ElementTagScan;
|
|
|
728
730
|
* the fleet distribution recorded by the baseline release must be measured
|
|
729
731
|
* by the same resolver that later gates routing, or the baseline is invalid.
|
|
730
732
|
*/
|
|
731
|
-
export declare function resolveCompositionElementCount(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string): Promise<{
|
|
733
|
+
export declare function resolveCompositionElementCount(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string, log?: Pick<ProducerLogger, "warn">): Promise<{
|
|
732
734
|
count: number;
|
|
733
735
|
source: "live" | "static";
|
|
734
736
|
byTag?: Readonly<Record<string, number>>;
|
|
@@ -761,7 +763,7 @@ export declare function detectAdaptersStatic(html: string): RuntimeAdapterName[]
|
|
|
761
763
|
* Runtime adapters a composition exercises. Unlike `resolveCompositionElementCount`
|
|
762
764
|
* (one source of truth, for gating), this is observational: unions live + static every render.
|
|
763
765
|
*/
|
|
764
|
-
export declare function resolveAdaptersUsed(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string): Promise<readonly RuntimeAdapterName[]>;
|
|
766
|
+
export declare function resolveAdaptersUsed(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string, log?: Pick<ProducerLogger, "warn">): Promise<readonly RuntimeAdapterName[]>;
|
|
765
767
|
/**
|
|
766
768
|
* Max-merge init telemetry across per-worker capture perf summaries — the
|
|
767
769
|
* success-path channel for PARALLEL renders, whose worker console buffers
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.195",
|
|
4
4
|
"description": "HTML-to-video rendering engine using Chrome's BeginFrame API",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"postcss": "^8.4.0",
|
|
36
36
|
"puppeteer": "^25.2.1",
|
|
37
37
|
"puppeteer-core": "^25.2.1",
|
|
38
|
-
"@hyperframes/
|
|
39
|
-
"@hyperframes/
|
|
40
|
-
"@hyperframes/
|
|
41
|
-
"@hyperframes/
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/core": "0.8.195",
|
|
39
|
+
"@hyperframes/lint": "0.8.195",
|
|
40
|
+
"@hyperframes/studio-server": "0.8.195",
|
|
41
|
+
"@hyperframes/parsers": "0.8.195",
|
|
42
|
+
"@hyperframes/engine": "0.8.195"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^25.0.10",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"tsx": "^4.21.0",
|
|
49
49
|
"typescript": "^5.7.2",
|
|
50
50
|
"vitest": "^4.1.11",
|
|
51
|
-
"@hyperframes/aws-lambda": "0.8.
|
|
51
|
+
"@hyperframes/aws-lambda": "0.8.195"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|