Skip to main content
Helios provides precise control over video playback and timeline navigation through a clean, imperative API.

Core timeline concepts

Time representations

Helios uses two primary time representations:
  • Frames: Integer frame numbers (0, 1, 2, …)
  • Seconds: Floating-point time values (0.0, 0.033, 0.067, …)
The relationship is always: time = frame / fps

Reactive state

All timeline state is exposed as signals for reactive programming:
See packages/core/src/Helios.ts:123 for signal definitions.

Playback controls

Play and pause

Playback implementation at Helios.ts:885:

Seeking

Frames are automatically clamped to [0, duration * fps].

Looping

Loop logic at Helios.ts:1229:

Playback rate

Control playback speed:
Playback rate affects:
  • Frame advancement during play()
  • Audio/video element playback (via drivers)
  • Animation speed (when using time-based animations)
Playback rate does not affect seeking. seek(100) always jumps to frame 100 regardless of playback rate.

Playback range

Limit playback to a specific frame range:
Playback range affects:
  • Where play() starts (at range start)
  • Where playback stops (at range end)
  • Loop boundaries (wraps within range)
See Helios.ts:832 for playback range API.

Timeline binding

Helios can be driven by different time sources:

Standalone playback (default)

Uses a ticker (RAF or setTimeout) to advance frames.

Bound to document timeline

Critical for server-side rendering: The renderer sets __HELIOS_VIRTUAL_TIME__ via CDP, and bound instances automatically sync to it. See Helios.ts:1085 for binding implementation.
When bound to document timeline, calling play() has no effect—time is controlled externally.

Bound to another Helios instance

See Helios.ts:994 for instance binding.

Unbinding

Frame-accurate rendering

For deterministic rendering, Helios provides a RenderSession API:
See packages/core/src/render-session.ts:9 for implementation.

Stability waiting

Before capturing each frame, wait for all async operations to complete:
Stability checks at Helios.ts:943:
This waits for:
  1. Driver stability (fonts, images, media)
  2. Custom registered checks
  3. Virtual time sync (if bound to document timeline)

State subscription

Subscribe to all state changes at once:
Full state type at Helios.ts:9:

Dynamic configuration

Most configuration can be changed at runtime:

Duration and FPS

Changing FPS recalculates the current frame to maintain the same time position. For example, if you’re at 3 seconds (frame 90 at 30fps), changing to 60fps moves you to frame 180.

Dimensions

Useful for responsive compositions or multi-resolution rendering.

Advanced timeline patterns

Scrubbing with momentum

Time remapping

Frame-by-frame control

Performance considerations

Seeking performance

Seeking triggers:
  1. Signal updates (fast)
  2. Driver sync (may trigger layout/paint)
  3. Subscriber callbacks (depends on your code)
For high-frequency scrubbing, debounce expensive operations:

Batch updates

Multiple state changes can be batched:
Helios signals already batch updates efficiently—subscribers only run once per transaction.

Next steps