@hyperframes/engine 0.6.118 → 0.6.120

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.
Files changed (73) hide show
  1. package/package.json +24 -7
  2. package/scripts/generate-lut-reference.py +0 -168
  3. package/scripts/test-fitTextFontSize-browser.ts +0 -135
  4. package/src/cdp-headless-experimental.d.ts +0 -54
  5. package/src/config.test.ts +0 -213
  6. package/src/config.ts +0 -417
  7. package/src/index.ts +0 -273
  8. package/src/services/audioMixer.test.ts +0 -326
  9. package/src/services/audioMixer.ts +0 -604
  10. package/src/services/audioMixer.types.ts +0 -35
  11. package/src/services/audioVolumeEnvelope.test.ts +0 -176
  12. package/src/services/audioVolumeEnvelope.ts +0 -138
  13. package/src/services/browserManager.test.ts +0 -330
  14. package/src/services/browserManager.ts +0 -670
  15. package/src/services/chunkEncoder.test.ts +0 -1415
  16. package/src/services/chunkEncoder.ts +0 -831
  17. package/src/services/chunkEncoder.types.ts +0 -60
  18. package/src/services/extractionCache.test.ts +0 -199
  19. package/src/services/extractionCache.ts +0 -216
  20. package/src/services/fileServer.ts +0 -110
  21. package/src/services/frameCapture-discardWarmup.test.ts +0 -183
  22. package/src/services/frameCapture-namePolyfill.test.ts +0 -78
  23. package/src/services/frameCapture-pollImagesReady.test.ts +0 -153
  24. package/src/services/frameCapture-staticDedupIndex.test.ts +0 -76
  25. package/src/services/frameCapture-warmupTicks.test.ts +0 -174
  26. package/src/services/frameCapture.test.ts +0 -192
  27. package/src/services/frameCapture.ts +0 -1934
  28. package/src/services/hdrCapture.test.ts +0 -159
  29. package/src/services/hdrCapture.ts +0 -315
  30. package/src/services/parallelCoordinator.test.ts +0 -139
  31. package/src/services/parallelCoordinator.ts +0 -437
  32. package/src/services/screenshotService.test.ts +0 -510
  33. package/src/services/screenshotService.ts +0 -615
  34. package/src/services/streamingEncoder.test.ts +0 -832
  35. package/src/services/streamingEncoder.ts +0 -594
  36. package/src/services/systemMemory.test.ts +0 -324
  37. package/src/services/systemMemory.ts +0 -180
  38. package/src/services/videoFrameExtractor.test.ts +0 -1062
  39. package/src/services/videoFrameExtractor.ts +0 -1139
  40. package/src/services/videoFrameInjector.test.ts +0 -300
  41. package/src/services/videoFrameInjector.ts +0 -687
  42. package/src/services/vp9Options.ts +0 -13
  43. package/src/types.ts +0 -191
  44. package/src/utils/alphaBlit.test.ts +0 -1349
  45. package/src/utils/alphaBlit.ts +0 -1015
  46. package/src/utils/assertSwiftShader.test.ts +0 -130
  47. package/src/utils/assertSwiftShader.ts +0 -126
  48. package/src/utils/ffmpegBinaries.test.ts +0 -43
  49. package/src/utils/ffmpegBinaries.ts +0 -63
  50. package/src/utils/ffprobe.test.ts +0 -342
  51. package/src/utils/ffprobe.ts +0 -457
  52. package/src/utils/gpuEncoder.test.ts +0 -140
  53. package/src/utils/gpuEncoder.ts +0 -268
  54. package/src/utils/hdr.test.ts +0 -191
  55. package/src/utils/hdr.ts +0 -137
  56. package/src/utils/hdrCompositing.test.ts +0 -130
  57. package/src/utils/htmlTemplate.test.ts +0 -42
  58. package/src/utils/htmlTemplate.ts +0 -42
  59. package/src/utils/layerCompositor.test.ts +0 -150
  60. package/src/utils/layerCompositor.ts +0 -58
  61. package/src/utils/parityContract.ts +0 -1
  62. package/src/utils/processTracker.test.ts +0 -74
  63. package/src/utils/processTracker.ts +0 -41
  64. package/src/utils/readWebGlVendorInfoFromCanvas.ts +0 -52
  65. package/src/utils/runFfmpeg.test.ts +0 -102
  66. package/src/utils/runFfmpeg.ts +0 -136
  67. package/src/utils/shaderTransitions.test.ts +0 -738
  68. package/src/utils/shaderTransitions.ts +0 -1130
  69. package/src/utils/uint16-alignment-audit.test.ts +0 -125
  70. package/src/utils/urlDownloader.test.ts +0 -65
  71. package/src/utils/urlDownloader.ts +0 -143
  72. package/tsconfig.json +0 -19
  73. package/vitest.config.ts +0 -7
