fix(engine): Linux GPU path uses deprecated EGL + NVENC probe fails on data-center GPUs (#1504)

* fix(engine): use ANGLE-EGL for Linux GPU path, bump NVENC probe size

Chrome 131+ rejects --use-gl=egl in headless shell; the GPU process
exits and the renderer silently falls back to SwiftShader. Switch to
(gl=angle, angle=gl-egl) which is on the headless-shell allowlist,
and add --ignore-gpu-blocklist + --disable-software-rasterizer so
data-center GPUs (L4/T4/A10) are not blocked.

Also bump the NVENC probe frame from 16×16 to 320×240 — NVIDIA
data-center cards require ≥257 on each dimension and reject the
smaller size with "Frame Dimension less than the minimum supported
value", causing the encoder probe to silently fall back to libx264.

Closes #1493

* fix(engine): address review feedback — probe test, observability, comments

- Export getProbeArgs and add test pinning 320×240 probe dimensions
  across all 5 GPU encoder backends (nvenc/videotoolbox/vaapi/qsv/amf)
- Add driver/SKU rationale comment on the probe size constant with
  context about NVIDIA data-center card behavior vs documented minimums
- Add rationale comment on --ignore-gpu-blocklist (operator opted into
  hardware mode explicitly)
- Log resolved GL flags at browser launch for GPU fallback observability
This commit is contained in:
Miguel Ángel
2026-06-16 12:07:04 -04:00
committed by GitHub
parent 479184ecf0
commit e5346afdd8
4 changed files with 43 additions and 7 deletions
@@ -3,6 +3,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import {
getCompiledGpuEncoders,
getGpuEncoderName,
getProbeArgs,
mapPresetForGpuEncoder,
selectUsableGpuEncoder,
} from "./gpuEncoder.js";
@@ -127,3 +128,13 @@ describe("mapPresetForGpuEncoder", () => {
});
});
});
describe("getProbeArgs", () => {
it("uses 320x240 probe dimensions for all GPU encoders", () => {
const encoders = ["nvenc", "videotoolbox", "vaapi", "qsv", "amf"] as const;
for (const encoder of encoders) {
const args = getProbeArgs(encoder);
expect(args).toContain("color=size=320x240:rate=1:duration=1");
}
});
});
+12 -2
View File
@@ -108,7 +108,17 @@ export function getGpuEncoderName(encoder: GpuEncoder, codec: "h264" | "h265"):
}
}
function getProbeArgs(encoder: ConcreteGpuEncoder): string[] {
// Minimum probe dimensions must clear every GPU encoder's hardware minimum.
// NVIDIA data-center SKUs (L4/T4/A10/A100) reject frames below ~257px on
// either dimension with "Frame Dimension less than the minimum supported
// value" (observed on driver 595.58.03, CUDA 13.2). The documented SDK
// minimums (145×49 H.264, 129×33 HEVC) are lower, but the driver enforces
// a stricter per-SKU alignment. 320×240 clears all known GPU encoder
// minimums (NVENC, VideoToolbox, VAAPI, QSV, AMF) while staying cheap.
const GPU_PROBE_WIDTH = 320;
const GPU_PROBE_HEIGHT = 240;
export function getProbeArgs(encoder: ConcreteGpuEncoder): string[] {
const args = [
"-hide_banner",
"-loglevel",
@@ -116,7 +126,7 @@ function getProbeArgs(encoder: ConcreteGpuEncoder): string[] {
"-f",
"lavfi",
"-i",
"color=size=16x16:rate=1:duration=1",
`color=size=${GPU_PROBE_WIDTH}x${GPU_PROBE_HEIGHT}:rate=1:duration=1`,
"-frames:v",
"1",
"-an",