@hyperframes/engine 0.8.193 → 0.8.195

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -50,7 +50,7 @@ export { parseVideoElements, parseImageElements, extractVideoFramesRange, extrac
50
50
  export { directorySizeBytes, gcExtractionCache } from "./services/extractionCache.js";
51
51
  export { resolveReferencedStart, resolveReferencedDuration, type RefResolverEl, type RefResolverDoc, } from "./services/referenceResolver.js";
52
52
  export { createVideoFrameInjector } from "./services/videoFrameInjector.js";
53
- export { MIXED_AUDIO_FILENAME, parseAudioElements, parseMasterFxChain, processCompositionAudio, } from "./services/audioMixer.js";
53
+ export { MIXED_AUDIO_FILENAME, parseAudioElements, parseMasterFxChain, processCompositionAudio, videoAudioId, } from "./services/audioMixer.js";
54
54
  export { audioFailureDiagnostics } from "./services/audioFailureDiagnostic.js";
55
55
  export { cloneCaptureWarning, cloneCaptureWarnings } from "./services/captureWarning.js";
56
56
  export type { AudioElement, AudioFailureReason, AudioFailureStage, AudioProcessingFailure, AudioFailureDiagnostic, AudioSubprocessEvidence, AudioTrack, AudioVolumeKeyframe, MixResult, } from "./services/audioMixer.types.js";
package/dist/index.js CHANGED
@@ -54,7 +54,7 @@ export { parseVideoElements, parseImageElements, extractVideoFramesRange, extrac
54
54
  export { directorySizeBytes, gcExtractionCache } from "./services/extractionCache.js";
55
55
  export { resolveReferencedStart, resolveReferencedDuration, } from "./services/referenceResolver.js";
56
56
  export { createVideoFrameInjector } from "./services/videoFrameInjector.js";
57
- export { MIXED_AUDIO_FILENAME, parseAudioElements, parseMasterFxChain, processCompositionAudio, } from "./services/audioMixer.js";
57
+ export { MIXED_AUDIO_FILENAME, parseAudioElements, parseMasterFxChain, processCompositionAudio, videoAudioId, } from "./services/audioMixer.js";
58
58
  export { audioFailureDiagnostics } from "./services/audioFailureDiagnostic.js";
59
59
  export { cloneCaptureWarning, cloneCaptureWarnings } from "./services/captureWarning.js";
60
60
  // ── Parallel rendering ─────────────────────────────────────────────────────────
@@ -30,6 +30,7 @@ export declare function volumeLaneKeyframes(automation: {
30
30
  * itself has no parsed element to carry it.
31
31
  */
32
32
  export declare function parseMasterFxChain(html: string): string | undefined;
33
+ export declare function videoAudioId(videoId: string): string;
33
34
  export declare function parseAudioElements(html: string): AudioElement[];
34
35
  /** Tracks per ffmpeg graph; a larger mix is summed in stages, so there is no cap on the total. */
35
36
  export declare const MAX_MIX_INPUTS = 96;
@@ -420,6 +420,9 @@ export function volumeLaneKeyframes(automation, trackStart, duration, gain, gain
420
420
  export function parseMasterFxChain(html) {
421
421
  return readMasterFxChain(parseHTML(unwrapTemplate(html)).document);
422
422
  }
423
+ export function videoAudioId(videoId) {
424
+ return `${videoId}-audio`;
425
+ }
423
426
  export function parseAudioElements(html) {
424
427
  const elements = [];
425
428
  const { document } = parseHTML(unwrapTemplate(html));
@@ -504,7 +507,7 @@ export function parseAudioElements(html) {
504
507
  continue;
505
508
  if (isKnownInactiveTimelineWindow(el, resolveStart(el)))
506
509
  continue;
507
- elements.push(build(el, `${id}-audio`, src, "video", true));
510
+ elements.push(build(el, videoAudioId(id), src, "video", true));
508
511
  }
509
512
  return elements;
510
513
  }
@@ -5,6 +5,7 @@
5
5
  * Manages Puppeteer browser lifecycle: Chrome executable resolution,
6
6
  * launch args, pooled browser acquisition/release.
7
7
  */
8
+ import { withHyperframesBrowserMarker } from "@hyperframes/core/browser-marker";
8
9
  import { scanHtmlOpeningTags } from "@hyperframes/parsers/html-attribute-spans";
9
10
  import { execSync } from "child_process";
10
11
  import { existsSync, readdirSync, statSync } from "fs";
@@ -55,7 +56,7 @@ async function probeHardwareWebGlInfo(ppt, options) {
55
56
  const launchOptions = {
56
57
  ...sigintLaunchOptions(),
57
58
  headless: true,
58
- args: options.args,
59
+ args: withHyperframesBrowserMarker(options.args),
59
60
  defaultViewport: { width: 64, height: 64 },
60
61
  executablePath: options.executablePath,
61
62
  env: options.env,
@@ -463,6 +464,25 @@ function envWithoutWaylandDisplay() {
463
464
  const { WAYLAND_DISPLAY: _wslg, ...env } = process.env;
464
465
  return env;
465
466
  }
467
+ // ANGLE and Dawn load SwiftShader via VK_ICD_FILENAMES, which these override or filter:
468
+ // https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderDriverInterface.md
469
+ const VULKAN_VARS_THAT_OVERRIDE_SWIFTSHADER = [
470
+ "VK_DRIVER_FILES",
471
+ "VK_LOADER_DRIVERS_SELECT",
472
+ "VK_LOADER_DRIVERS_DISABLE",
473
+ ];
474
+ function launchEnv(fingerprint) {
475
+ if (fingerprint.withoutWaylandDisplay)
476
+ return envWithoutWaylandDisplay();
477
+ const swiftShader = fingerprint.args.some((arg) => arg === "--use-angle=swiftshader" || arg === "--use-vulkan=swiftshader");
478
+ const overriding = VULKAN_VARS_THAT_OVERRIDE_SWIFTSHADER.filter((name) => name in process.env);
479
+ if (!swiftShader || overriding.length === 0)
480
+ return undefined;
481
+ const env = { ...process.env };
482
+ for (const name of overriding)
483
+ delete env[name];
484
+ return env;
485
+ }
466
486
  /** True when a `resolvedMode` render must launch without WAYLAND_DISPLAY to reach the GPU. */
467
487
  export async function captureWithoutWaylandDisplay(resolvedMode) {
468
488
  if (resolvedMode !== "hardware")
@@ -630,14 +650,14 @@ export async function acquireBrowser(chromeArgs, config) {
630
650
  // fallow-ignore-next-line complexity
631
651
  async function launchBrowser(fingerprint) {
632
652
  const ppt = await getPuppeteer();
633
- const env = fingerprint.withoutWaylandDisplay ? envWithoutWaylandDisplay() : undefined;
653
+ const env = launchEnv(fingerprint);
634
654
  let captureMode = fingerprint.requestedCaptureMode;
635
655
  let browser;
636
656
  try {
637
657
  browser = await ppt.launch({
638
658
  ...sigintLaunchOptions(),
639
659
  headless: true,
640
- args: [...fingerprint.args],
660
+ args: withHyperframesBrowserMarker(fingerprint.args),
641
661
  defaultViewport: null,
642
662
  executablePath: fingerprint.executablePath,
643
663
  env,
@@ -662,7 +682,7 @@ async function launchBrowser(fingerprint) {
662
682
  browser = await ppt.launch({
663
683
  ...sigintLaunchOptions(),
664
684
  headless: true,
665
- args: stripBeginFrameFlags([...fingerprint.args]),
685
+ args: withHyperframesBrowserMarker(stripBeginFrameFlags([...fingerprint.args])),
666
686
  defaultViewport: null,
667
687
  executablePath: fingerprint.executablePath,
668
688
  env,
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { frameSequencePath } from "./extractedFrameIndex.js";
9
9
  import { closeSync, copyFileSync, existsSync, ftruncateSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, statSync, writeFileSync, writeSync, } from "fs";
10
- import { join, dirname, extname } from "path";
10
+ import { join, dirname, extname, resolve } from "path";
11
11
  import { DEFAULT_CONFIG } from "../config.js";
12
12
  import { getCachedGpuEncoder, getGpuEncoderName, buildVideoToolboxRateControlArgs, mapPresetForGpuEncoder, } from "../utils/gpuEncoder.js";
13
13
  import { getHdrEncoderColorParams, hdrFrameTagsFilter } from "../utils/hdr.js";
@@ -460,7 +460,7 @@ let concatListSeq = 0;
460
460
  function writeConcatList(dir, inputPaths) {
461
461
  concatListSeq += 1;
462
462
  const listPath = join(dir, `concat-list-${process.pid}-${concatListSeq}.txt`);
463
- const body = inputPaths.map((p) => `file '${p.replace(/'/g, "'\\''")}'`).join("\n");
463
+ const body = inputPaths.map((p) => `file '${resolve(p).replace(/'/g, "'\\''")}'`).join("\n");
464
464
  writeFileSync(listPath, body, "utf-8");
465
465
  return listPath;
466
466
  }
@@ -18,6 +18,7 @@
18
18
  *
19
19
  * Performance: ~6 fps at 1080x1920 via base64 transfer.
20
20
  */
21
+ import { withHyperframesBrowserMarker } from "@hyperframes/core/browser-marker";
21
22
  import { resolveFullChromePath, sigintLaunchOptions } from "./browserManager.js";
22
23
  // ── PQ (SMPTE 2084) OETF ─────────────────────────────────────────────────────
23
24
  const PQ_M1 = 0.1593017578125;
@@ -183,7 +184,7 @@ export async function launchHdrBrowser(width, height) {
183
184
  ...sigintLaunchOptions(),
184
185
  headless: false,
185
186
  executablePath: chromePath,
186
- args: buildHdrChromeArgs(width, height),
187
+ args: withHyperframesBrowserMarker(buildHdrChromeArgs(width, height)),
187
188
  });
188
189
  const page = await browser.newPage();
189
190
  await page.setViewport({ width, height });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/engine",
3
- "version": "0.8.193",
3
+ "version": "0.8.195",
4
4
  "description": "Seekable web page to video rendering engine (Puppeteer + FFmpeg)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -50,8 +50,8 @@
50
50
  "linkedom": "^0.18.12",
51
51
  "puppeteer": "^25.8.0",
52
52
  "puppeteer-core": "^25.8.0",
53
- "@hyperframes/core": "^0.8.193",
54
- "@hyperframes/parsers": "^0.8.193"
53
+ "@hyperframes/parsers": "^0.8.195",
54
+ "@hyperframes/core": "^0.8.195"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/node": "^25.0.10",