Merge pull request #2359 from heygen-com/via/issue-3-software-gpu-screenshot

fix(engine): software-GPU browsers imply screenshot capture
This commit is contained in:
Vance Ingalls
2026-07-13 20:37:12 -07:00
committed by GitHub
5 changed files with 385 additions and 7 deletions
+23 -5
View File
@@ -43,7 +43,7 @@ import {
produceDrawElementFrameBatch,
} from "./drawElementService.js";
import { initThreeDProjection, detectCssEffectRisk } from "./threeDProjection.js";
import { DEFAULT_CONFIG, type EngineConfig } from "../config.js";
import { DEFAULT_CONFIG, applyConcreteGpuScreenshotClamp, type EngineConfig } from "../config.js";
import type {
CaptureOptions,
CaptureVideoMetadataHint,
@@ -815,15 +815,33 @@ export async function createCaptureSession(
// need explicit clip+scale on `Page.captureScreenshot`, so fall back to
// the screenshot path for any DPR > 1.
const supersampling = (options.deviceScaleFactor ?? 1) > 1;
const preMode: CaptureMode =
headlessShell && isLinux && !forceScreenshot && !supersampling && !drawElementTransparent
? "beginframe"
: "screenshot";
const requestedGpuMode = config?.browserGpuMode ?? DEFAULT_CONFIG.browserGpuMode;
const resolvedGpuMode = await resolveBrowserGpuMode(requestedGpuMode, {
chromePath: headlessShell ?? undefined,
browserTimeout: config?.browserTimeout,
});
// Apply the software-GPU→screenshot invariant at the concrete-resolved
// point too — `resolveConfig` can only see the pre-resolve `browserGpuMode`
// string, so `"auto"` that probes to software would otherwise slip through
// and launch BeginFrame + SwiftShader (the exact combination the invariant
// is meant to prevent). Both env and programmatic opt-outs preserved via
// `applyConcreteGpuScreenshotClamp` (the programmatic one carried on the
// config as `forceScreenshotExplicitlyOptedOut`, since at this point the
// boolean `forceScreenshot === false` is otherwise ambiguous between
// default and explicit opt-out).
const effectiveForceScreenshot = applyConcreteGpuScreenshotClamp(
forceScreenshot,
resolvedGpuMode,
config,
);
const preMode: CaptureMode =
headlessShell &&
isLinux &&
!effectiveForceScreenshot &&
!supersampling &&
!drawElementTransparent
? "beginframe"
: "screenshot";
const chromeArgs = buildChromeArgs(
{ width: options.width, height: options.height, captureMode: preMode },
{ ...config, browserGpuMode: resolvedGpuMode },