Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/guides/rendering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4, MOV, or W

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

Expand Down Expand Up @@ -124,7 +125,7 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4, MOV, or W
| `--workers` | 1-8 or `auto` | auto | Parallel render workers (see [Workers](#workers) below) |
| `--max-concurrent-renders` | 1-10 | 2 | Max simultaneous renders via the producer server (see [Concurrent Renders](#concurrent-renders) below) |
| `--gpu` | — | off | GPU encoding (NVENC, VideoToolbox, VAAPI, QSV) |
| `--browser-gpu` / `--no-browser-gpu` | — | on locally, off in Docker | Use or opt out of host GPU acceleration for local Chrome/WebGL capture |
| `--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 |
| `--hdr` | — | off | Force HDR output even if no HDR sources are detected (MP4 only). See [HDR Rendering](/guides/hdr) |
| `--sdr` | — | off | Force SDR output even if HDR sources are detected |
| `--docker` | — | off | Use Docker for [deterministic rendering](/concepts/determinism) |
Expand Down
6 changes: 3 additions & 3 deletions docs/packages/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -597,8 +597,8 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
# With options
npx hyperframes render --output output.mp4 --fps 60 --quality high

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

# Add hardware FFmpeg encoding
npx hyperframes render --gpu --output gpu.mp4
Expand All @@ -617,7 +617,7 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
| `--sdr` | — | off | Force SDR output even if HDR sources are detected |
| `--workers` | 1-8 | 4 | Parallel render workers |
| `--gpu` | — | off | GPU encoding (NVENC, VideoToolbox, VAAPI, QSV) |
| `--browser-gpu` / `--no-browser-gpu` | — | on locally, off in Docker | Use or opt out of host GPU acceleration for local Chrome/WebGL capture |
| `--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 |
| `--docker` | — | off | Use Docker for [deterministic rendering](/concepts/determinism) |
| `--quiet` | — | off | Suppress verbose output |
| `--variables` | JSON object | — | Variable overrides merged over `data-composition-variables` defaults. Read via `window.__hyperframes.getVariables()` |
Expand Down
2 changes: 1 addition & 1 deletion docs/packages/producer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ When GPU encoding is enabled, Hyperframes detects the available FFmpeg hardware
npx hyperframes doctor
```

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:
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:

```typescript
import { resolveConfig } from '@hyperframes/producer';
Expand Down
8 changes: 4 additions & 4 deletions packages/cli/src/commands/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe("renderLocal browser GPU config", () => {
});
}, 15_000);

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

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

it("resolves browser GPU from CLI flags, Docker mode, and env fallback", () => {
// Default (no flag, no env): auto — engine probes and chooses.
expect(resolveBrowserGpuForCli(false, undefined, undefined)).toBe("auto");
// Default (no flag, no env): software for stable cross-platform captures.
expect(resolveBrowserGpuForCli(false, undefined, undefined)).toBe("software");
// Env override
expect(resolveBrowserGpuForCli(false, undefined, "hardware")).toBe("hardware");
expect(resolveBrowserGpuForCli(false, undefined, "software")).toBe("software");
Expand Down
21 changes: 11 additions & 10 deletions packages/cli/src/commands/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const examples: Example[] = [
["High quality at 60fps", "hyperframes render --fps 60 --quality high --output hd.mp4"],
["Deterministic render via Docker", "hyperframes render --docker --output deterministic.mp4"],
["Parallel rendering with 6 workers", "hyperframes render --workers 6 --output fast.mp4"],
["Opt out of browser GPU render", "hyperframes render --no-browser-gpu --output cpu.mp4"],
["Opt in to browser GPU render", "hyperframes render --browser-gpu --output gpu-browser.mp4"],
["HDR output (auto-detected)", "hyperframes render --output hdr-output.mp4"],
[
"Override composition variables (parametrized render)",
Expand Down Expand Up @@ -180,7 +180,7 @@ export default defineCommand({
"browser-gpu": {
type: "boolean",
description:
"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).",
"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.",
},
quiet: {
type: "boolean",
Expand Down Expand Up @@ -570,8 +570,8 @@ interface RenderOptions {
gpu: boolean;
/**
* Chrome WebGL backend mode. "auto" probes on first launch and falls back
* to "software" if no usable GPU. Defaults to "software" when omitted to
* stay backwards-compatible with callers that pre-date the tri-state.
* to "software" if no usable GPU. Defaults to "software" when omitted for
* deterministic local frame capture.
*/
browserGpuMode?: "auto" | "hardware" | "software";
hdrMode: "auto" | "force-hdr" | "force-sdr";
Expand Down Expand Up @@ -734,12 +734,13 @@ export function validateVariablesAgainstProject(
* `--no-browser-gpu` → "software".
* 3. Env var `PRODUCER_BROWSER_GPU_MODE` accepts "hardware" / "software" /
* "auto".
* 4. Default = "auto" — engine probes WebGL availability on first launch
* and falls back to software if the host lacks a usable GPU.
* 4. Default = "software" — deterministic SwiftShader capture unless the
* user explicitly opts into host GPU rendering.
*
* Returning "auto" by default lets local renders Just Work whether or not the
* host has a GPU, while preserving the explicit overrides for CI / power
* users who want failure-on-misconfig.
* Plain DOM renders can hit platform-specific GPU compositor bugs on local
* Chrome, especially on older Apple Silicon. Keep the default aligned with
* the engine's conservative software mode, while preserving explicit hardware
* and env-driven auto probing for power users.
*/
export function resolveBrowserGpuForCli(
useDocker: boolean,
Expand All @@ -750,7 +751,7 @@ export function resolveBrowserGpuForCli(
if (browserGpuArg === true) return "hardware";
if (browserGpuArg === false) return "software";
if (envMode === "hardware" || envMode === "software" || envMode === "auto") return envMode;
return "auto";
return "software";
}

const DOCKER_IMAGE_PREFIX = "hyperframes-renderer";
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/docs/rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ Requires: Docker installed and running.
- `--crf` — Override encoder CRF (mutually exclusive with `--video-bitrate`)
- `--video-bitrate` — Target video bitrate such as `10M` (mutually exclusive with `--crf`)
- `--gpu` — Use GPU encoding (NVENC, VideoToolbox, VAAPI, QSV)
- `--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.
- `--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.
- `-o, --output` — Custom output path

## Tips

- Use `draft` quality for fast previews during development
- 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
- 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
- Use `--gpu` when a local render also benefits from hardware FFmpeg encoding
- Use `npx hyperframes benchmark` to find optimal settings
- 4 workers is usually the sweet spot for most compositions
Loading