Skip to main content

Overview

Helios uses a driver-based architecture to synchronize animations across different rendering contexts. The TimeDriver interface allows you to create custom implementations for specialized workflows beyond DOM and canvas.

TimeDriver interface

All drivers must implement the TimeDriver interface:

Required methods

init(scope: unknown) Called once when the Helios instance is created. Use this to set up your rendering context.
update(timeInMs: number, options) Called every frame to synchronize your rendering context to the given time.
waitUntilStable() Return a promise that resolves when all assets are loaded and ready to render.

Optional methods

dispose() - Clean up resources when the instance is destroyed subscribeToMetadata(callback) - Notify Helios about discovered audio tracks getAudioContext() - Return Web Audio API context for mixing getAudioSourceNode(trackId) - Return audio source node for a specific track

Built-in drivers

DomDriver

The default driver for HTML/CSS animations. It:
  • Scans for animations using document.getAnimations()
  • Seeks animations via animation.currentTime
  • Discovers shadow DOM boundaries
  • Syncs <audio> and <video> elements
  • Tracks audio metadata with data-helios-track-id

NoopDriver

A no-op driver that does nothing. Useful for:
  • Pure canvas compositions with manual timing
  • Testing
  • Headless environments without DOM

Creating a custom driver

Example: Three.js driver

Here’s a custom driver for synchronizing Three.js animations:

Using the custom driver

Custom tickers

Drivers control where animations happen. Tickers control when frames are rendered during preview.

Ticker interface

Built-in tickers

RafTicker - Uses requestAnimationFrame (default for browser) TimeoutTicker - Uses setTimeout for Node.js environments ManualTicker - Allows manual frame stepping for tests

Example: Fixed timestep ticker

Audio track discovery

Drivers can notify Helios about audio tracks for mixing and export.
Custom drivers must be deterministic. The same timeInMs should always produce identical visual output, regardless of how many times update() is called or in what order.

Best practices

Use existing drivers when possible - DomDriver handles most HTML/CSS/SVG use cases Make drivers stateless - Don’t accumulate state across update() calls Handle disposal properly - Clean up event listeners, contexts, and resources Test with manual ticker - Use ManualTicker to verify frame-perfect accuracy Document scope requirements - Make it clear what animationScope should contain

Next steps