package/src/config.ts DELETED
@@ -1,417 +0,0 @@
1
- /**
2
- * Engine Configuration
3
- *
4
- * Typed configuration for the rendering pipeline. Replaces the PRODUCER_*
5
- * env var sprawl with a structured interface. Env vars still work as
6
- * fallbacks for backward compatibility during migration.
7
- */
8
-
9
- import {
10
- getSystemTotalMb,
11
- isLowMemorySystem,
12
- LOW_MEMORY_TOTAL_MB_THRESHOLD,
13
- } from "./services/systemMemory.js";
14
- import { DEFAULT_VP9_CPU_USED, normalizeVp9CpuUsed } from "./services/vp9Options.js";
15
-
16
- /**
17
- * Full engine configuration. All fields are wired through the config
18
- * object; env vars serve as backward-compatible fallbacks resolved
19
- * in `resolveConfig()`.
20
- */
21
- export interface EngineConfig {
22
- // ── Rendering ────────────────────────────────────────────────────────
23
- fps: 24 | 30 | 60;
24
- quality: "draft" | "standard" | "high";
25
- format: "jpeg" | "png";
26
- jpegQuality: number;
27
-
28
- // ── Parallelism ──────────────────────────────────────────────────────
29
- /** Max worker count. "auto" uses CPU-based heuristic. */
30
- concurrency: number | "auto";
31
- /** CPU cores allocated per worker. */
32
- coresPerWorker: number;
33
- /** Minimum frames before parallel workers are used. */
34
- minParallelFrames: number;
35
- /** Frame count threshold for "large render" heuristics. */
36
- largeRenderThreshold: number;
37
-
38
- // ── Browser ──────────────────────────────────────────────────────────
39
- chromePath?: string;
40
- disableGpu: boolean;
41
- /**
42
- * Chrome/WebGL rendering backend.
43
- * - "software": SwiftShader (CPU-only). Always works; ~5-50× slower than GPU.
44
- * - "hardware": host GPU via platform-native ANGLE backend (Metal/D3D11/EGL).
45
- * Errors if no usable GPU is reachable from Chrome.
46
- * - "auto": probe Chrome for WebGL availability on first launch in this
47
- * process; fall back to software if hardware-mode WebGL is unavailable.
48
- * Cost: one extra Chrome launch (~1-2 s) per process; result cached.
49
- */
50
- browserGpuMode: "software" | "hardware" | "auto";
51
- enableBrowserPool: boolean;
52
- browserTimeout: number;
53
- protocolTimeout: number;
54
- /** Expected Chromium major version (optional validation). */
55
- expectedChromiumMajor?: number;
56
- /** Force screenshot capture mode (skip BeginFrame even on Linux). */
57
- forceScreenshot: boolean;
58
- /**
59
- * Static-frame dedup: reuse byte-identical frames instead of re-seeking +
60
- * re-screenshotting (anchor-verified at init). Default ON; disable via
61
- * `HF_STATIC_DEDUP` in {false,0,off}. Only arms in screenshot capture mode.
62
- */
63
- staticFrameDedup: boolean;
64
- /**
65
- * Low-memory render profile. When `true`, the orchestrator collapses the
66
- * pipeline to its cheapest shape on memory-constrained hosts: it skips the
67
- * throwaway auto-worker calibration browser, pins capture to a single
68
- * worker (unless the user passed an explicit `--workers`), and prefers
69
- * screenshot capture over BeginFrame. Resolved automatically from total
70
- * RAM (`isLowMemorySystem()`); force on/off via `PRODUCER_LOW_MEMORY_MODE`
71
- * or the `--low-memory-mode` CLI flag.
72
- */
73
- lowMemoryMode: boolean;
74
- /**
75
- * Opt-in: page-side shader-transition compositing.
76
- *
77
- * When `true`, shader transitions for SDR compositions run their blend
78
- * inside Chrome via WebGL on a page-side compositor canvas instead of
79
- * Node-side per-pixel blending (the hf#677 layered pipeline). The engine
80
- * then captures ONE opaque RGB frame per output frame via the streaming
81
- * capture path, skipping per-scene transparent screenshots and the
82
- * Node-side shader-blend worker pool entirely.
83
- *
84
- * The feature stacks on top of the hf#677 chain — it does not undo it.
85
- * When this flag is OFF (the default), behaviour is byte-identical to the
86
- * current path. When ON and the composition has no shader transitions or
87
- * has HDR content (which forces the layered path regardless), this flag
88
- * is a no-op.
89
- *
90
- * Mac viability: Chrome on Mac accelerates page-side WebGL canvases via
91
- * Metal/CoreAnimation natively. This is the lever for Mac users who
92
- * cannot use `--enable-begin-frame-control` (Chromium structural limit,
93
- * crbug.com/40656275).
94
- *
95
- * Determinism: page-side WebGL is f32, not f64. Byte-equality fixture
96
- * pins are NOT compatible with this path; the new path's correctness
97
- * pin is PSNR-based. Default OFF preserves the existing pins for the
98
- * hf#677 chain.
99
- *
100
- * Env fallback: `HF_PAGE_SIDE_COMPOSITING=true`.
101
- */
102
- enablePageSideCompositing: boolean;
103
-
104
- // ── Encoding ─────────────────────────────────────────────────────────
105
- /**
106
- * libvpx-vp9 speed/quality tradeoff. Higher values encode faster with a
107
- * larger quality/size tradeoff. FFmpeg accepts integer values from -8 to 8.
108
- */
109
- vp9CpuUsed: number;
110
- enableChunkedEncode: boolean;
111
- chunkSizeFrames: number;
112
- enableStreamingEncode: boolean;
113
- /**
114
- * Max composition duration eligible for streaming encode (seconds).
115
- * Mirrors GSAP rendering's 4-minute streaming guard: production has seen
116
- * ffmpeg's streaming pipe hit FFMPEG_STREAMING_TIMEOUT_MS on longer videos.
117
- */
118
- streamingEncodeMaxDurationSeconds: number;
119
-
120
- // ── FFmpeg timeouts ──────────────────────────────────────────────────
121
- /** Timeout for FFmpeg frame encoding (ms). Default: 600_000 */
122
- ffmpegEncodeTimeout: number;
123
- /** Timeout for FFmpeg mux/faststart processes (ms). Default: 300_000 */
124
- ffmpegProcessTimeout: number;
125
- /**
126
- * Inactivity timeout for FFmpeg streaming encode (ms). The timer resets on
127
- * every successful `writeFrame` call, so this caps the duration of a
128
- * single "no frame arrived" gap (capture hang, dead Chrome), not the total
129
- * render time. Default: 600_000 (10 minutes without any frame = dead).
130
- */
131
- ffmpegStreamingTimeout: number;
132
-
133
- // ── HDR ──────────────────────────────────────────────────────────────
134
- /** HDR output transfer function. false = SDR output (default). */
135
- hdr: { transfer: "hlg" | "pq" } | false;
136
- /** Auto-detect HDR from video sources when hdr is not explicitly set. */
137
- hdrAutoDetect: boolean;
138
-
139
- // ── Media ────────────────────────────────────────────────────────────
140
- audioGain: number;
141
- /**
142
- * Hard upper bound on entries kept in the video frame data URI cache.
143
- * Acts as a sanity cap; the byte budget below normally fires first on
144
- * high-resolution renders. At 1080p with ~6 MB per JPEG frame the default
145
- * 256 entries fit inside ~1.5 GB. At 4K the byte budget evicts long
146
- * before this cap is reached.
147
- */
148
- frameDataUriCacheLimit: number;
149
- /**
150
- * Memory budget for the cache, in megabytes. Eviction kicks in once the
151
- * sum of cached data-URI string lengths exceeds this. Sized so a worker
152
- * stays comfortably under a few GB even at 4K (where each PNG frame is
153
- * ~25 MB and the base64 data URI is ~33 MB).
154
- */
155
- frameDataUriCacheBytesLimitMb: number;
156
-
157
- // ── Timeouts ─────────────────────────────────────────────────────────
158
- playerReadyTimeout: number;
159
- renderReadyTimeout: number;
160
- /**
161
- * Puppeteer `page.goto()` navigation timeout for the entry HTML, in ms.
162
- * The browser must reach `domcontentloaded` within this budget — heavy
163
- * compositions (many videos, large fonts, hundreds of asset requests)
164
- * can blow past the default 60s on cold cache. Default: 60_000.
165
- *
166
- * Env fallback: `PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS`.
167
- * CLI flag: `--browser-timeout <seconds>`.
168
- */
169
- pageNavigationTimeout: number;
170
-
171
- // ── Runtime ──────────────────────────────────────────────────────────
172
- /** Verify Hyperframe runtime SHA256 checksums. */
173
- verifyRuntime: boolean;
174
- /** Custom manifest path for Hyperframe runtime. */
175
- runtimeManifestPath?: string;
176
-
177
- // ── Cache ────────────────────────────────────────────────────────────
178
- /**
179
- * Directory where the content-addressed extraction cache persists frame
180
- * bundles keyed on (path, mtime, size, mediaStart, duration, fps, format).
181
- * Undefined disables caching — extraction runs into the render's workDir
182
- * and cleanup removes it when the render ends, preserving the pre-cache
183
- * behaviour.
184
- *
185
- * **Single-writer.** The cache is not safe for concurrent renders pointing
186
- * at the same directory. A `.hf-complete` sentinel prevents another render
187
- * from serving an entry that hasn't finished extracting, but individual
188
- * frame files are written non-atomically — a second render reading during
189
- * the write window can observe a truncated frame. Give each concurrent
190
- * render pipeline its own `extractCacheDir`, or gate with an external mutex.
191
- *
192
- * **Network filesystems.** `mtime` resolution on NFS/SMB mounts can be
193
- * coarser than expected (seconds rather than nanoseconds), which may
194
- * produce spurious cache hits if a source file is overwritten within the
195
- * same mtime tick. Local filesystems are the intended deployment target.
196
- *
197
- * Env fallback: `HYPERFRAMES_EXTRACT_CACHE_DIR`.
198
- */
199
- extractCacheDir?: string;
200
-
201
- // ── Debug ────────────────────────────────────────────────────────────
202
- debug: boolean;
203
- }
204
-
205
- /** Default configuration — sensible for Hyperframes compositions. */
206
- export const DEFAULT_CONFIG: EngineConfig = {
207
- fps: 30,
208
- quality: "standard",
209
- format: "jpeg",
210
- jpegQuality: 80,
211
-
212
- concurrency: "auto",
213
- coresPerWorker: 2.5,
214
- minParallelFrames: 120,
215
- largeRenderThreshold: 1000,
216
-
217
- disableGpu: false,
218
- browserGpuMode: "software",
219
- enableBrowserPool: true,
220
- browserTimeout: 120_000,
221
- protocolTimeout: 300_000,
222
- forceScreenshot: false,
223
- staticFrameDedup: true,
224
- // Auto-detected per host in `resolveConfig`; defaults off for the raw
225
- // DEFAULT_CONFIG (used directly by tests and worker-sizing fallbacks).
226
- lowMemoryMode: false,
227
- enablePageSideCompositing: true,
228
-
229
- vp9CpuUsed: DEFAULT_VP9_CPU_USED,
230
- enableChunkedEncode: false,
231
- chunkSizeFrames: 360,
232
- enableStreamingEncode: true,
233
- streamingEncodeMaxDurationSeconds: 240,
234
-
235
- ffmpegEncodeTimeout: 600_000,
236
- ffmpegProcessTimeout: 300_000,
237
- ffmpegStreamingTimeout: 600_000,
238
-
239
- hdr: false,
240
- hdrAutoDetect: true,
241
-
242
- audioGain: 1,
243
- frameDataUriCacheLimit: 256,
244
- frameDataUriCacheBytesLimitMb: 1500,
245
-
246
- playerReadyTimeout: 45_000,
247
- renderReadyTimeout: 15_000,
248
- pageNavigationTimeout: 60_000,
249
-
250
- verifyRuntime: true,
251
-
252
- debug: false,
253
- };
254
-
255
- function memoryAdaptiveCacheLimit(): number {
256
- const total = getSystemTotalMb();
257
- if (total < 4096) return 32;
258
- if (total <= LOW_MEMORY_TOTAL_MB_THRESHOLD) return 64;
259
- return DEFAULT_CONFIG.frameDataUriCacheLimit;
260
- }
261
-
262
- function memoryAdaptiveCacheBytesMb(): number {
263
- const total = getSystemTotalMb();
264
- if (total < 4096) return 128;
265
- if (total <= LOW_MEMORY_TOTAL_MB_THRESHOLD) return 256;
266
- return DEFAULT_CONFIG.frameDataUriCacheBytesLimitMb;
267
- }
268
-
269
- /**
270
- * Resolve configuration by merging: defaults ← env vars ← explicit overrides.
271
- * Env vars provide backward compatibility during migration; explicit config
272
- * takes precedence over everything.
273
- */
274
- export function resolveConfig(overrides?: Partial<EngineConfig>): EngineConfig {
275
- const env = (key: string): string | undefined => process.env[key];
276
- const envNum = (key: string, fallback: number): number => {
277
- const raw = env(key);
278
- if (raw === undefined || raw === "") return fallback;
279
- const n = Number(raw);
280
- return Number.isFinite(n) ? n : fallback;
281
- };
282
- const envBool = (key: string, fallback: boolean): boolean => {
283
- const raw = env(key);
284
- if (raw === undefined) return fallback;
285
- return raw === "true";
286
- };
287
- const envVp9CpuUsed = (): number => {
288
- const raw = env("PRODUCER_VP9_CPU_USED");
289
- if (raw === undefined || raw === "") return DEFAULT_CONFIG.vp9CpuUsed;
290
- return normalizeVp9CpuUsed(Number(raw));
291
- };
292
- const envBrowserGpuMode = (): EngineConfig["browserGpuMode"] => {
293
- const raw = env("PRODUCER_BROWSER_GPU_MODE");
294
- if (raw === "hardware" || raw === "software" || raw === "auto") return raw;
295
- return DEFAULT_CONFIG.browserGpuMode;
296
- };
297
- // Tri-state: explicit on/off via env, otherwise auto-detect from total RAM.
298
- const resolveLowMemoryMode = (): boolean => {
299
- const raw = env("PRODUCER_LOW_MEMORY_MODE")?.toLowerCase();
300
- if (raw === "true" || raw === "on" || raw === "1") return true;
301
- if (raw === "false" || raw === "off" || raw === "0") return false;
302
- return isLowMemorySystem();
303
- };
304
- // Opt-OUT: default ON, disabled only by an explicit falsey value.
305
- const resolveStaticFrameDedup = (): boolean => {
306
- const raw = env("HF_STATIC_DEDUP")?.trim().toLowerCase();
307
- return !(raw === "false" || raw === "off" || raw === "0");
308
- };
309
-
310
- // Env-var layer (backward compat)
311
- const fromEnv: Partial<EngineConfig> = {
312
- concurrency: env("PRODUCER_MAX_WORKERS") ? Number(env("PRODUCER_MAX_WORKERS")) : undefined,
313
- coresPerWorker: envNum("PRODUCER_CORES_PER_WORKER", DEFAULT_CONFIG.coresPerWorker),
314
- minParallelFrames: envNum("PRODUCER_MIN_PARALLEL_FRAMES", DEFAULT_CONFIG.minParallelFrames),
315
- largeRenderThreshold: envNum(
316
- "PRODUCER_LARGE_RENDER_THRESHOLD",
317
- DEFAULT_CONFIG.largeRenderThreshold,
318
- ),
319
-
320
- chromePath: env("PRODUCER_HEADLESS_SHELL_PATH"),
321
- disableGpu: envBool("PRODUCER_DISABLE_GPU", DEFAULT_CONFIG.disableGpu),
322
- browserGpuMode: envBrowserGpuMode(),
323
- enableBrowserPool: envBool("PRODUCER_ENABLE_BROWSER_POOL", DEFAULT_CONFIG.enableBrowserPool),
324
- browserTimeout: envNum("PRODUCER_PUPPETEER_LAUNCH_TIMEOUT_MS", DEFAULT_CONFIG.browserTimeout),
325
- protocolTimeout: envNum(
326
- "PRODUCER_PUPPETEER_PROTOCOL_TIMEOUT_MS",
327
- DEFAULT_CONFIG.protocolTimeout,
328
- ),
329
- expectedChromiumMajor: env("PRODUCER_EXPECTED_CHROMIUM_MAJOR")
330
- ? Number(env("PRODUCER_EXPECTED_CHROMIUM_MAJOR"))
331
- : undefined,
332
-
333
- forceScreenshot: envBool("PRODUCER_FORCE_SCREENSHOT", DEFAULT_CONFIG.forceScreenshot),
334
- staticFrameDedup: resolveStaticFrameDedup(),
335
- lowMemoryMode: resolveLowMemoryMode(),
336
- enablePageSideCompositing: envBool(
337
- "HF_PAGE_SIDE_COMPOSITING",
338
- DEFAULT_CONFIG.enablePageSideCompositing,
339
- ),
340
-
341
- vp9CpuUsed: envVp9CpuUsed(),
342
- enableChunkedEncode: envBool(
343
- "PRODUCER_ENABLE_CHUNKED_ENCODE",
344
- DEFAULT_CONFIG.enableChunkedEncode,
345
- ),
346
- chunkSizeFrames: Math.max(
347
- 120,
348
- envNum("PRODUCER_CHUNK_SIZE_FRAMES", DEFAULT_CONFIG.chunkSizeFrames),
349
- ),
350
- enableStreamingEncode: envBool(
351
- "PRODUCER_ENABLE_STREAMING_ENCODE",
352
- DEFAULT_CONFIG.enableStreamingEncode,
353
- ),
354
- streamingEncodeMaxDurationSeconds: Math.max(
355
- 0,
356
- envNum(
357
- "PRODUCER_STREAMING_ENCODE_MAX_DURATION_SECONDS",
358
- DEFAULT_CONFIG.streamingEncodeMaxDurationSeconds,
359
- ),
360
- ),
361
-
362
- ffmpegEncodeTimeout: envNum("FFMPEG_ENCODE_TIMEOUT_MS", DEFAULT_CONFIG.ffmpegEncodeTimeout),
363
- ffmpegProcessTimeout: envNum("FFMPEG_PROCESS_TIMEOUT_MS", DEFAULT_CONFIG.ffmpegProcessTimeout),
364
- ffmpegStreamingTimeout: envNum(
365
- "FFMPEG_STREAMING_TIMEOUT_MS",
366
- DEFAULT_CONFIG.ffmpegStreamingTimeout,
367
- ),
368
-
369
- hdr: (() => {
370
- const raw = env("PRODUCER_HDR_TRANSFER");
371
- if (raw === "hlg" || raw === "pq") return { transfer: raw };
372
- return false;
373
- })(),
374
- hdrAutoDetect: envBool("PRODUCER_HDR_AUTO_DETECT", DEFAULT_CONFIG.hdrAutoDetect),
375
-
376
- audioGain: envNum("PRODUCER_AUDIO_GAIN", DEFAULT_CONFIG.audioGain),
377
- frameDataUriCacheLimit: Math.max(
378
- 32,
379
- envNum("PRODUCER_FRAME_DATA_URI_CACHE_LIMIT", memoryAdaptiveCacheLimit()),
380
- ),
381
- frameDataUriCacheBytesLimitMb: Math.max(
382
- 64,
383
- envNum("PRODUCER_FRAME_DATA_URI_CACHE_BYTES_MB", memoryAdaptiveCacheBytesMb()),
384
- ),
385
-
386
- playerReadyTimeout: envNum(
387
- "PRODUCER_PLAYER_READY_TIMEOUT_MS",
388
- DEFAULT_CONFIG.playerReadyTimeout,
389
- ),
390
- renderReadyTimeout: envNum(
391
- "PRODUCER_RENDER_READY_TIMEOUT_MS",
392
- DEFAULT_CONFIG.renderReadyTimeout,
393
- ),
394
- pageNavigationTimeout: envNum(
395
- "PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS",
396
- DEFAULT_CONFIG.pageNavigationTimeout,
397
- ),
398
-
399
- verifyRuntime: env("PRODUCER_VERIFY_HYPERFRAME_RUNTIME") !== "false",
400
- runtimeManifestPath: env("PRODUCER_HYPERFRAME_MANIFEST_PATH"),
401
-
402
- extractCacheDir: env("HYPERFRAMES_EXTRACT_CACHE_DIR"),
403
- };
404
-
405
- // Remove undefined values so they don't override defaults
406
- const cleanEnv = Object.fromEntries(Object.entries(fromEnv).filter(([, v]) => v !== undefined));
407
-
408
- const merged = {
409
- ...DEFAULT_CONFIG,
410
- ...cleanEnv,
411
- ...overrides,
412
- };
413
- return {
414
- ...merged,
415
- vp9CpuUsed: normalizeVp9CpuUsed(merged.vp9CpuUsed),
416
- };
417
- }
package/src/index.ts DELETED
@@ -1,273 +0,0 @@
1
- /**
2
- * @hyperframes/engine
3
- *
4
- * Seekable web page to video rendering engine.
5
- * Framework-agnostic: works with GSAP, Lottie, Three.js, CSS animations,
6
- * or any web content that implements the window.__hf seek protocol.
7
- *
8
- * ## Error Convention
9
- *
10
- * Engine services use three error strategies depending on the operation type:
11
- *
12
- * - **Orchestration services throw on failure.** Browser launch, session init,
13
- * frame capture, and CDP operations propagate errors as thrown exceptions.
14
- * Callers are expected to catch and handle (e.g. frameCapture, browserManager,
15
- * screenshotService, videoFrameExtractor.extractVideoFramesRange).
16
- *
17
- * - **FFmpeg process wrappers return `{ success, error? }` result objects.**
18
- * Encoding, muxing, audio mixing, and streaming encode operations never reject.
19
- * They resolve with a result that includes `success: boolean` and an optional
20
- * `error` string (e.g. chunkEncoder, audioMixer, streamingEncoder).
21
- *
22
- * - **Cleanup and teardown functions never throw.** Browser close, session close,
23
- * temp directory removal, and resource release swallow errors via `.catch(() => {})`
24
- * to avoid masking the original failure (e.g. releaseBrowser, closeCaptureSession,
25
- * FrameLookupTable.cleanup).
26
- *
27
- * - **Optional lookups return `T | undefined` or `T | null`.**
28
- * Functions that may legitimately find nothing (resolveHeadlessShellPath,
29
- * getFrameAtTime, detectGpuEncoder) return a nullable value instead of throwing.
30
- *
31
- */
32
-
33
- // ── Protocol types ─────────────────────────────────────────────────────────────
34
- export type {
35
- HfProtocol,
36
- HfMediaElement,
37
- HfTransitionMeta,
38
- CaptureOptions,
39
- CaptureVideoMetadataHint,
40
- CaptureResult,
41
- CaptureBufferResult,
42
- CapturePerfSummary,
43
- } from "./types.js";
44
-
45
- // ── Configuration ──────────────────────────────────────────────────────────────
46
- export { resolveConfig, DEFAULT_CONFIG, type EngineConfig } from "./config.js";
47
- export {
48
- DEFAULT_VP9_CPU_USED,
49
- MAX_VP9_CPU_USED,
50
- MIN_VP9_CPU_USED,
51
- normalizeVp9CpuUsed,
52
- } from "./services/vp9Options.js";
53
- export {
54
- getSystemTotalMb,
55
- isLowMemorySystem,
56
- LOW_MEMORY_TOTAL_MB_THRESHOLD,
57
- } from "./services/systemMemory.js";
58
-
59
- // ── Browser management ─────────────────────────────────────────────────────────
60
- export {
61
- acquireBrowser,
62
- releaseBrowser,
63
- drainBrowserPool,
64
- resolveHeadlessShellPath,
65
- resolveBrowserGpuMode,
66
- buildChromeArgs,
67
- ENABLE_BROWSER_POOL,
68
- type BuildChromeArgsOptions,
69
- type CaptureMode,
70
- type AcquiredBrowser,
71
- } from "./services/browserManager.js";
72
-
73
- // ── Frame capture pipeline ──────────────────────────────────────────────────────
74
- export {
75
- createCaptureSession,
76
- initializeSession,
77
- closeCaptureSession,
78
- captureFrame,
79
- captureFrameToBuffer,
80
- discardWarmupCapture,
81
- getCompositionDuration,
82
- getCapturePerfSummary,
83
- prepareCaptureSessionForReuse,
84
- type CaptureSession,
85
- type BeforeCaptureHook,
86
- type DiscardWarmupInnerCapture,
87
- } from "./services/frameCapture.js";
88
-
89
- // ── Screenshot (BeginFrame) ─────────────────────────────────────────────────────
90
- export {
91
- beginFrameCapture,
92
- pageScreenshotCapture,
93
- getCdpSession,
94
- injectVideoFramesBatch,
95
- syncVideoFrameVisibility,
96
- cdpSessionCache,
97
- initTransparentBackground,
98
- captureAlphaPng,
99
- applyDomLayerMask,
100
- removeDomLayerMask,
101
- DOM_LAYER_MASK_STYLE_ID,
102
- type BeginFrameResult,
103
- } from "./services/screenshotService.js";
104
-
105
- // ── Encoding ───────────────────────────────────────────────────────────────────
106
- export {
107
- buildEncoderArgs,
108
- encodeFramesFromDir,
109
- encodeFramesChunkedConcat,
110
- muxVideoWithAudio,
111
- applyFaststart,
112
- detectGpuEncoder,
113
- ENCODER_PRESETS,
114
- getEncoderPreset,
115
- type GpuEncoder,
116
- } from "./services/chunkEncoder.js";
117
- export type { EncoderOptions, EncodeResult, MuxResult } from "./services/chunkEncoder.types.js";
118
-
119
- export {
120
- spawnStreamingEncoder,
121
- createFrameReorderBuffer,
122
- type StreamingEncoder,
123
- type StreamingEncoderOptions,
124
- type StreamingEncoderResult,
125
- type FrameReorderBuffer,
126
- } from "./services/streamingEncoder.js";
127
-
128
- // ── Media processing ───────────────────────────────────────────────────────────
129
- export {
130
- parseVideoElements,
131
- parseImageElements,
132
- extractVideoFramesRange,
133
- extractAllVideoFrames,
134
- resolveProjectRelativeSrc,
135
- getFrameAtTime,
136
- createFrameLookupTable,
137
- FrameLookupTable,
138
- type VideoElement,
139
- type ImageElement,
140
- type ExtractedFrames,
141
- type ExtractionOptions,
142
- type ExtractionResult,
143
- type ExtractionPhaseBreakdown,
144
- type VideoFrameFormat,
145
- VIDEO_FRAME_FORMATS,
146
- isVideoFrameFormat,
147
- } from "./services/videoFrameExtractor.js";
148
-
149
- export { createVideoFrameInjector } from "./services/videoFrameInjector.js";
150
-
151
- export { parseAudioElements, processCompositionAudio } from "./services/audioMixer.js";
152
- export type {
153
- AudioElement,
154
- AudioTrack,
155
- AudioVolumeKeyframe,
156
- MixResult,
157
- } from "./services/audioMixer.types.js";
158
-
159
- // ── Parallel rendering ─────────────────────────────────────────────────────────
160
- export {
161
- calculateOptimalWorkers,
162
- distributeFrames,
163
- executeParallelCapture,
164
- mergeWorkerFrames,
165
- getSystemResources,
166
- type WorkerTask,
167
- type WorkerResult,
168
- type ParallelProgress,
169
- } from "./services/parallelCoordinator.js";
170
-
171
- // ── File server ────────────────────────────────────────────────────────────────
172
- export {
173
- createFileServer,
174
- type FileServerOptions,
175
- type FileServerHandle,
176
- } from "./services/fileServer.js";
177
-
178
- // ── Utilities ──────────────────────────────────────────────────────────────────
179
- export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
180
-
181
- export {
182
- assertSwiftShader,
183
- readWebGlVendorInfo,
184
- SwiftShaderAssertionError,
185
- BROWSER_GPU_NOT_SOFTWARE,
186
- } from "./utils/assertSwiftShader.js";
187
-
188
- export { readWebGlVendorInfoFromCanvas } from "./utils/readWebGlVendorInfoFromCanvas.js";
189
-
190
- export {
191
- extractMediaMetadata,
192
- extractVideoMetadata,
193
- extractAudioMetadata,
194
- analyzeKeyframeIntervals,
195
- type VideoMetadata,
196
- type AudioMetadata,
197
- type KeyframeAnalysis,
198
- } from "./utils/ffprobe.js";
199
-
200
- export { assertPublicHttpsUrl, downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
201
- export {
202
- runFfmpeg,
203
- formatFfmpegError,
204
- type RunFfmpegOptions,
205
- type RunFfmpegResult,
206
- } from "./utils/runFfmpeg.js";
207
- export {
208
- assertConfiguredFfmpegBinariesExist,
209
- getFfmpegBinary,
210
- getFfprobeBinary,
211
- FFMPEG_PATH_ENV,
212
- FFPROBE_PATH_ENV,
213
- } from "./utils/ffmpegBinaries.js";
214
-
215
- export { trackChildProcess, killTrackedProcesses } from "./utils/processTracker.js";
216
-
217
- export {
218
- decodePng,
219
- decodePngToRgb48le,
220
- blitRgba8OverRgb48le,
221
- blitRgb48leRegion,
222
- blitRgb48leAffine,
223
- parseTransformMatrix,
224
- roundedRectAlpha,
225
- resampleRgb48leObjectFit,
226
- normalizeObjectFit,
227
- type ObjectFit,
228
- } from "./utils/alphaBlit.js";
229
-
230
- export { groupIntoLayers, type CompositeLayer } from "./utils/layerCompositor.js";
231
-
232
- // ── Shader transitions ────────────────────────────────────────────────────────
233
- export {
234
- type TransitionFn,
235
- TRANSITIONS,
236
- crossfade,
237
- sampleRgb48le,
238
- hdrToLinear,
239
- linearToHdr,
240
- convertTransfer,
241
- } from "./utils/shaderTransitions.js";
242
-
243
- export {
244
- initHdrReadback,
245
- uploadAndReadbackHdrFrame,
246
- float16ToPqRgb,
247
- buildHdrChromeArgs,
248
- launchHdrBrowser,
249
- } from "./services/hdrCapture.js";
250
-
251
- export { captureScreenshotWithAlpha } from "./services/screenshotService.js";
252
-
253
- export {
254
- hideVideoElements,
255
- showVideoElements,
256
- queryVideoElementBounds,
257
- queryElementStacking,
258
- type VideoElementBounds,
259
- type ElementStackingInfo,
260
- } from "./services/videoFrameInjector.js";
261
-
262
- export {
263
- isHdrColorSpace,
264
- detectTransfer,
265
- getHdrEncoderColorParams,
266
- analyzeCompositionHdr,
267
- DEFAULT_HDR10_MASTERING,
268
- type HdrTransfer,
269
- type HdrEncoderColorParams,
270
- type CompositionHdrInfo,
271
- type HdrMasteringMetadata,
272
- } from "./utils/hdr.js";
273
- export type { VideoColorSpace } from "./utils/ffprobe.js";