Skip to content

Commit e0c8a4b

Browse files
committed
fix(cli): keep browser gpu opt-in for local renders
1 parent 3aa5cf3 commit e0c8a4b

6 files changed

Lines changed: 24 additions & 22 deletions

File tree

docs/guides/rendering.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4, MOV, or W
6565

6666
**Pros:**
6767
- Fast startup, no container overhead
68-
- Can use your system GPU for Chrome/WebGL capture by default
68+
- Uses software Chrome/WebGL capture by default for stable frame output
69+
- Can opt into your system GPU for Chrome/WebGL capture with `--browser-gpu`
6970
- Can use your system GPU for hardware-accelerated encoding (with `--gpu`)
7071
- Best for iterative development
7172

@@ -124,7 +125,7 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4, MOV, or W
124125
| `--workers` | 1-8 or `auto` | auto | Parallel render workers (see [Workers](#workers) below) |
125126
| `--max-concurrent-renders` | 1-10 | 2 | Max simultaneous renders via the producer server (see [Concurrent Renders](#concurrent-renders) below) |
126127
| `--gpu` || off | GPU encoding (NVENC, VideoToolbox, VAAPI, QSV) |
127-
| `--browser-gpu` / `--no-browser-gpu` || on locally, off in Docker | Use or opt out of host GPU acceleration for local Chrome/WebGL capture |
128+
| `--browser-gpu` / `--no-browser-gpu` || software | Use or opt out of host GPU acceleration for local Chrome/WebGL capture. Set `PRODUCER_BROWSER_GPU_MODE=auto` to probe hardware availability |
128129
| `--hdr` || off | Force HDR output even if no HDR sources are detected (MP4 only). See [HDR Rendering](/guides/hdr) |
129130
| `--sdr` || off | Force SDR output even if HDR sources are detected |
130131
| `--docker` || off | Use Docker for [deterministic rendering](/concepts/determinism) |

docs/packages/cli.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,8 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
597597
# With options
598598
npx hyperframes render --output output.mp4 --fps 60 --quality high
599599

600-
# Opt out of local browser GPU capture
601-
npx hyperframes render --no-browser-gpu --output cpu-browser.mp4
600+
# Opt in to local browser GPU capture
601+
npx hyperframes render --browser-gpu --output gpu-browser.mp4
602602

603603
# Add hardware FFmpeg encoding
604604
npx hyperframes render --gpu --output gpu.mp4
@@ -617,7 +617,7 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
617617
| `--sdr` || off | Force SDR output even if HDR sources are detected |
618618
| `--workers` | 1-8 | 4 | Parallel render workers |
619619
| `--gpu` || off | GPU encoding (NVENC, VideoToolbox, VAAPI, QSV) |
620-
| `--browser-gpu` / `--no-browser-gpu` || on locally, off in Docker | Use or opt out of host GPU acceleration for local Chrome/WebGL capture |
620+
| `--browser-gpu` / `--no-browser-gpu` || software | Use or opt out of host GPU acceleration for local Chrome/WebGL capture. Set `PRODUCER_BROWSER_GPU_MODE=auto` to probe hardware availability |
621621
| `--docker` || off | Use Docker for [deterministic rendering](/concepts/determinism) |
622622
| `--quiet` || off | Suppress verbose output |
623623
| `--variables` | JSON object || Variable overrides merged over `data-composition-variables` defaults. Read via `window.__hyperframes.getVariables()` |

docs/packages/producer.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ When GPU encoding is enabled, Hyperframes detects the available FFmpeg hardware
226226
npx hyperframes doctor
227227
```
228228

229-
The CLI enables local Chrome/WebGL GPU capture automatically and supports `--no-browser-gpu` as an opt-out. When using the producer API directly, pass an engine config override:
229+
The CLI uses software Chrome/WebGL capture by default for stable cross-platform frame output. Use `--browser-gpu` to opt into host GPU capture, or set `PRODUCER_BROWSER_GPU_MODE=auto` to probe hardware availability and fall back to software. When using the producer API directly, pass an engine config override:
230230

231231
```typescript
232232
import { resolveConfig } from '@hyperframes/producer';

packages/cli/src/commands/render.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe("renderLocal browser GPU config", () => {
8484
});
8585
}, 15_000);
8686

87-
it("forwards browserGpuMode='auto' into producer config (probe-then-choose)", async () => {
87+
it("forwards browserGpuMode='auto' into producer config when explicitly requested by a caller", async () => {
8888
await renderLocal("/tmp/project", "/tmp/out.mp4", {
8989
fps: { num: 30, den: 1 },
9090
quality: "standard",
@@ -102,7 +102,7 @@ describe("renderLocal browser GPU config", () => {
102102
});
103103
});
104104

105-
it("passes an explicit hardware override for default local browser GPU", async () => {
105+
it("passes an explicit hardware override for --browser-gpu", async () => {
106106
await renderLocal("/tmp/project", "/tmp/out.mp4", {
107107
fps: { num: 30, den: 1 },
108108
quality: "standard",
@@ -121,8 +121,8 @@ describe("renderLocal browser GPU config", () => {
121121
});
122122

123123
it("resolves browser GPU from CLI flags, Docker mode, and env fallback", () => {
124-
// Default (no flag, no env): auto — engine probes and chooses.
125-
expect(resolveBrowserGpuForCli(false, undefined, undefined)).toBe("auto");
124+
// Default (no flag, no env): software for stable cross-platform captures.
125+
expect(resolveBrowserGpuForCli(false, undefined, undefined)).toBe("software");
126126
// Env override
127127
expect(resolveBrowserGpuForCli(false, undefined, "hardware")).toBe("hardware");
128128
expect(resolveBrowserGpuForCli(false, undefined, "software")).toBe("software");

packages/cli/src/commands/render.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const examples: Example[] = [
1818
["High quality at 60fps", "hyperframes render --fps 60 --quality high --output hd.mp4"],
1919
["Deterministic render via Docker", "hyperframes render --docker --output deterministic.mp4"],
2020
["Parallel rendering with 6 workers", "hyperframes render --workers 6 --output fast.mp4"],
21-
["Opt out of browser GPU render", "hyperframes render --no-browser-gpu --output cpu.mp4"],
21+
["Opt in to browser GPU render", "hyperframes render --browser-gpu --output gpu-browser.mp4"],
2222
["HDR output (auto-detected)", "hyperframes render --output hdr-output.mp4"],
2323
[
2424
"Override composition variables (parametrized render)",
@@ -180,7 +180,7 @@ export default defineCommand({
180180
"browser-gpu": {
181181
type: "boolean",
182182
description:
183-
"Force host GPU acceleration for Chrome/WebGL capture. Default: auto (probe on first launch; fall back to software if no GPU). Use --no-browser-gpu to force software (SwiftShader).",
183+
"Force host GPU acceleration for Chrome/WebGL capture. Default: software (SwiftShader) for stable cross-platform frame capture. Set PRODUCER_BROWSER_GPU_MODE=auto to probe hardware availability.",
184184
},
185185
quiet: {
186186
type: "boolean",
@@ -570,8 +570,8 @@ interface RenderOptions {
570570
gpu: boolean;
571571
/**
572572
* Chrome WebGL backend mode. "auto" probes on first launch and falls back
573-
* to "software" if no usable GPU. Defaults to "software" when omitted to
574-
* stay backwards-compatible with callers that pre-date the tri-state.
573+
* to "software" if no usable GPU. Defaults to "software" when omitted for
574+
* deterministic local frame capture.
575575
*/
576576
browserGpuMode?: "auto" | "hardware" | "software";
577577
hdrMode: "auto" | "force-hdr" | "force-sdr";
@@ -734,12 +734,13 @@ export function validateVariablesAgainstProject(
734734
* `--no-browser-gpu` → "software".
735735
* 3. Env var `PRODUCER_BROWSER_GPU_MODE` accepts "hardware" / "software" /
736736
* "auto".
737-
* 4. Default = "auto" — engine probes WebGL availability on first launch
738-
* and falls back to software if the host lacks a usable GPU.
737+
* 4. Default = "software" — deterministic SwiftShader capture unless the
738+
* user explicitly opts into host GPU rendering.
739739
*
740-
* Returning "auto" by default lets local renders Just Work whether or not the
741-
* host has a GPU, while preserving the explicit overrides for CI / power
742-
* users who want failure-on-misconfig.
740+
* Plain DOM renders can hit platform-specific GPU compositor bugs on local
741+
* Chrome, especially on older Apple Silicon. Keep the default aligned with
742+
* the engine's conservative software mode, while preserving explicit hardware
743+
* and env-driven auto probing for power users.
743744
*/
744745
export function resolveBrowserGpuForCli(
745746
useDocker: boolean,
@@ -750,7 +751,7 @@ export function resolveBrowserGpuForCli(
750751
if (browserGpuArg === true) return "hardware";
751752
if (browserGpuArg === false) return "software";
752753
if (envMode === "hardware" || envMode === "software" || envMode === "auto") return envMode;
753-
return "auto";
754+
return "software";
754755
}
755756

756757
const DOCKER_IMAGE_PREFIX = "hyperframes-renderer";

packages/cli/src/docs/rendering.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ Requires: Docker installed and running.
2020
- `--crf` — Override encoder CRF (mutually exclusive with `--video-bitrate`)
2121
- `--video-bitrate` — Target video bitrate such as `10M` (mutually exclusive with `--crf`)
2222
- `--gpu` — Use GPU encoding (NVENC, VideoToolbox, VAAPI, QSV)
23-
- `--browser-gpu` / `--no-browser-gpu` — Force host GPU or software (SwiftShader) for Chrome/WebGL capture. Default for local renders is `auto` — probe WebGL availability on first launch and fall back to software if no GPU is reachable. Docker mode always uses software.
23+
- `--browser-gpu` / `--no-browser-gpu` — Force host GPU or software (SwiftShader) for Chrome/WebGL capture. Local renders default to software for stable cross-platform capture. Set `PRODUCER_BROWSER_GPU_MODE=auto` to probe hardware availability. Docker mode always uses software.
2424
- `-o, --output` — Custom output path
2525

2626
## Tips
2727

2828
- Use `draft` quality for fast previews during development
29-
- Local renders auto-detect GPU on first launch; use `--browser-gpu` to force hardware (errors if no GPU) or `--no-browser-gpu` to force SwiftShader
29+
- Local renders use software Chrome capture by default; use `--browser-gpu` to force hardware (errors if no GPU) or `PRODUCER_BROWSER_GPU_MODE=auto` to probe and fall back to SwiftShader
3030
- Use `--gpu` when a local render also benefits from hardware FFmpeg encoding
3131
- Use `npx hyperframes benchmark` to find optimal settings
3232
- 4 workers is usually the sweet spot for most compositions

0 commit comments

Comments
 (0)