> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/BintzGavin/helios/llms.txt
> Use this file to discover all available pages before exploring further.

# Performance tuning

> Optimizing Helios compositions for fast rendering and smooth previews

## Overview

Helios is designed for production-grade video rendering. This guide covers performance optimization strategies for both preview and render workflows.

## Rendering performance

### Choose the right rendering path

Helios supports two rendering modes:

**Canvas mode** (faster)

* Direct WebCodecs encoding
* GPU-accelerated
* Best for: Three.js, Pixi.js, Canvas API

**DOM mode** (versatile)

* Screenshots HTML/CSS/SVG
* Works with any web content
* Best for: Text, layouts, complex CSS

```typescript theme={null}
import { Renderer } from '@helios-project/renderer';

// Canvas mode (default)
const renderer = new Renderer({ mode: 'canvas' });

// DOM mode
const renderer = new Renderer({ mode: 'dom' });
```

### Enable hardware acceleration

GPU acceleration is enabled by default, but you can verify:

```typescript theme={null}
const diagnostics = await renderer.diagnose();

console.log('Hardware Encoders:', diagnostics.browser.codecs);
console.log('FFmpeg HW Accel:', diagnostics.ffmpeg.hwaccels);
```

Supported hardware acceleration:

* **H.264** - Most common, best compatibility
* **VP8/VP9** - WebM format
* **AV1** - Newer, better compression (slower)

### Bitrate and quality

Higher bitrate = better quality but larger files:

```typescript theme={null}
const renderer = new Renderer({
  mode: 'canvas',
  ffmpegConfig: {
    videoBitrate: '5M',  // 5 Mbps (high quality)
    // '2M' = medium quality
    // '10M' = very high quality
  }
});
```

### Codec selection

H.264 provides the best speed/quality balance:

```typescript theme={null}
const renderer = new Renderer({
  mode: 'canvas',
  ffmpegConfig: {
    videoCodec: 'libx264',
    preset: 'medium',  // slow/medium/fast/ultrafast
    crf: 23,           // 0-51 (lower = better quality)
  }
});
```

**Preset recommendations:**

* `ultrafast` - Quick tests (low quality)
* `medium` - Production (balanced)
* `slow` - Final export (best quality)

### Frame rate optimization

Lower frame rates render faster:

```typescript theme={null}
const helios = new Helios({
  duration: 10,
  fps: 30  // Use 30 instead of 60 if motion blur isn't critical
});
```

**Frame rate guidelines:**

* **24 fps** - Cinematic look
* **30 fps** - Standard web video
* **60 fps** - Smooth motion, gaming

### Resolution optimization

Render at target resolution, not higher:

```typescript theme={null}
const helios = new Helios({
  width: 1920,
  height: 1080,
  duration: 10,
  fps: 30
});

canvas.width = 1920;
canvas.height = 1080;
```

<Warning>
  Avoid rendering at 4K and downscaling to 1080p. Render at 1080p directly for 4x faster encodes.
</Warning>

## Preview performance

### Disable autoplay animations

Helios controls timing, so disable auto-playing animations:

```css theme={null}
/* Good: Helios controls timing */
.box {
  animation: fadeIn 1s forwards paused;
}

/* Bad: Animation plays independently */
.box {
  animation: fadeIn 1s forwards;
}
```

Use `autoSyncAnimations: true` to automatically pause animations:

```typescript theme={null}
const helios = new Helios({
  duration: 10,
  fps: 30,
  autoSyncAnimations: true  // Pauses all WAAPI animations
});
```

### Use requestAnimationFrame efficiently

Helios uses `RafTicker` by default, which is optimized for browser rendering:

```typescript theme={null}
import { Helios, RafTicker } from '@helios-project/core';

const helios = new Helios({
  duration: 10,
  fps: 30,
  ticker: new RafTicker()  // Default
});
```

For Node.js or testing, use `TimeoutTicker`:

```typescript theme={null}
import { TimeoutTicker } from '@helios-project/core';

const helios = new Helios({
  ticker: new TimeoutTicker()
});
```

### Debounce expensive operations

Avoid recalculating on every frame if not needed:

```typescript theme={null}
let cachedValue: number;
let lastFrame = -1;

helios.subscribe((state) => {
  // Only recalculate every 10 frames
  if (state.currentFrame % 10 === 0 || state.currentFrame !== lastFrame) {
    cachedValue = expensiveCalculation(state);
    lastFrame = state.currentFrame;
  }
  
  applyValue(cachedValue);
});
```

### Optimize asset loading

Preload assets before starting playback:

```typescript theme={null}
const helios = new Helios({ duration: 10, fps: 30 });

// Wait for all assets to load
await helios.waitUntilStable();

// Now start playback
helios.play();
```

The `waitUntilStable()` method waits for:

* Fonts (`document.fonts.ready`)
* Images (`img.decode()`)
* Audio/video metadata

### Shadow DOM performance

`DomDriver` automatically discovers shadow roots, but deep nesting impacts performance:

```typescript theme={null}
// Good: Flat structure
<div>
  <my-component></my-component>
</div>

// Slower: Deep shadow DOM nesting
<level-1>
  <level-2>
    <level-3>
      <level-4>...</level-4>
    </level-3>
  </level-2>
</level-1>
```

## Memory optimization

### Dispose resources

Always clean up when done:

```typescript theme={null}
const helios = new Helios({ duration: 10, fps: 30 });

// Use composition
helios.play();

// Clean up when done
helios.dispose();
```

For Three.js, dispose geometries and materials:

```typescript theme={null}
scene.traverse((obj) => {
  if (obj instanceof THREE.Mesh) {
    obj.geometry.dispose();
    if (Array.isArray(obj.material)) {
      obj.material.forEach(m => m.dispose());
    } else {
      obj.material.dispose();
    }
  }
});

renderer.dispose();
```

### Reuse objects

Avoid creating new objects every frame:

```typescript theme={null}
// Bad: Creates garbage
helios.subscribe(() => {
  const vec = new THREE.Vector3(x, y, z);
  cube.position.copy(vec);
});

// Good: Reuse
const vec = new THREE.Vector3();
helios.subscribe(() => {
  vec.set(x, y, z);
  cube.position.copy(vec);
});
```

### Limit subscriber count

Each subscriber adds overhead:

```typescript theme={null}
// Bad: Multiple subscribers
helios.subscribe(() => updateBox());
helios.subscribe(() => updateCircle());
helios.subscribe(() => updateText());

// Good: Single subscriber
helios.subscribe(() => {
  updateBox();
  updateCircle();
  updateText();
});
```

## Distributed rendering

For large projects, use distributed rendering:

```bash theme={null}
# Generate job spec
helios render composition.html --emit-job job.json

# Run distributed job
helios job run job.json --chunks 4
```

This splits rendering across multiple workers for 4x speedup.

### Chunk size optimization

More chunks = more parallelism, but more overhead:

```bash theme={null}
# Short video (< 30s): 2-4 chunks
helios job run job.json --chunks 4

# Medium video (30s - 2m): 8-16 chunks
helios job run job.json --chunks 16

# Long video (> 2m): 32+ chunks
helios job run job.json --chunks 32
```

**Rule of thumb:** 1 chunk per 10-15 seconds of video

## Profiling and debugging

### Measure render time

```typescript theme={null}
const start = Date.now();

await renderer.render('composition.html', 'output.mp4');

const duration = Date.now() - start;
console.log(`Rendered in ${duration}ms`);
```

### Monitor frame budget

Each frame has a time budget. For 30fps, that's 33.3ms per frame:

```typescript theme={null}
let slowFrames = 0;

helios.subscribe((state) => {
  const frameStart = performance.now();
  
  // Your rendering code
  renderer.render(scene, camera);
  
  const frameTime = performance.now() - frameStart;
  const budget = 1000 / state.fps;
  
  if (frameTime > budget) {
    console.warn(`Frame ${state.currentFrame} over budget: ${frameTime.toFixed(2)}ms`);
    slowFrames++;
  }
});

console.log(`Slow frames: ${slowFrames}`);
```

### Diagnose bottlenecks

Use Chrome DevTools to profile:

```bash theme={null}
# Run with remote debugging
helios render composition.html --no-headless
```

Then:

1. Open `chrome://inspect`
2. Click "inspect" on your composition
3. Use Performance tab to record

### Check diagnostics

```typescript theme={null}
const report = await Helios.diagnose();

console.log('WebCodecs:', report.webCodecs);
console.log('WebGL:', report.webgl);
console.log('WebGL2:', report.webgl2);
console.log('H.264:', report.videoCodecs.h264);
console.log('VP9:', report.videoCodecs.vp9);
console.log('User Agent:', report.userAgent);
```

## Benchmarking examples

Typical render speeds on modern hardware (M1 MacBook Pro):

| Composition        | Mode   | Resolution | FPS | Real-time Factor |
| ------------------ | ------ | ---------- | --- | ---------------- |
| DOM (CSS)          | DOM    | 1080p      | 30  | 0.5x (slower)    |
| Canvas (2D)        | Canvas | 1080p      | 30  | 2-3x (faster)    |
| Three.js (simple)  | Canvas | 1080p      | 30  | 1-2x             |
| Three.js (complex) | Canvas | 1080p      | 30  | 0.5-1x           |
| Pixi.js            | Canvas | 1080p      | 60  | 2-4x             |

**Real-time factor:**

* `1x` = Renders as fast as playback (10s video in 10s)
* `2x` = Renders twice as fast (10s video in 5s)
* `0.5x` = Renders half speed (10s video in 20s)

## Performance checklist

**Rendering:**

* ✅ Use canvas mode for canvas-heavy compositions
* ✅ Enable GPU acceleration
* ✅ Choose appropriate bitrate (2-5 Mbps for 1080p)
* ✅ Use H.264 codec for best compatibility
* ✅ Render at target resolution (don't downscale)
* ✅ Use distributed rendering for videos > 30s

**Preview:**

* ✅ Set `autoSyncAnimations: true`
* ✅ Preload assets with `waitUntilStable()`
* ✅ Use single subscriber when possible
* ✅ Avoid per-frame allocations
* ✅ Reuse Three.js geometries and materials

**Memory:**

* ✅ Call `helios.dispose()` when done
* ✅ Dispose Three.js resources
* ✅ Reuse objects instead of creating new ones
* ✅ Clear intervals and event listeners

## Next steps

* Learn about [custom drivers](/advanced/custom-drivers) for specialized workflows
* Optimize [canvas and WebGL](/advanced/canvas-webgl) rendering
* Debug performance with [diagnostics](/advanced/debugging)
