@hyperframes/engine 0.4.0 → 0.4.2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserManager.d.ts","sourceRoot":"","sources":["../../src/services/browserManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,gBAAgB,CAAC;AAI7D,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAmBjE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,GACjD,MAAM,GAAG,SAAS,CA0BpB;AAOD,eAAO,MAAM,mBAAmB,SAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"browserManager.d.ts","sourceRoot":"","sources":["../../src/services/browserManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,gBAAgB,CAAC;AAI7D,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAmBjE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,GACjD,MAAM,GAAG,SAAS,CA0BpB;AAOD,eAAO,MAAM,mBAAmB,SAAmC,CAAC;AA6DpE,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,CAAC,EAAE,OAAO,CACd,IAAI,CACF,YAAY,EACZ,gBAAgB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,YAAY,GAAG,iBAAiB,CAC9F,CACF,GACA,OAAO,CAAC,eAAe,CAAC,CAoE1B;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC,GACxD,OAAO,CAAC,IAAI,CAAC,CAef;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,EAC/B,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,YAAY,CAAC,CAAC,GAChE,MAAM,EAAE,CA4DV"}
|
|
@@ -64,6 +64,62 @@ let pooledBrowserRefCount = 0;
|
|
|
64
64
|
let pooledCaptureMode = "screenshot";
|
|
65
65
|
// Preserve the producer-era export so re-export shims keep the same public API.
|
|
66
66
|
export const ENABLE_BROWSER_POOL = DEFAULT_CONFIG.enableBrowserPool;
|
|
67
|
+
// Flags only meaningful when Chrome's compositor is driven by
|
|
68
|
+
// HeadlessExperimental.beginFrame. If we fall back to screenshot mode they
|
|
69
|
+
// must be stripped — `--enable-begin-frame-control` in particular makes the
|
|
70
|
+
// compositor wait for frames we'll never send, producing blank screenshots.
|
|
71
|
+
const BEGINFRAME_ONLY_FLAGS = new Set([
|
|
72
|
+
"--deterministic-mode",
|
|
73
|
+
"--enable-begin-frame-control",
|
|
74
|
+
"--disable-new-content-rendering-timeout",
|
|
75
|
+
"--run-all-compositor-stages-before-draw",
|
|
76
|
+
"--disable-threaded-animation",
|
|
77
|
+
"--disable-threaded-scrolling",
|
|
78
|
+
"--disable-checker-imaging",
|
|
79
|
+
"--disable-image-animation-resync",
|
|
80
|
+
"--enable-surface-synchronization",
|
|
81
|
+
]);
|
|
82
|
+
function stripBeginFrameFlags(args) {
|
|
83
|
+
return args.filter((a) => !BEGINFRAME_ONLY_FLAGS.has(a));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Probe whether the browser still speaks HeadlessExperimental.beginFrame.
|
|
87
|
+
*
|
|
88
|
+
* Recent chrome-headless-shell builds (observed on 147) expose the domain
|
|
89
|
+
* well enough that HeadlessExperimental.enable succeeds but drop the
|
|
90
|
+
* beginFrame method itself — the capture loop then dies on first frame with
|
|
91
|
+
* `'HeadlessExperimental.beginFrame' wasn't found`. So we probe BOTH: enable
|
|
92
|
+
* + one cheap beginFrame raced against a 2s timeout. In beginframe-control
|
|
93
|
+
* mode the command completes as soon as the compositor acks, so a real
|
|
94
|
+
* supported browser returns well under the timeout.
|
|
95
|
+
*
|
|
96
|
+
* Any failure (method missing, timeout, protocol error) is treated as
|
|
97
|
+
* unsupported. Real errors after launch would surface in the warmup loop and
|
|
98
|
+
* fall out through the caller's try/catch.
|
|
99
|
+
*/
|
|
100
|
+
async function probeBeginFrameSupport(browser) {
|
|
101
|
+
let page;
|
|
102
|
+
try {
|
|
103
|
+
page = await browser.newPage();
|
|
104
|
+
const client = await page.createCDPSession();
|
|
105
|
+
await client.send("HeadlessExperimental.enable");
|
|
106
|
+
const beginFrame = client.send("HeadlessExperimental.beginFrame", {
|
|
107
|
+
frameTimeTicks: 0,
|
|
108
|
+
interval: 33,
|
|
109
|
+
noDisplayUpdates: true,
|
|
110
|
+
});
|
|
111
|
+
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error("beginFrame probe timeout")), 2000));
|
|
112
|
+
await Promise.race([beginFrame, timeout]);
|
|
113
|
+
await client.detach().catch(() => { });
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
await page?.close().catch(() => { });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
67
123
|
export async function acquireBrowser(chromeArgs, config) {
|
|
68
124
|
const enablePool = config?.enableBrowserPool ?? DEFAULT_CONFIG.enableBrowserPool;
|
|
69
125
|
if (enablePool && pooledBrowser) {
|
|
@@ -87,14 +143,37 @@ export async function acquireBrowser(chromeArgs, config) {
|
|
|
87
143
|
executablePath = headlessShell ?? undefined;
|
|
88
144
|
}
|
|
89
145
|
const ppt = await getPuppeteer();
|
|
90
|
-
const
|
|
146
|
+
const browserTimeout = config?.browserTimeout ?? DEFAULT_CONFIG.browserTimeout;
|
|
147
|
+
const protocolTimeout = config?.protocolTimeout ?? DEFAULT_CONFIG.protocolTimeout;
|
|
148
|
+
let browser = await ppt.launch({
|
|
91
149
|
headless: true,
|
|
92
150
|
args: chromeArgs,
|
|
93
151
|
defaultViewport: null,
|
|
94
152
|
executablePath,
|
|
95
|
-
timeout:
|
|
96
|
-
protocolTimeout
|
|
153
|
+
timeout: browserTimeout,
|
|
154
|
+
protocolTimeout,
|
|
97
155
|
});
|
|
156
|
+
// Probe HeadlessExperimental.beginFrame — recent chrome-headless-shell
|
|
157
|
+
// builds (observed on 147) dropped the method while keeping the flags
|
|
158
|
+
// valid, so `--enable-begin-frame-control` leaves the compositor waiting
|
|
159
|
+
// for beginFrames the engine can no longer send. Auto-fall back to
|
|
160
|
+
// screenshot mode with the appropriate flags.
|
|
161
|
+
if (captureMode === "beginframe") {
|
|
162
|
+
const supported = await probeBeginFrameSupport(browser).catch(() => true);
|
|
163
|
+
if (!supported) {
|
|
164
|
+
await browser.close().catch(() => { });
|
|
165
|
+
console.warn("[BrowserManager] HeadlessExperimental.beginFrame unavailable in this Chromium build; falling back to screenshot mode.");
|
|
166
|
+
captureMode = "screenshot";
|
|
167
|
+
browser = await ppt.launch({
|
|
168
|
+
headless: true,
|
|
169
|
+
args: stripBeginFrameFlags(chromeArgs),
|
|
170
|
+
defaultViewport: null,
|
|
171
|
+
executablePath,
|
|
172
|
+
timeout: browserTimeout,
|
|
173
|
+
protocolTimeout,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
98
177
|
if (enablePool) {
|
|
99
178
|
pooledBrowser = browser;
|
|
100
179
|
pooledBrowserRefCount = 1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserManager.js","sourceRoot":"","sources":["../../src/services/browserManager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"browserManager.js","sourceRoot":"","sources":["../../src/services/browserManager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Seekable web page to video rendering engine (Puppeteer + FFmpeg)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"linkedom": "^0.18.12",
|
|
20
20
|
"puppeteer": "^24.0.0",
|
|
21
21
|
"puppeteer-core": "^24.39.1",
|
|
22
|
-
"@hyperframes/core": "^0.4.
|
|
22
|
+
"@hyperframes/core": "^0.4.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^22.10.1",
|
|
@@ -77,6 +77,65 @@ let pooledCaptureMode: CaptureMode = "screenshot";
|
|
|
77
77
|
// Preserve the producer-era export so re-export shims keep the same public API.
|
|
78
78
|
export const ENABLE_BROWSER_POOL = DEFAULT_CONFIG.enableBrowserPool;
|
|
79
79
|
|
|
80
|
+
// Flags only meaningful when Chrome's compositor is driven by
|
|
81
|
+
// HeadlessExperimental.beginFrame. If we fall back to screenshot mode they
|
|
82
|
+
// must be stripped — `--enable-begin-frame-control` in particular makes the
|
|
83
|
+
// compositor wait for frames we'll never send, producing blank screenshots.
|
|
84
|
+
const BEGINFRAME_ONLY_FLAGS = new Set([
|
|
85
|
+
"--deterministic-mode",
|
|
86
|
+
"--enable-begin-frame-control",
|
|
87
|
+
"--disable-new-content-rendering-timeout",
|
|
88
|
+
"--run-all-compositor-stages-before-draw",
|
|
89
|
+
"--disable-threaded-animation",
|
|
90
|
+
"--disable-threaded-scrolling",
|
|
91
|
+
"--disable-checker-imaging",
|
|
92
|
+
"--disable-image-animation-resync",
|
|
93
|
+
"--enable-surface-synchronization",
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
function stripBeginFrameFlags(args: string[]): string[] {
|
|
97
|
+
return args.filter((a) => !BEGINFRAME_ONLY_FLAGS.has(a));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Probe whether the browser still speaks HeadlessExperimental.beginFrame.
|
|
102
|
+
*
|
|
103
|
+
* Recent chrome-headless-shell builds (observed on 147) expose the domain
|
|
104
|
+
* well enough that HeadlessExperimental.enable succeeds but drop the
|
|
105
|
+
* beginFrame method itself — the capture loop then dies on first frame with
|
|
106
|
+
* `'HeadlessExperimental.beginFrame' wasn't found`. So we probe BOTH: enable
|
|
107
|
+
* + one cheap beginFrame raced against a 2s timeout. In beginframe-control
|
|
108
|
+
* mode the command completes as soon as the compositor acks, so a real
|
|
109
|
+
* supported browser returns well under the timeout.
|
|
110
|
+
*
|
|
111
|
+
* Any failure (method missing, timeout, protocol error) is treated as
|
|
112
|
+
* unsupported. Real errors after launch would surface in the warmup loop and
|
|
113
|
+
* fall out through the caller's try/catch.
|
|
114
|
+
*/
|
|
115
|
+
async function probeBeginFrameSupport(browser: Browser): Promise<boolean> {
|
|
116
|
+
let page;
|
|
117
|
+
try {
|
|
118
|
+
page = await browser.newPage();
|
|
119
|
+
const client = await page.createCDPSession();
|
|
120
|
+
await client.send("HeadlessExperimental.enable");
|
|
121
|
+
const beginFrame = client.send("HeadlessExperimental.beginFrame", {
|
|
122
|
+
frameTimeTicks: 0,
|
|
123
|
+
interval: 33,
|
|
124
|
+
noDisplayUpdates: true,
|
|
125
|
+
});
|
|
126
|
+
const timeout = new Promise<never>((_, reject) =>
|
|
127
|
+
setTimeout(() => reject(new Error("beginFrame probe timeout")), 2000),
|
|
128
|
+
);
|
|
129
|
+
await Promise.race([beginFrame, timeout]);
|
|
130
|
+
await client.detach().catch(() => {});
|
|
131
|
+
return true;
|
|
132
|
+
} catch {
|
|
133
|
+
return false;
|
|
134
|
+
} finally {
|
|
135
|
+
await page?.close().catch(() => {});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
80
139
|
export async function acquireBrowser(
|
|
81
140
|
chromeArgs: string[],
|
|
82
141
|
config?: Partial<
|
|
@@ -112,14 +171,41 @@ export async function acquireBrowser(
|
|
|
112
171
|
}
|
|
113
172
|
|
|
114
173
|
const ppt = await getPuppeteer();
|
|
115
|
-
const
|
|
174
|
+
const browserTimeout = config?.browserTimeout ?? DEFAULT_CONFIG.browserTimeout;
|
|
175
|
+
const protocolTimeout = config?.protocolTimeout ?? DEFAULT_CONFIG.protocolTimeout;
|
|
176
|
+
let browser = await ppt.launch({
|
|
116
177
|
headless: true,
|
|
117
178
|
args: chromeArgs,
|
|
118
179
|
defaultViewport: null,
|
|
119
180
|
executablePath,
|
|
120
|
-
timeout:
|
|
121
|
-
protocolTimeout
|
|
181
|
+
timeout: browserTimeout,
|
|
182
|
+
protocolTimeout,
|
|
122
183
|
});
|
|
184
|
+
|
|
185
|
+
// Probe HeadlessExperimental.beginFrame — recent chrome-headless-shell
|
|
186
|
+
// builds (observed on 147) dropped the method while keeping the flags
|
|
187
|
+
// valid, so `--enable-begin-frame-control` leaves the compositor waiting
|
|
188
|
+
// for beginFrames the engine can no longer send. Auto-fall back to
|
|
189
|
+
// screenshot mode with the appropriate flags.
|
|
190
|
+
if (captureMode === "beginframe") {
|
|
191
|
+
const supported = await probeBeginFrameSupport(browser).catch(() => true);
|
|
192
|
+
if (!supported) {
|
|
193
|
+
await browser.close().catch(() => {});
|
|
194
|
+
console.warn(
|
|
195
|
+
"[BrowserManager] HeadlessExperimental.beginFrame unavailable in this Chromium build; falling back to screenshot mode.",
|
|
196
|
+
);
|
|
197
|
+
captureMode = "screenshot";
|
|
198
|
+
browser = await ppt.launch({
|
|
199
|
+
headless: true,
|
|
200
|
+
args: stripBeginFrameFlags(chromeArgs),
|
|
201
|
+
defaultViewport: null,
|
|
202
|
+
executablePath,
|
|
203
|
+
timeout: browserTimeout,
|
|
204
|
+
protocolTimeout,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
123
209
|
if (enablePool) {
|
|
124
210
|
pooledBrowser = browser;
|
|
125
211
|
pooledBrowserRefCount = 1;
|