@hyperframes/engine 0.7.43 → 0.7.44
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/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/frameCapture.d.ts +17 -1
- package/dist/services/frameCapture.d.ts.map +1 -1
- package/dist/services/frameCapture.js +100 -33
- package/dist/services/frameCapture.js.map +1 -1
- package/dist/services/parallelCoordinator.d.ts +18 -2
- package/dist/services/parallelCoordinator.d.ts.map +1 -1
- package/dist/services/parallelCoordinator.js +99 -4
- package/dist/services/parallelCoordinator.js.map +1 -1
- package/dist/services/streamingEncoder.d.ts +8 -0
- package/dist/services/streamingEncoder.d.ts.map +1 -1
- package/dist/services/streamingEncoder.js +29 -10
- package/dist/services/streamingEncoder.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* getFrameAtTime, detectGpuEncoder) return a nullable value instead of throwing.
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
|
-
export type { HfProtocol, HfMediaElement, HfTransitionMeta, CaptureOptions, CaptureVideoMetadataHint, CaptureResult, CaptureBufferResult, CapturePerfSummary, } from "./types.js";
|
|
32
|
+
export type { HfProtocol, HfMediaElement, HfTransitionMeta, CaptureOptions, CaptureVideoMetadataHint, CaptureResult, CaptureBufferResult, CapturePerfSummary, SubTimelineWaitOutcome, } from "./types.js";
|
|
33
33
|
export { resolveConfig, DEFAULT_CONFIG, scaleProtocolTimeoutForComposition, type EngineConfig, } from "./config.js";
|
|
34
34
|
export { DEFAULT_VP9_CPU_USED, MAX_VP9_CPU_USED, MIN_VP9_CPU_USED, normalizeVp9CpuUsed, } from "./services/vp9Options.js";
|
|
35
35
|
export { getSystemTotalMb, isLowMemorySystem, LOW_MEMORY_TOTAL_MB_THRESHOLD, } from "./services/systemMemory.js";
|
|
@@ -43,7 +43,7 @@ export { parseVideoElements, parseImageElements, extractVideoFramesRange, extrac
|
|
|
43
43
|
export { createVideoFrameInjector } from "./services/videoFrameInjector.js";
|
|
44
44
|
export { parseAudioElements, processCompositionAudio } from "./services/audioMixer.js";
|
|
45
45
|
export type { AudioElement, AudioTrack, AudioVolumeKeyframe, MixResult, } from "./services/audioMixer.types.js";
|
|
46
|
-
export { calculateOptimalWorkers, distributeFrames, executeParallelCapture, mergeWorkerFrames, getSystemResources, type WorkerTask, type WorkerResult, type ParallelProgress, } from "./services/parallelCoordinator.js";
|
|
46
|
+
export { calculateOptimalWorkers, distributeFrames, distributeFramesInterleaved, executeParallelCapture, mergeWorkerFrames, getSystemResources, type WorkerTask, type WorkerResult, type ParallelProgress, } from "./services/parallelCoordinator.js";
|
|
47
47
|
export { createFileServer, type FileServerOptions, type FileServerHandle, } from "./services/fileServer.js";
|
|
48
48
|
export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
|
|
49
49
|
export { assertSwiftShader, readWebGlVendorInfo, SwiftShaderAssertionError, BROWSER_GPU_NOT_SOFTWARE, } from "./utils/assertSwiftShader.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ export { parseVideoElements, parseImageElements, extractVideoFramesRange, extrac
|
|
|
47
47
|
export { createVideoFrameInjector } from "./services/videoFrameInjector.js";
|
|
48
48
|
export { parseAudioElements, processCompositionAudio } from "./services/audioMixer.js";
|
|
49
49
|
// ── Parallel rendering ─────────────────────────────────────────────────────────
|
|
50
|
-
export { calculateOptimalWorkers, distributeFrames, executeParallelCapture, mergeWorkerFrames, getSystemResources, } from "./services/parallelCoordinator.js";
|
|
50
|
+
export { calculateOptimalWorkers, distributeFrames, distributeFramesInterleaved, executeParallelCapture, mergeWorkerFrames, getSystemResources, } from "./services/parallelCoordinator.js";
|
|
51
51
|
// ── File server ────────────────────────────────────────────────────────────────
|
|
52
52
|
export { createFileServer, } from "./services/fileServer.js";
|
|
53
53
|
// ── Utilities ──────────────────────────────────────────────────────────────────
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { type Browser, type Page } from "puppeteer-core";
|
|
10
10
|
import { type CaptureMode } from "./browserManager.js";
|
|
11
11
|
import { type EngineConfig } from "../config.js";
|
|
12
|
-
import type { CaptureOptions, CaptureResult, CaptureBufferResult, CapturePerfSummary } from "../types.js";
|
|
12
|
+
import type { CaptureOptions, CaptureResult, CaptureBufferResult, CapturePerfSummary, SubTimelineWaitOutcome } from "../types.js";
|
|
13
13
|
export type { CaptureOptions, CaptureResult, CaptureBufferResult, CapturePerfSummary };
|
|
14
14
|
/** Called after seeking, before screenshot. Use for video frame injection or other pre-capture work. */
|
|
15
15
|
export type BeforeCaptureHook = (page: Page, time: number) => Promise<void>;
|
|
@@ -43,6 +43,16 @@ export interface CaptureSession {
|
|
|
43
43
|
pageReleased?: boolean;
|
|
44
44
|
browserReleased?: boolean;
|
|
45
45
|
browserConsoleBuffer: string[];
|
|
46
|
+
/**
|
|
47
|
+
* Script resources that failed to load (request failure or HTTP >= 400).
|
|
48
|
+
* pollSubCompositionTimelines fail-fasts on these: a comp whose timeline
|
|
49
|
+
* script 404'd can never register window.__timelines[id], so waiting the
|
|
50
|
+
* full playerReadyTimeout (45s) buys nothing (~1% of wild local renders
|
|
51
|
+
* were hitting that wall — a 705-render spike at the 45s setup bucket).
|
|
52
|
+
*/
|
|
53
|
+
scriptLoadFailures: string[];
|
|
54
|
+
/** Outcome of the sub-composition timeline wait: ready | timeout | script_failure. */
|
|
55
|
+
subTimelineWaitOutcome?: SubTimelineWaitOutcome;
|
|
46
56
|
initTelemetry?: {
|
|
47
57
|
initDurationMs: number;
|
|
48
58
|
tweenCount: number;
|
|
@@ -97,6 +107,11 @@ export interface CaptureSession {
|
|
|
97
107
|
* worker-encode path (mirrors `lastFrameBuffer` on the screenshot path). Only set
|
|
98
108
|
* when static-frame dedup is armed on the drawElement path. */
|
|
99
109
|
lastEncodeResult?: Promise<Buffer>;
|
|
110
|
+
/** Frame index lastEncodeResult belongs to — static-dedup reuse must verify
|
|
111
|
+
* every frame in (lastEncodeResultFrame, i] is predicted-static (under the
|
|
112
|
+
* interleaved parallel stride the "previous" produced frame is i−N, and
|
|
113
|
+
* reusing it for frame i is only valid when the whole gap is static). */
|
|
114
|
+
lastEncodeResultFrame?: number;
|
|
100
115
|
/** Per-render self-verification ground truth (ungated-release safety net):
|
|
101
116
|
* K screenshot frames captured at init BEFORE the drawElement canvas is
|
|
102
117
|
* injected (the only window where a page screenshot shows the live DOM, not
|
|
@@ -227,6 +242,7 @@ export declare function formatConsoleDiagnostic(type: string, text: string, loca
|
|
|
227
242
|
text: string;
|
|
228
243
|
suppressHostLog: boolean;
|
|
229
244
|
};
|
|
245
|
+
export declare function pollSubCompositionTimelines(page: Page, timeoutMs: number, intervalMs?: number, getScriptLoadFailures?: () => readonly string[], scriptFailureGraceMs?: number): Promise<SubTimelineWaitOutcome>;
|
|
230
246
|
/** @internal exported for unit testing only */
|
|
231
247
|
export declare function pollImagesReady(page: Page, timeoutMs: number, intervalMs?: number): Promise<boolean>;
|
|
232
248
|
export declare function initializeSession(session: CaptureSession): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frameCapture.d.ts","sourceRoot":"","sources":["../../src/services/frameCapture.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,IAAI,EAAsC,MAAM,gBAAgB,CAAC;AAM7F,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAqB7B,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EACV,cAAc,EAEd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"frameCapture.d.ts","sourceRoot":"","sources":["../../src/services/frameCapture.ts"],"names":[],"mappings":"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"}
|
|
@@ -626,6 +626,7 @@ export async function createCaptureSession(serverUrl, outputDir, options, onBefo
|
|
|
626
626
|
onBeforeCapture,
|
|
627
627
|
isInitialized: false,
|
|
628
628
|
browserConsoleBuffer: [],
|
|
629
|
+
scriptLoadFailures: [],
|
|
629
630
|
capturePerf: {
|
|
630
631
|
frames: 0,
|
|
631
632
|
seekMs: 0,
|
|
@@ -689,16 +690,6 @@ export function formatConsoleDiagnostic(type, text, locationUrl) {
|
|
|
689
690
|
: "[Browser]";
|
|
690
691
|
return { text: `${prefix} ${text}`, suppressHostLog: false };
|
|
691
692
|
}
|
|
692
|
-
async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100) {
|
|
693
|
-
const deadline = Date.now() + timeoutMs;
|
|
694
|
-
while (Date.now() < deadline) {
|
|
695
|
-
const ready = Boolean(await page.evaluate(expression));
|
|
696
|
-
if (ready)
|
|
697
|
-
return true;
|
|
698
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
699
|
-
}
|
|
700
|
-
return Boolean(await page.evaluate(expression));
|
|
701
|
-
}
|
|
702
693
|
const HF_READY_DIAGNOSTIC_EXPR = `(function() {
|
|
703
694
|
var hf = window.__hf;
|
|
704
695
|
var player = window.__player;
|
|
@@ -799,7 +790,14 @@ async function pollHfReady(page, timeoutMs, intervalMs = 100) {
|
|
|
799
790
|
` State: __hf=${diag.hasHf}, seek=${diag.hasSeek}, player=${diag.hasPlayer}, ` +
|
|
800
791
|
`renderReady=${diag.renderReady}, duration=${diag.duration}`);
|
|
801
792
|
}
|
|
802
|
-
async function pollSubCompositionTimelines(page, timeoutMs, intervalMs = 150
|
|
793
|
+
export async function pollSubCompositionTimelines(page, timeoutMs, intervalMs = 150,
|
|
794
|
+
// Fail-fast hook: when a SCRIPT resource failed to load (404 / request
|
|
795
|
+
// failure), the timeline registration it carried can never arrive — the
|
|
796
|
+
// full-timeout wait buys nothing (measured: a 705-render spike at the 45s
|
|
797
|
+
// setup bucket in 30 days of wild local renders, ~1% of renders, each also
|
|
798
|
+
// shipping silently-broken animations). Once failures are present the poll
|
|
799
|
+
// is cut to `scriptFailureGraceMs` from its start.
|
|
800
|
+
getScriptLoadFailures, scriptFailureGraceMs = 2_000) {
|
|
803
801
|
// Hosts may opt out of the timeline wait with `data-no-timeline` —
|
|
804
802
|
// compositions driven purely by CSS animations / rAF (the render-compat
|
|
805
803
|
// contract) never register window.__timelines[id], and without the opt-out
|
|
@@ -816,7 +814,28 @@ async function pollSubCompositionTimelines(page, timeoutMs, intervalMs = 150) {
|
|
|
816
814
|
}
|
|
817
815
|
return true;
|
|
818
816
|
})()`;
|
|
819
|
-
const
|
|
817
|
+
const start = Date.now();
|
|
818
|
+
const deadline = start + timeoutMs;
|
|
819
|
+
let ready = false;
|
|
820
|
+
let scriptFailureBail = false;
|
|
821
|
+
for (;;) {
|
|
822
|
+
ready = Boolean(await page.evaluate(expression));
|
|
823
|
+
if (ready)
|
|
824
|
+
break;
|
|
825
|
+
const now = Date.now();
|
|
826
|
+
if (now >= deadline)
|
|
827
|
+
break;
|
|
828
|
+
const failures = getScriptLoadFailures?.() ?? [];
|
|
829
|
+
if (failures.length > 0 && now - start >= scriptFailureGraceMs) {
|
|
830
|
+
scriptFailureBail = true;
|
|
831
|
+
console.warn(`[FrameCapture] Sub-composition timeline wait cut short after ${now - start}ms: ` +
|
|
832
|
+
`script resource(s) failed to load (${failures.join(", ")}) — ` +
|
|
833
|
+
`the timeline registration they carry can never arrive. ` +
|
|
834
|
+
`Fix the script reference; the render proceeds without those animations.`);
|
|
835
|
+
break;
|
|
836
|
+
}
|
|
837
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
838
|
+
}
|
|
820
839
|
// Always force a timeline rebind once sub-composition timelines are
|
|
821
840
|
// confirmed present. The previous implementation only called rebind
|
|
822
841
|
// when the timeline count grew during the poll, which missed the case
|
|
@@ -830,23 +849,32 @@ async function pollSubCompositionTimelines(page, timeoutMs, intervalMs = 150) {
|
|
|
830
849
|
window.__hfForceTimelineRebind();
|
|
831
850
|
}
|
|
832
851
|
})()`);
|
|
852
|
+
return "ready";
|
|
833
853
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
854
|
+
// Enumerate the still-unregistered composition ids regardless of bail
|
|
855
|
+
// reason — a script-failure bail used to skip this entirely, so a render
|
|
856
|
+
// with multiple sub-compositions only named the failed script URL(s), not
|
|
857
|
+
// which composition(s) it was still waiting on (review).
|
|
858
|
+
const missing = await page.evaluate(`(function() {
|
|
859
|
+
var hosts = document.querySelectorAll("[data-composition-id]");
|
|
860
|
+
var timelines = window.__timelines || {};
|
|
861
|
+
var m = [];
|
|
862
|
+
for (var i = 0; i < hosts.length; i++) {
|
|
863
|
+
if (hosts[i].hasAttribute("data-no-timeline")) continue;
|
|
864
|
+
var id = hosts[i].getAttribute("data-composition-id");
|
|
865
|
+
if (id && !timelines[id]) m.push(id);
|
|
866
|
+
}
|
|
867
|
+
return m.join(", ");
|
|
868
|
+
})()`);
|
|
869
|
+
if (scriptFailureBail) {
|
|
870
|
+
console.warn(`[FrameCapture] Composition(s) still waiting on the failed script: ${missing}.`);
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
846
873
|
console.warn(`[FrameCapture] Sub-composition timelines not registered after ${timeoutMs}ms: ${missing}. ` +
|
|
847
874
|
`Compositions that load data asynchronously (e.g. fetch) must register window.__timelines[id] after setup completes. ` +
|
|
848
875
|
`Compositions intentionally driven without GSAP timelines (CSS animations / rAF) can mark the host with data-no-timeline to skip this wait.`);
|
|
849
876
|
}
|
|
877
|
+
return scriptFailureBail ? "script_failure" : "timeout";
|
|
850
878
|
}
|
|
851
879
|
async function pollVideosReady(page, skipIds, timeoutMs, intervalMs = 100) {
|
|
852
880
|
const check = async () => {
|
|
@@ -991,6 +1019,15 @@ async function waitForOptionalTailwindReady(page, timeoutMs) {
|
|
|
991
1019
|
throw new Error(`[FrameCapture] window.__tailwindReady not resolved after ${timeoutMs}ms. Tailwind browser runtime must finish before frame capture starts.`);
|
|
992
1020
|
}
|
|
993
1021
|
}
|
|
1022
|
+
// A 4xx `response` and a `requestfailed` can both fire for the same script
|
|
1023
|
+
// (e.g. a `requestfailed` following the 4xx), and repeated <script> tags for
|
|
1024
|
+
// the same URL duplicate it further — dedupe so the fail-fast warning names
|
|
1025
|
+
// each failed URL once.
|
|
1026
|
+
function recordScriptLoadFailure(session, url) {
|
|
1027
|
+
if (!session.scriptLoadFailures.includes(url)) {
|
|
1028
|
+
session.scriptLoadFailures.push(url);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
994
1031
|
// fallow-ignore-next-line unit-size
|
|
995
1032
|
export async function initializeSession(session) {
|
|
996
1033
|
const { page, serverUrl } = session;
|
|
@@ -1016,6 +1053,9 @@ export async function initializeSession(session) {
|
|
|
1016
1053
|
appendBrowserDiagnostic(session, text);
|
|
1017
1054
|
});
|
|
1018
1055
|
page.on("requestfailed", (request) => {
|
|
1056
|
+
if (request.resourceType() === "script") {
|
|
1057
|
+
recordScriptLoadFailure(session, request.url());
|
|
1058
|
+
}
|
|
1019
1059
|
appendBrowserDiagnostic(session, formatRequestFailureDiagnostic({
|
|
1020
1060
|
method: request.method(),
|
|
1021
1061
|
resourceType: request.resourceType(),
|
|
@@ -1028,6 +1068,9 @@ export async function initializeSession(session) {
|
|
|
1028
1068
|
if (status < 400)
|
|
1029
1069
|
return;
|
|
1030
1070
|
const request = response.request();
|
|
1071
|
+
if (request.resourceType() === "script") {
|
|
1072
|
+
recordScriptLoadFailure(session, response.url());
|
|
1073
|
+
}
|
|
1031
1074
|
appendBrowserDiagnostic(session, formatHttpErrorDiagnostic({
|
|
1032
1075
|
method: request.method(),
|
|
1033
1076
|
resourceType: request.resourceType(),
|
|
@@ -1077,8 +1120,8 @@ export async function initializeSession(session) {
|
|
|
1077
1120
|
const pageReadyTimeout = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG.playerReadyTimeout;
|
|
1078
1121
|
await pollHfReady(page, pageReadyTimeout);
|
|
1079
1122
|
logInitPhase("pollHfReady complete");
|
|
1080
|
-
await pollSubCompositionTimelines(page, pageReadyTimeout);
|
|
1081
|
-
logInitPhase(
|
|
1123
|
+
session.subTimelineWaitOutcome = await pollSubCompositionTimelines(page, pageReadyTimeout, undefined, () => session.scriptLoadFailures);
|
|
1124
|
+
logInitPhase(`pollSubCompositionTimelines complete (${session.subTimelineWaitOutcome})`);
|
|
1082
1125
|
await applyVideoMetadataHints(page, session.options.videoMetadataHints);
|
|
1083
1126
|
logInitPhase("applyVideoMetadataHints complete");
|
|
1084
1127
|
// Run independent readiness checks in parallel — videos, images, fonts,
|
|
@@ -1195,8 +1238,8 @@ export async function initializeSession(session) {
|
|
|
1195
1238
|
warmupState.running = false;
|
|
1196
1239
|
throw err;
|
|
1197
1240
|
}
|
|
1198
|
-
await pollSubCompositionTimelines(page, pageReadyTimeout);
|
|
1199
|
-
logInitPhase(
|
|
1241
|
+
session.subTimelineWaitOutcome = await pollSubCompositionTimelines(page, pageReadyTimeout, undefined, () => session.scriptLoadFailures);
|
|
1242
|
+
logInitPhase(`pollSubCompositionTimelines complete (${session.subTimelineWaitOutcome})`);
|
|
1200
1243
|
await applyVideoMetadataHints(page, session.options.videoMetadataHints);
|
|
1201
1244
|
logInitPhase("applyVideoMetadataHints complete");
|
|
1202
1245
|
// Run independent readiness checks in parallel — videos, images, fonts,
|
|
@@ -1994,9 +2037,28 @@ export async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
1994
2037
|
// and skip the seek + drawElement + encode entirely. Same predicate as the serial
|
|
1995
2038
|
// path; clip-cut frames are excluded from staticFrames so they always capture.
|
|
1996
2039
|
if (session.staticFrames?.has(frameIndex) && session.lastEncodeResult) {
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2040
|
+
// Reuse is valid only when EVERY frame in (lastEncodeResultFrame, i] is
|
|
2041
|
+
// predicted-static — then all of them (and the reused buffer) share the
|
|
2042
|
+
// same pixels. Sequential capture reduces to has(i) (gap = {i}); the
|
|
2043
|
+
// interleaved parallel stride makes the gap N frames wide.
|
|
2044
|
+
const lastIdx = session.lastEncodeResultFrame ?? frameIndex - 1;
|
|
2045
|
+
let gapStatic = true;
|
|
2046
|
+
for (let j = lastIdx + 1; j <= frameIndex; j++) {
|
|
2047
|
+
if (!session.staticFrames.has(j)) {
|
|
2048
|
+
gapStatic = false;
|
|
2049
|
+
break;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
if (gapStatic) {
|
|
2053
|
+
session.staticDedupCount = (session.staticDedupCount ?? 0) + 1;
|
|
2054
|
+
session.capturePerf.frames += 1;
|
|
2055
|
+
// Advance the watermark on reuse too, not just on real captures — the
|
|
2056
|
+
// gap-check above starts from lastEncodeResultFrame, so leaving it
|
|
2057
|
+
// pinned to the last REAL capture makes every consecutive reuse rescan
|
|
2058
|
+
// an ever-widening window instead of just the one new frame (review).
|
|
2059
|
+
session.lastEncodeResultFrame = frameIndex;
|
|
2060
|
+
return { encodeResult: session.lastEncodeResult, captureTimeMs: Date.now() - startTime };
|
|
2061
|
+
}
|
|
2000
2062
|
}
|
|
2001
2063
|
try {
|
|
2002
2064
|
const { quantizedTime, seekMs, beforeCaptureMs } = await prepareFrameForCapture(session, frameIndex, time);
|
|
@@ -2023,8 +2085,10 @@ export async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
2023
2085
|
session.capturePerf.frameMs.push(boundaryMs);
|
|
2024
2086
|
}
|
|
2025
2087
|
const boundaryResult = Promise.resolve(buffer);
|
|
2026
|
-
if (session.staticFrames)
|
|
2088
|
+
if (session.staticFrames) {
|
|
2027
2089
|
session.lastEncodeResult = boundaryResult;
|
|
2090
|
+
session.lastEncodeResultFrame = frameIndex;
|
|
2091
|
+
}
|
|
2028
2092
|
return { encodeResult: boundaryResult, captureTimeMs: Date.now() - startTime };
|
|
2029
2093
|
}
|
|
2030
2094
|
// Worker-encode is gated to the macOS GPU path (beginFrameTimeTicks === 0,
|
|
@@ -2041,8 +2105,10 @@ export async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
2041
2105
|
session.capturePerf.totalMs += captureTimeMs;
|
|
2042
2106
|
session.capturePerf.frameMs.push(captureTimeMs);
|
|
2043
2107
|
// Task B: retain this encode result so a following static frame can reuse it.
|
|
2044
|
-
if (session.staticFrames)
|
|
2108
|
+
if (session.staticFrames) {
|
|
2045
2109
|
session.lastEncodeResult = encodeResult;
|
|
2110
|
+
session.lastEncodeResultFrame = frameIndex;
|
|
2111
|
+
}
|
|
2046
2112
|
return { encodeResult, captureTimeMs };
|
|
2047
2113
|
}
|
|
2048
2114
|
catch (captureError) {
|
|
@@ -2398,6 +2464,7 @@ export function getCapturePerfSummary(session) {
|
|
|
2398
2464
|
avgBeforeCaptureMs: Math.round(session.capturePerf.beforeCaptureMs / frames),
|
|
2399
2465
|
avgScreenshotMs: Math.round(session.capturePerf.screenshotMs / frames),
|
|
2400
2466
|
p50TotalMs: medianOf(session.capturePerf.frameMs),
|
|
2467
|
+
subTimelineWaitOutcome: session.subTimelineWaitOutcome,
|
|
2401
2468
|
staticDedupReused: session.staticDedupCount ?? 0,
|
|
2402
2469
|
staticDedupEnabled: session.staticDedupEnabled ?? false,
|
|
2403
2470
|
// armed ⟺ a non-empty static set survived verification; predicted === its size.
|