@hyperframes/engine 0.4.6 → 0.4.8
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/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/services/browserManager.d.ts.map +1 -1
- package/dist/services/browserManager.js +6 -3
- package/dist/services/browserManager.js.map +1 -1
- package/dist/services/chunkEncoder.d.ts +14 -7
- package/dist/services/chunkEncoder.d.ts.map +1 -1
- package/dist/services/chunkEncoder.js +25 -9
- package/dist/services/chunkEncoder.js.map +1 -1
- package/dist/services/chunkEncoder.types.d.ts +4 -0
- package/dist/services/chunkEncoder.types.d.ts.map +1 -1
- package/dist/services/hdrCapture.d.ts +62 -0
- package/dist/services/hdrCapture.d.ts.map +1 -0
- package/dist/services/hdrCapture.js +259 -0
- package/dist/services/hdrCapture.js.map +1 -0
- package/dist/services/screenshotService.d.ts +115 -0
- package/dist/services/screenshotService.d.ts.map +1 -1
- package/dist/services/screenshotService.js +252 -19
- package/dist/services/screenshotService.js.map +1 -1
- package/dist/services/streamingEncoder.d.ts +18 -3
- package/dist/services/streamingEncoder.d.ts.map +1 -1
- package/dist/services/streamingEncoder.js +104 -50
- package/dist/services/streamingEncoder.js.map +1 -1
- package/dist/services/videoFrameExtractor.d.ts.map +1 -1
- package/dist/services/videoFrameExtractor.js +109 -18
- package/dist/services/videoFrameExtractor.js.map +1 -1
- package/dist/services/videoFrameInjector.d.ts +59 -0
- package/dist/services/videoFrameInjector.d.ts.map +1 -1
- package/dist/services/videoFrameInjector.js +290 -0
- package/dist/services/videoFrameInjector.js.map +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/alphaBlit.d.ts +105 -0
- package/dist/utils/alphaBlit.d.ts.map +1 -0
- package/dist/utils/alphaBlit.js +550 -0
- package/dist/utils/alphaBlit.js.map +1 -0
- package/dist/utils/ffprobe.d.ts +10 -0
- package/dist/utils/ffprobe.d.ts.map +1 -1
- package/dist/utils/ffprobe.js +7 -0
- package/dist/utils/ffprobe.js.map +1 -1
- package/dist/utils/hdr.d.ts +82 -0
- package/dist/utils/hdr.d.ts.map +1 -0
- package/dist/utils/hdr.js +87 -0
- package/dist/utils/hdr.js.map +1 -0
- package/dist/utils/layerCompositor.d.ts +36 -0
- package/dist/utils/layerCompositor.d.ts.map +1 -0
- package/dist/utils/layerCompositor.js +49 -0
- package/dist/utils/layerCompositor.js.map +1 -0
- package/dist/utils/shaderTransitions.d.ts +166 -0
- package/dist/utils/shaderTransitions.d.ts.map +1 -0
- package/dist/utils/shaderTransitions.js +894 -0
- package/dist/utils/shaderTransitions.js.map +1 -0
- package/package.json +3 -2
- package/src/config.ts +16 -0
- package/src/index.ts +61 -0
- package/src/services/browserManager.ts +6 -3
- package/src/services/chunkEncoder.test.ts +88 -0
- package/src/services/chunkEncoder.ts +35 -9
- package/src/services/chunkEncoder.types.ts +3 -0
- package/src/services/hdrCapture.test.ts +159 -0
- package/src/services/hdrCapture.ts +354 -0
- package/src/services/screenshotService.ts +271 -17
- package/src/services/streamingEncoder.test.ts +228 -0
- package/src/services/streamingEncoder.ts +153 -63
- package/src/services/videoFrameExtractor.ts +135 -31
- package/src/services/videoFrameInjector.ts +342 -0
- package/src/types.ts +34 -0
- package/src/utils/alphaBlit.test.ts +993 -0
- package/src/utils/alphaBlit.ts +643 -0
- package/src/utils/ffprobe.ts +22 -0
- package/src/utils/hdr.test.ts +191 -0
- package/src/utils/hdr.ts +137 -0
- package/src/utils/layerCompositor.test.ts +141 -0
- package/src/utils/layerCompositor.ts +58 -0
- package/src/utils/shaderTransitions.test.ts +674 -0
- package/src/utils/shaderTransitions.ts +1130 -0
- package/src/utils/uint16-alignment-audit.test.ts +125 -0
- package/tsconfig.json +2 -1
|
@@ -104,6 +104,212 @@ export async function pageScreenshotCapture(page, options) {
|
|
|
104
104
|
});
|
|
105
105
|
return Buffer.from(result.data, "base64");
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Capture a screenshot with transparent background (PNG + alpha channel).
|
|
109
|
+
*
|
|
110
|
+
* Used in the two-pass HDR compositing pipeline — captures DOM content
|
|
111
|
+
* (text, graphics, SDR overlays) with transparency where the background shows,
|
|
112
|
+
* so it can be overlaid on top of native HDR video frames in FFmpeg.
|
|
113
|
+
*
|
|
114
|
+
* Sets and restores the background color override on every call. For sessions
|
|
115
|
+
* that capture many frames, prefer calling initTransparentBackground() once
|
|
116
|
+
* at session init, then captureAlphaPng() per frame to avoid the 2× CDP
|
|
117
|
+
* round-trip overhead.
|
|
118
|
+
*/
|
|
119
|
+
export async function captureScreenshotWithAlpha(page, width, height) {
|
|
120
|
+
const client = await getCdpSession(page);
|
|
121
|
+
// Force transparent background so the screenshot has a real alpha channel
|
|
122
|
+
await client.send("Emulation.setDefaultBackgroundColorOverride", {
|
|
123
|
+
color: { r: 0, g: 0, b: 0, a: 0 },
|
|
124
|
+
});
|
|
125
|
+
try {
|
|
126
|
+
const result = await client.send("Page.captureScreenshot", {
|
|
127
|
+
format: "png",
|
|
128
|
+
fromSurface: true,
|
|
129
|
+
captureBeyondViewport: false,
|
|
130
|
+
optimizeForSpeed: false, // `true` uses a zero-alpha-aware fast path that crushes real alpha values — observed empirically, CDP docs don't spell it out
|
|
131
|
+
clip: { x: 0, y: 0, width, height, scale: 1 },
|
|
132
|
+
});
|
|
133
|
+
return Buffer.from(result.data, "base64");
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
// Restore opaque background even if captureScreenshot throws, otherwise
|
|
137
|
+
// subsequent opaque captures keep a transparent background.
|
|
138
|
+
await client.send("Emulation.setDefaultBackgroundColorOverride", {}).catch(() => { });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Set the page background to transparent once for a dedicated HDR DOM session.
|
|
143
|
+
*
|
|
144
|
+
* Call this once after session initialization. Then use captureAlphaPng() per
|
|
145
|
+
* frame instead of captureScreenshotWithAlpha() to skip the per-frame CDP
|
|
146
|
+
* background override round-trips.
|
|
147
|
+
*
|
|
148
|
+
* Only use on sessions that are exclusively dedicated to transparent capture
|
|
149
|
+
* (e.g., the HDR two-pass DOM layer session) — the background will stay
|
|
150
|
+
* transparent for the lifetime of the session.
|
|
151
|
+
*
|
|
152
|
+
* NOTE on the injected stylesheet: `Emulation.setDefaultBackgroundColorOverride`
|
|
153
|
+
* only replaces the *default* page background. Compositions almost always set
|
|
154
|
+
* `body { background: ... }` and `#root { background: ... }`, which paint over
|
|
155
|
+
* the override and ruin alpha capture for layered HDR compositing — the
|
|
156
|
+
* composition root's full-frame background paints across the entire viewport
|
|
157
|
+
* and wipes out HDR content captured beneath it.
|
|
158
|
+
*
|
|
159
|
+
* We force `html`, `body`, and any element marked as a composition root
|
|
160
|
+
* (`[data-composition-id]`) to transparent. In HDR layered compositing the HDR
|
|
161
|
+
* video itself is the backdrop, so DOM layers must only contribute their
|
|
162
|
+
* foreground UI pixels — never a page-spanning solid backdrop.
|
|
163
|
+
*/
|
|
164
|
+
export const TRANSPARENT_BG_STYLE_ID = "__hf_transparent_bg__";
|
|
165
|
+
export async function initTransparentBackground(page) {
|
|
166
|
+
const client = await getCdpSession(page);
|
|
167
|
+
await client.send("Emulation.setDefaultBackgroundColorOverride", {
|
|
168
|
+
color: { r: 0, g: 0, b: 0, a: 0 },
|
|
169
|
+
});
|
|
170
|
+
await page.evaluate((styleId) => {
|
|
171
|
+
if (document.getElementById(styleId))
|
|
172
|
+
return;
|
|
173
|
+
const style = document.createElement("style");
|
|
174
|
+
style.id = styleId;
|
|
175
|
+
style.textContent =
|
|
176
|
+
"html,body,[data-composition-id]{background:transparent !important;background-color:transparent !important;background-image:none !important;}";
|
|
177
|
+
document.head.appendChild(style);
|
|
178
|
+
}, TRANSPARENT_BG_STYLE_ID);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Capture a transparent-background PNG screenshot without setting the
|
|
182
|
+
* background color override. Requires initTransparentBackground() to have
|
|
183
|
+
* been called once on this session.
|
|
184
|
+
*
|
|
185
|
+
* Faster than captureScreenshotWithAlpha() for per-frame use in the HDR
|
|
186
|
+
* two-pass compositing loop.
|
|
187
|
+
*/
|
|
188
|
+
export async function captureAlphaPng(page, width, height) {
|
|
189
|
+
const client = await getCdpSession(page);
|
|
190
|
+
const result = await client.send("Page.captureScreenshot", {
|
|
191
|
+
format: "png",
|
|
192
|
+
fromSurface: true,
|
|
193
|
+
captureBeyondViewport: false,
|
|
194
|
+
optimizeForSpeed: false, // must be false to preserve alpha
|
|
195
|
+
clip: { x: 0, y: 0, width, height, scale: 1 },
|
|
196
|
+
});
|
|
197
|
+
return Buffer.from(result.data, "base64");
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Stylesheet ID used by applyDomLayerMask / removeDomLayerMask. Exposed so
|
|
201
|
+
* tests can assert presence/absence of the mask between captures.
|
|
202
|
+
*/
|
|
203
|
+
export const DOM_LAYER_MASK_STYLE_ID = "__hf_dom_layer_mask__";
|
|
204
|
+
/**
|
|
205
|
+
* Mask the DOM so a single layer screenshot captures ONLY the layer's pixels.
|
|
206
|
+
*
|
|
207
|
+
* The HDR layered compositor walks z-ordered layers and blits each one over a
|
|
208
|
+
* shared canvas. DOM layers are full-page screenshots — a naive screenshot
|
|
209
|
+
* captures every painted pixel on the page, which means root background +
|
|
210
|
+
* static overlays + sibling-scene content all overwrite previously composited
|
|
211
|
+
* HDR content beneath. The mask narrows each screenshot to the elements that
|
|
212
|
+
* actually belong to this layer.
|
|
213
|
+
*
|
|
214
|
+
* Strategy:
|
|
215
|
+
*
|
|
216
|
+
* 1. Inject a stylesheet that hides every body descendant
|
|
217
|
+
* (`body * { visibility: hidden !important }`) and re-shows the layer's
|
|
218
|
+
* elements (and their descendants and their injected `__render_frame_*`
|
|
219
|
+
* siblings) via `visibility: visible !important`. CSS `visibility: visible`
|
|
220
|
+
* on a descendant overrides an ancestor's `visibility: hidden`, so deep
|
|
221
|
+
* layer elements remain visible even though intermediate parents are
|
|
222
|
+
* hidden by the mass-hide rule.
|
|
223
|
+
* 2. Inline-hide each `extraHideId` (and its `__render_frame_*` sibling) with
|
|
224
|
+
* `visibility: hidden !important`. Inline `!important` beats stylesheet
|
|
225
|
+
* `!important`, so this overrides the show rule for elements that fall
|
|
226
|
+
* under a show selector but should NOT paint — typically other-layer
|
|
227
|
+
* elements that are descendants of a container layer (for example HDR
|
|
228
|
+
* videos and other-layer SDR videos are descendants of `#root` when we
|
|
229
|
+
* capture the root DOM layer).
|
|
230
|
+
*
|
|
231
|
+
* Only `visibility` is set on extraHideIds — never `opacity`. CSS opacity is
|
|
232
|
+
* multiplicative through the descendant chain and a descendant cannot escape
|
|
233
|
+
* an ancestor's `opacity: 0`. If `#root` is in `extraHideIds` and we set
|
|
234
|
+
* `opacity: 0` on it, every descendant — including `#vid-5-b` and its
|
|
235
|
+
* `__render_frame_vid-5-b__` IMG — becomes invisible even with
|
|
236
|
+
* `visibility: visible !important`. `visibility` does NOT have this problem:
|
|
237
|
+
* a descendant with `visibility: visible` overrides an ancestor's
|
|
238
|
+
* `visibility: hidden`.
|
|
239
|
+
*
|
|
240
|
+
* Layout is preserved (visibility doesn't trigger reflow), so border-radius
|
|
241
|
+
* clipping, overflow:hidden, and absolute positioning continue to apply to
|
|
242
|
+
* the visible layer elements. Opacity is also preserved — an ancestor at
|
|
243
|
+
* `opacity: 0` (e.g. an inactive scene during a transition) still
|
|
244
|
+
* propagates to its descendants, which is the desired behavior during
|
|
245
|
+
* cross-scene blends.
|
|
246
|
+
*
|
|
247
|
+
* Idempotent across calls: an existing mask stylesheet is removed before a
|
|
248
|
+
* new one is installed, so consecutive `applyDomLayerMask` invocations leave
|
|
249
|
+
* exactly one stylesheet attached.
|
|
250
|
+
*/
|
|
251
|
+
export async function applyDomLayerMask(page, showIds, extraHideIds) {
|
|
252
|
+
await page.evaluate((args) => {
|
|
253
|
+
const existing = document.getElementById(args.styleId);
|
|
254
|
+
if (existing)
|
|
255
|
+
existing.remove();
|
|
256
|
+
const showSelectors = [];
|
|
257
|
+
for (const id of args.show) {
|
|
258
|
+
const escaped = CSS.escape(id);
|
|
259
|
+
showSelectors.push(`#${escaped}`, `#${escaped} *`);
|
|
260
|
+
const renderEscaped = CSS.escape(`__render_frame_${id}__`);
|
|
261
|
+
showSelectors.push(`#${renderEscaped}`, `#${renderEscaped} *`);
|
|
262
|
+
}
|
|
263
|
+
const massHideRule = "body *{visibility:hidden !important;}";
|
|
264
|
+
const showRule = showSelectors.length === 0
|
|
265
|
+
? ""
|
|
266
|
+
: `${showSelectors.join(",")}{visibility:visible !important;}`;
|
|
267
|
+
const style = document.createElement("style");
|
|
268
|
+
style.id = args.styleId;
|
|
269
|
+
style.textContent = `${massHideRule}\n${showRule}`;
|
|
270
|
+
document.head.appendChild(style);
|
|
271
|
+
for (const id of args.hide) {
|
|
272
|
+
const el = document.getElementById(id);
|
|
273
|
+
if (el) {
|
|
274
|
+
el.style.setProperty("visibility", "hidden", "important");
|
|
275
|
+
}
|
|
276
|
+
const img = document.getElementById(`__render_frame_${id}__`);
|
|
277
|
+
if (img) {
|
|
278
|
+
img.style.setProperty("visibility", "hidden", "important");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}, { show: showIds, hide: extraHideIds, styleId: DOM_LAYER_MASK_STYLE_ID });
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Tear down the mask installed by applyDomLayerMask.
|
|
285
|
+
*
|
|
286
|
+
* Removes the mask stylesheet and clears the inline `visibility` properties
|
|
287
|
+
* set on `extraHideIds` (and their `__render_frame_*` siblings).
|
|
288
|
+
*
|
|
289
|
+
* IMPORTANT: We do NOT strip inline `opacity` here. applyDomLayerMask only
|
|
290
|
+
* ever sets `visibility` (never `opacity`), so any inline opacity present on
|
|
291
|
+
* a wrapper was put there by user animation code (typically GSAP) and must
|
|
292
|
+
* survive across per-layer captures. GSAP's seek with suppress-events does
|
|
293
|
+
* not re-apply tweens when the timeline is already at the target time, so if
|
|
294
|
+
* we strip opacity here and then seek to the same time for the next layer,
|
|
295
|
+
* GSAP won't put it back and the wrapper will render fully opaque.
|
|
296
|
+
*/
|
|
297
|
+
export async function removeDomLayerMask(page, extraHideIds) {
|
|
298
|
+
await page.evaluate((args) => {
|
|
299
|
+
const style = document.getElementById(args.styleId);
|
|
300
|
+
if (style)
|
|
301
|
+
style.remove();
|
|
302
|
+
for (const id of args.hide) {
|
|
303
|
+
const el = document.getElementById(id);
|
|
304
|
+
if (el) {
|
|
305
|
+
el.style.removeProperty("visibility");
|
|
306
|
+
}
|
|
307
|
+
const img = document.getElementById(`__render_frame_${id}__`);
|
|
308
|
+
if (img)
|
|
309
|
+
img.style.removeProperty("visibility");
|
|
310
|
+
}
|
|
311
|
+
}, { hide: extraHideIds, styleId: DOM_LAYER_MASK_STYLE_ID });
|
|
312
|
+
}
|
|
107
313
|
export async function injectVideoFramesBatch(page, updates) {
|
|
108
314
|
if (updates.length === 0)
|
|
109
315
|
return;
|
|
@@ -116,6 +322,16 @@ export async function injectVideoFramesBatch(page, updates) {
|
|
|
116
322
|
let img = video.nextElementSibling;
|
|
117
323
|
const isNewImage = !img || !img.classList.contains("__render_frame__");
|
|
118
324
|
const computedStyle = window.getComputedStyle(video);
|
|
325
|
+
// GSAP seeks re-apply tween values during an active tween, but do not
|
|
326
|
+
// re-apply tweens that have already completed. After an opacity fade-in
|
|
327
|
+
// finishes, GSAP's last set value is overwritten on subsequent frames
|
|
328
|
+
// by the `opacity: 0 !important` we apply at the bottom of this
|
|
329
|
+
// function to hide the native <video>. That leaves `computedOpacity`
|
|
330
|
+
// stuck at 0 even though the user's intent is opacity 1 (the tween's
|
|
331
|
+
// end state). The `|| 1` fallback treats computedOpacity === 0 as a
|
|
332
|
+
// hidden-native-video artifact and recovers opacity 1, matching the
|
|
333
|
+
// final on-screen state for the vast majority of compositions.
|
|
334
|
+
// For active tweens in the [0,1] exclusive range this is a no-op.
|
|
119
335
|
const computedOpacity = parseFloat(computedStyle.opacity) || 1;
|
|
120
336
|
const sourceIsStatic = !computedStyle.position || computedStyle.position === "static";
|
|
121
337
|
if (isNewImage) {
|
|
@@ -127,17 +343,11 @@ export async function injectVideoFramesBatch(page, updates) {
|
|
|
127
343
|
}
|
|
128
344
|
if (!img)
|
|
129
345
|
continue;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
img.style.left = computedStyle.left;
|
|
136
|
-
img.style.right = computedStyle.right;
|
|
137
|
-
img.style.bottom = computedStyle.bottom;
|
|
138
|
-
img.style.inset = computedStyle.inset;
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
346
|
+
// Always use absolute positioning so the <img> overlays the <video>
|
|
347
|
+
// instead of flowing below it. With position:relative, both elements
|
|
348
|
+
// stack vertically — the <img> lands below the video and gets clipped
|
|
349
|
+
// by any overflow:hidden ancestor (e.g., border-radius wrappers).
|
|
350
|
+
{
|
|
141
351
|
const videoRect = video.getBoundingClientRect();
|
|
142
352
|
const offsetLeft = Number.isFinite(video.offsetLeft) ? video.offsetLeft : 0;
|
|
143
353
|
const offsetTop = Number.isFinite(video.offsetTop) ? video.offsetTop : 0;
|
|
@@ -156,6 +366,15 @@ export async function injectVideoFramesBatch(page, updates) {
|
|
|
156
366
|
img.style.objectPosition = computedStyle.objectPosition;
|
|
157
367
|
img.style.zIndex = computedStyle.zIndex;
|
|
158
368
|
for (const property of visualProperties) {
|
|
369
|
+
// Opacity is handled explicitly via `computedOpacity` below — copying
|
|
370
|
+
// via the generic loop would race against the opacity:0 hide applied
|
|
371
|
+
// to the <video> at the end of this function. GSAP may animate
|
|
372
|
+
// opacity either on a wrapper (the <img> inherits via the stacking
|
|
373
|
+
// context) or directly on the <video> (we must copy it to the <img>
|
|
374
|
+
// since they are siblings). Reading computedStyle.opacity before
|
|
375
|
+
// hiding the <video> handles both cases correctly.
|
|
376
|
+
if (property === "opacity")
|
|
377
|
+
continue;
|
|
159
378
|
if (sourceIsStatic &&
|
|
160
379
|
(property === "top" ||
|
|
161
380
|
property === "left" ||
|
|
@@ -191,15 +410,29 @@ export async function syncVideoFrameVisibility(page, activeVideoIds) {
|
|
|
191
410
|
const active = new Set(ids);
|
|
192
411
|
const videos = Array.from(document.querySelectorAll("video[data-start]"));
|
|
193
412
|
for (const video of videos) {
|
|
194
|
-
if (active.has(video.id))
|
|
195
|
-
continue;
|
|
196
|
-
video.style.removeProperty("display");
|
|
197
|
-
video.style.setProperty("visibility", "hidden", "important");
|
|
198
|
-
video.style.setProperty("opacity", "0", "important");
|
|
199
|
-
video.style.setProperty("pointer-events", "none", "important");
|
|
200
413
|
const img = video.nextElementSibling;
|
|
201
|
-
|
|
202
|
-
|
|
414
|
+
const hasImg = img && img.classList.contains("__render_frame__");
|
|
415
|
+
if (active.has(video.id)) {
|
|
416
|
+
// Active video: show injected <img>, hide native <video>.
|
|
417
|
+
// Do NOT clobber inline opacity here — GSAP-controlled opacity must
|
|
418
|
+
// survive until injectVideoFramesBatch reads it via getComputedStyle.
|
|
419
|
+
// visibility:hidden alone hides the native element without affecting
|
|
420
|
+
// its computed opacity.
|
|
421
|
+
video.style.setProperty("visibility", "hidden", "important");
|
|
422
|
+
video.style.setProperty("pointer-events", "none", "important");
|
|
423
|
+
if (hasImg) {
|
|
424
|
+
img.style.visibility = "visible";
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
// Inactive video: hide both
|
|
429
|
+
video.style.removeProperty("display");
|
|
430
|
+
video.style.setProperty("visibility", "hidden", "important");
|
|
431
|
+
video.style.setProperty("opacity", "0", "important");
|
|
432
|
+
video.style.setProperty("pointer-events", "none", "important");
|
|
433
|
+
if (hasImg) {
|
|
434
|
+
img.style.visibility = "hidden";
|
|
435
|
+
}
|
|
203
436
|
}
|
|
204
437
|
}
|
|
205
438
|
}, activeVideoIds);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshotService.js","sourceRoot":"","sources":["../../src/services/screenshotService.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"screenshotService.js","sourceRoot":"","sources":["../../src/services/screenshotService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Streaming Encoder Service
|
|
3
3
|
*
|
|
4
|
-
* Pipes frame screenshot buffers directly to FFmpeg's stdin
|
|
5
|
-
* them to disk and reading them back in a separate encode
|
|
6
|
-
* Remotion
|
|
4
|
+
* Pipes frame screenshot buffers directly to FFmpeg's stdin via `-f image2pipe`
|
|
5
|
+
* instead of writing them to disk and reading them back in a separate encode
|
|
6
|
+
* stage. Inspired by Remotion's approach to browser-based video rendering.
|
|
7
7
|
*
|
|
8
8
|
* Two building blocks:
|
|
9
9
|
* 1. Frame reorder buffer – ensures out-of-order parallel workers feed
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* 2. Streaming FFmpeg encoder – spawns FFmpeg with `-f image2pipe` and
|
|
12
12
|
* exposes a `writeFrame(buffer)` + `close()` API.
|
|
13
13
|
*/
|
|
14
|
+
import { type GpuEncoder } from "../utils/gpuEncoder.js";
|
|
14
15
|
import { type EngineConfig } from "../config.js";
|
|
15
16
|
export type { EncoderOptions } from "./chunkEncoder.types.js";
|
|
16
17
|
export interface FrameReorderBuffer {
|
|
@@ -30,6 +31,11 @@ export interface StreamingEncoderOptions {
|
|
|
30
31
|
pixelFormat?: string;
|
|
31
32
|
useGpu?: boolean;
|
|
32
33
|
imageFormat?: "jpeg" | "png";
|
|
34
|
+
hdr?: {
|
|
35
|
+
transfer: import("../utils/hdr.js").HdrTransfer;
|
|
36
|
+
};
|
|
37
|
+
/** When set, use rawvideo input instead of image2pipe. For HDR PQ-encoded frames. */
|
|
38
|
+
rawInputFormat?: "rgb48le";
|
|
33
39
|
}
|
|
34
40
|
export interface StreamingEncoderResult {
|
|
35
41
|
success: boolean;
|
|
@@ -42,6 +48,15 @@ export interface StreamingEncoder {
|
|
|
42
48
|
close: () => Promise<StreamingEncoderResult>;
|
|
43
49
|
getExitStatus: () => "running" | "success" | "error";
|
|
44
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Build FFmpeg args for streaming (image2pipe) input.
|
|
53
|
+
* Reuses the same codec/quality/GPU logic as chunkEncoder's buildEncoderArgs
|
|
54
|
+
* but with `-f image2pipe` instead of `-i <pattern>`.
|
|
55
|
+
*
|
|
56
|
+
* Exported so unit tests can assert on the constructed CLI without spawning
|
|
57
|
+
* FFmpeg — see streamingEncoder.test.ts.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildStreamingArgs(options: StreamingEncoderOptions, outputPath: string, gpuEncoder?: GpuEncoder): string[];
|
|
45
60
|
/**
|
|
46
61
|
* Spawn a streaming FFmpeg encoder that accepts frame buffers on stdin.
|
|
47
62
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamingEncoder.d.ts","sourceRoot":"","sources":["../../src/services/streamingEncoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"streamingEncoder.d.ts","sourceRoot":"","sources":["../../src/services/streamingEncoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAAE,KAAK,UAAU,EAA0C,MAAM,wBAAwB,CAAC;AAGjG,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAc9D,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CA4CjG;AAMD,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7B,GAAG,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,iBAAiB,EAAE,WAAW,CAAA;KAAE,CAAC;IAC1D,qFAAqF;IACrF,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,KAAK,EAAE,MAAM,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC7C,aAAa,EAAE,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;CACtD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,UAAiB,GAC5B,MAAM,EAAE,CAgLV;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,uBAAuB,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,wBAAwB,CAAC,CAAC,GAC7D,OAAO,CAAC,gBAAgB,CAAC,CAyH3B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Streaming Encoder Service
|
|
3
3
|
*
|
|
4
|
-
* Pipes frame screenshot buffers directly to FFmpeg's stdin
|
|
5
|
-
* them to disk and reading them back in a separate encode
|
|
6
|
-
* Remotion
|
|
4
|
+
* Pipes frame screenshot buffers directly to FFmpeg's stdin via `-f image2pipe`
|
|
5
|
+
* instead of writing them to disk and reading them back in a separate encode
|
|
6
|
+
* stage. Inspired by Remotion's approach to browser-based video rendering.
|
|
7
7
|
*
|
|
8
8
|
* Two building blocks:
|
|
9
9
|
* 1. Frame reorder buffer – ensures out-of-order parallel workers feed
|
|
@@ -15,54 +15,78 @@ import { spawn } from "child_process";
|
|
|
15
15
|
import { existsSync, mkdirSync, statSync } from "fs";
|
|
16
16
|
import { dirname } from "path";
|
|
17
17
|
import { getCachedGpuEncoder, getGpuEncoderName } from "../utils/gpuEncoder.js";
|
|
18
|
+
import { getHdrEncoderColorParams } from "../utils/hdr.js";
|
|
18
19
|
import { DEFAULT_CONFIG } from "../config.js";
|
|
19
20
|
export function createFrameReorderBuffer(startFrame, endFrame) {
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
let cursor = startFrame;
|
|
22
|
+
const pending = new Map();
|
|
23
|
+
const enqueueAt = (frame, resolve) => {
|
|
24
|
+
const list = pending.get(frame);
|
|
25
|
+
if (list === undefined) {
|
|
26
|
+
pending.set(frame, [resolve]);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
list.push(resolve);
|
|
28
30
|
}
|
|
29
31
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
resolveWaiters();
|
|
38
|
-
},
|
|
39
|
-
waitForAllDone: () => new Promise((resolve) => {
|
|
40
|
-
waiters.push({ frame: endFrame, resolve });
|
|
41
|
-
resolveWaiters();
|
|
42
|
-
}),
|
|
32
|
+
const flushAt = (frame) => {
|
|
33
|
+
const list = pending.get(frame);
|
|
34
|
+
if (list === undefined)
|
|
35
|
+
return;
|
|
36
|
+
pending.delete(frame);
|
|
37
|
+
for (const resolve of list)
|
|
38
|
+
resolve();
|
|
43
39
|
};
|
|
40
|
+
const waitForFrame = (frame) => new Promise((resolve) => {
|
|
41
|
+
if (frame === cursor) {
|
|
42
|
+
resolve();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
enqueueAt(frame, resolve);
|
|
46
|
+
});
|
|
47
|
+
const advanceTo = (frame) => {
|
|
48
|
+
cursor = frame;
|
|
49
|
+
flushAt(frame);
|
|
50
|
+
};
|
|
51
|
+
const waitForAllDone = () => new Promise((resolve) => {
|
|
52
|
+
if (cursor >= endFrame) {
|
|
53
|
+
resolve();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
enqueueAt(endFrame, resolve);
|
|
57
|
+
});
|
|
58
|
+
return { waitForFrame, advanceTo, waitForAllDone };
|
|
44
59
|
}
|
|
45
60
|
/**
|
|
46
61
|
* Build FFmpeg args for streaming (image2pipe) input.
|
|
47
62
|
* Reuses the same codec/quality/GPU logic as chunkEncoder's buildEncoderArgs
|
|
48
63
|
* but with `-f image2pipe` instead of `-i <pattern>`.
|
|
64
|
+
*
|
|
65
|
+
* Exported so unit tests can assert on the constructed CLI without spawning
|
|
66
|
+
* FFmpeg — see streamingEncoder.test.ts.
|
|
49
67
|
*/
|
|
50
|
-
function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
68
|
+
export function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
51
69
|
const { fps, codec = "h264", preset = "medium", quality = 23, bitrate, pixelFormat = "yuv420p", useGpu = false, imageFormat = "jpeg", } = options;
|
|
52
70
|
// Input args: pipe from stdin
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
const args = [];
|
|
72
|
+
if (options.rawInputFormat) {
|
|
73
|
+
// Raw pixel input (HLG/PQ-encoded rgb48le from FFmpeg extraction).
|
|
74
|
+
// Tag the input with the correct color space so FFmpeg uses the right
|
|
75
|
+
// YUV matrix when converting rgb48le → yuv420p10le for encoding.
|
|
76
|
+
// Without these tags FFmpeg assumes bt709 and applies the wrong matrix.
|
|
77
|
+
const hdrTransfer = options.hdr?.transfer;
|
|
78
|
+
const inputColorTrc = hdrTransfer === "pq" ? "smpte2084" : hdrTransfer === "hlg" ? "arib-std-b67" : undefined;
|
|
79
|
+
args.push("-f", "rawvideo", "-pix_fmt", options.rawInputFormat, "-s", `${options.width}x${options.height}`, "-framerate", String(fps));
|
|
80
|
+
if (inputColorTrc) {
|
|
81
|
+
args.push("-color_primaries", "bt2020", "-color_trc", inputColorTrc, "-colorspace", "bt2020nc");
|
|
82
|
+
}
|
|
83
|
+
args.push("-i", "-");
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const inputCodec = imageFormat === "png" ? "png" : "mjpeg";
|
|
87
|
+
args.push("-f", "image2pipe", "-vcodec", inputCodec, "-framerate", String(fps), "-i", "-");
|
|
88
|
+
}
|
|
89
|
+
args.push("-r", String(fps));
|
|
66
90
|
const shouldUseGpu = useGpu && gpuEncoder !== null;
|
|
67
91
|
if (codec === "h264" || codec === "h265") {
|
|
68
92
|
if (shouldUseGpu) {
|
|
@@ -109,17 +133,25 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
109
133
|
args.push("-b:v", bitrate);
|
|
110
134
|
else
|
|
111
135
|
args.push("-crf", String(quality));
|
|
112
|
-
// Encoder-specific params: anti-banding +
|
|
113
|
-
//
|
|
114
|
-
//
|
|
136
|
+
// Encoder-specific params: anti-banding + color space tagging.
|
|
137
|
+
// For HDR, getHdrEncoderColorParams also emits the SMPTE ST 2086
|
|
138
|
+
// mastering-display and CTA-861.3 MaxCLL/MaxFALL SEI messages —
|
|
139
|
+
// without them, players (Apple, YouTube, HDR TVs) treat the file
|
|
140
|
+
// as SDR BT.2020 and tone-map incorrectly.
|
|
115
141
|
const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
|
|
116
|
-
const colorParams =
|
|
142
|
+
const colorParams = options.rawInputFormat && options.hdr
|
|
143
|
+
? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams
|
|
144
|
+
: "colorprim=bt709:transfer=bt709:colormatrix=bt709";
|
|
117
145
|
if (preset === "ultrafast") {
|
|
118
146
|
args.push(xParamsFlag, `aq-mode=3:${colorParams}`);
|
|
119
147
|
}
|
|
120
148
|
else {
|
|
121
149
|
args.push(xParamsFlag, `aq-mode=3:aq-strength=0.8:deblock=1,1:${colorParams}`);
|
|
122
150
|
}
|
|
151
|
+
// Apple devices require hvc1 tag for HEVC playback (default hev1 won't open in QuickTime)
|
|
152
|
+
if (codec === "h265") {
|
|
153
|
+
args.push("-tag:v", "hvc1");
|
|
154
|
+
}
|
|
123
155
|
}
|
|
124
156
|
}
|
|
125
157
|
else if (codec === "vp9") {
|
|
@@ -136,18 +168,31 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
136
168
|
args.push("-pix_fmt", pixelFormat);
|
|
137
169
|
return [...args, "-y", outputPath];
|
|
138
170
|
}
|
|
139
|
-
//
|
|
140
|
-
//
|
|
171
|
+
// Color space metadata.
|
|
172
|
+
// When rawInputFormat is set, data comes from the WebGPU HDR pipeline
|
|
173
|
+
// (PQ-encoded) — tag with bt2020/PQ truthfully.
|
|
174
|
+
// Otherwise, Chrome captures sRGB — tag as bt709.
|
|
141
175
|
if (codec === "h264" || codec === "h265") {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
176
|
+
if (options.rawInputFormat && options.hdr) {
|
|
177
|
+
args.push("-colorspace:v", "bt2020nc", "-color_primaries:v", "bt2020", "-color_trc:v", options.hdr.transfer === "pq" ? "smpte2084" : "arib-std-b67", "-color_range", "tv");
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
args.push("-colorspace:v", "bt709", "-color_primaries:v", "bt709", "-color_trc:v", "bt709", "-color_range", "tv");
|
|
181
|
+
}
|
|
182
|
+
// Video filter for range/color conversion.
|
|
183
|
+
// Raw HDR input (from WebGPU pipeline) is already PQ-encoded — no conversion needed.
|
|
184
|
+
// Chrome screenshots need full→TV range conversion.
|
|
185
|
+
if (options.rawInputFormat) {
|
|
186
|
+
// No filter needed — PQ data goes straight to encoder
|
|
187
|
+
}
|
|
188
|
+
else if (gpuEncoder === "vaapi") {
|
|
145
189
|
const vfIdx = args.indexOf("-vf");
|
|
146
190
|
if (vfIdx !== -1) {
|
|
147
191
|
args[vfIdx + 1] = `scale=in_range=pc:out_range=tv,${args[vfIdx + 1]}`;
|
|
148
192
|
}
|
|
149
193
|
}
|
|
150
194
|
else if (!shouldUseGpu) {
|
|
195
|
+
// Range conversion: Chrome screenshots are full-range RGB.
|
|
151
196
|
args.push("-vf", "scale=in_range=pc:out_range=tv");
|
|
152
197
|
}
|
|
153
198
|
// Fixed timescale for consistent A/V timing across platforms.
|
|
@@ -220,16 +265,25 @@ export async function spawnStreamingEncoder(outputPath, options, signal, config)
|
|
|
220
265
|
if (exitStatus !== "running" || !ffmpeg.stdin || ffmpeg.stdin.destroyed) {
|
|
221
266
|
return false;
|
|
222
267
|
}
|
|
223
|
-
|
|
268
|
+
// Copy the buffer before writing — Node streams hold a reference to the
|
|
269
|
+
// provided buffer and drain it asynchronously. The HDR path's compositor
|
|
270
|
+
// reuses pre-allocated transOutput/normalCanvas buffers across frames,
|
|
271
|
+
// so without this copy the pipe would read partially-overwritten data
|
|
272
|
+
// and flicker. The SDR path doesn't invoke writeFrame at all (it pipes
|
|
273
|
+
// PNG files via encodeFramesFromDir), so the memcpy here is HDR-only
|
|
274
|
+
// and justified by correctness.
|
|
275
|
+
const copy = Buffer.from(buffer);
|
|
276
|
+
return ffmpeg.stdin.write(copy);
|
|
224
277
|
},
|
|
225
278
|
close: async () => {
|
|
226
279
|
clearTimeout(timer);
|
|
227
280
|
if (signal)
|
|
228
281
|
signal.removeEventListener("abort", onAbort);
|
|
229
282
|
// Close stdin to signal end of input
|
|
230
|
-
|
|
283
|
+
const stdin = ffmpeg.stdin;
|
|
284
|
+
if (stdin && !stdin.destroyed) {
|
|
231
285
|
await new Promise((resolve) => {
|
|
232
|
-
|
|
286
|
+
stdin.end(() => resolve());
|
|
233
287
|
});
|
|
234
288
|
}
|
|
235
289
|
// Wait for FFmpeg to finish
|