Skip to main content

Quickstart

This guide will walk you through creating your first Helios composition from scratch. In about 10 minutes, you’ll have a working animated video.
We’ll build a simple canvas animation that you can preview in your browser and render to MP4. This example uses vanilla JavaScript, but Helios works with React, Vue, Svelte, and other frameworks.

What we’re building

A 5-second animation featuring:
  • A circle moving across the screen
  • A rotating square in the center
  • Smooth, frame-perfect playback

Setup your project

1

Create a new project directory

mkdir my-first-helios-video
cd my-first-helios-video
npm init -y
2

Install dependencies

npm install @helios-project/core @helios-project/player vite
This installs:
  • @helios-project/core - The animation engine
  • @helios-project/player - Preview player
  • vite - Development server and bundler
3

Create project files

Create the following file structure:
my-first-helios-video/
├── package.json
├── index.html
└── src/
    └── main.ts

Create your composition

HTML entry point

Create index.html:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My First Helios Video</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        width: 100vw;
        height: 100vh;
        overflow: hidden;
        background: #000;
      }
      #composition-canvas {
        display: block;
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <canvas id="composition-canvas"></canvas>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

Composition logic

Create src/main.ts:
import { Helios, HeliosState } from '@helios-project/core';

const canvas = document.getElementById('composition-canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d')!;

// Setup canvas to match window size
const resizeCanvas = () => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
};

resizeCanvas();
window.addEventListener('resize', resizeCanvas);

// Video configuration
const duration = 5; // seconds
const fps = 30;

// Initialize Helios engine
const helios = new Helios({
  duration,
  fps,
});

// Bind to document timeline so the player can drive us
helios.bindToDocumentTimeline();

// Draw function - called on every frame update
function draw(currentFrame: number) {
  const time = currentFrame / fps * 1000; // Convert to milliseconds
  const progress = (time % (duration * 1000)) / (duration * 1000); // 0 to 1

  const { width, height } = canvas;

  // Clear canvas
  ctx.fillStyle = '#111';
  ctx.fillRect(0, 0, width, height);

  // Draw moving circle
  const x = progress * width;
  const y = height / 2;
  const radius = 50;

  ctx.fillStyle = 'royalblue';
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2);
  ctx.fill();

  // Draw rotating square
  const squareSize = 100;
  ctx.save();
  ctx.translate(width / 2, height / 2);
  ctx.rotate(progress * Math.PI * 2);
  ctx.fillStyle = 'tomato';
  ctx.fillRect(-squareSize / 2, -squareSize / 2, squareSize, squareSize);
  ctx.restore();
}

// Subscribe to Helios state changes
helios.subscribe((state: HeliosState) => {
  draw(state.currentFrame);
});

// Expose helios globally for debugging and player control
declare global {
  interface Window {
    helios: Helios;
  }
}
window.helios = helios;

Understanding the code

Let’s break down what’s happening:
1

Initialize Helios

const helios = new Helios({
  duration: 5,  // 5 second video
  fps: 30,      // 30 frames per second = 150 total frames
});
This creates a Helios instance that manages the animation timeline.
2

Bind to document timeline

helios.bindToDocumentTimeline();
This connects Helios to the browser’s native animation system, allowing the player and renderer to control playback.
3

Subscribe to frame updates

helios.subscribe((state: HeliosState) => {
  draw(state.currentFrame);
});
Every time Helios updates (play, pause, seek), your draw function is called with the current frame number.
4

Calculate progress

const progress = (time % (duration * 1000)) / (duration * 1000);
Convert the current frame to a 0-1 progress value. This makes it easy to animate properties smoothly.
5

Expose to window

window.helios = helios;
The player and renderer look for window.helios to control your composition.

Preview your composition

1

Add dev script to package.json

{
  "scripts": {
    "dev": "vite"
  }
}
2

Start the dev server

npm run dev
Open your browser to http://localhost:5173. You should see your animation!
3

Test the preview controls

Open your browser console and try:
// Play the animation
helios.play();

// Pause
helios.pause();

// Jump to frame 75 (middle of the video)
helios.seek(75);

// Get current state
console.log(helios.getState());

Add the player component

For a better preview experience with UI controls, use the Helios Player:
1

Create a player HTML file

Create preview.html:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Helios Player Preview</title>
  </head>
  <body>
    <helios-player 
      src="./index.html" 
      width="1920" 
      height="1080"
    ></helios-player>
    
    <script type="module">
      import '@helios-project/player';
    </script>
  </body>
</html>
2

Preview with player controls

Navigate to http://localhost:5173/preview.htmlYou now have:
  • Play/pause button
  • Seek bar
  • Frame counter
  • Export options
The player loads your composition in a sandboxed iframe, providing isolation and standard HTMLMediaElement controls.

Render to video

Now let’s render your composition to an MP4 file.
1

Install the renderer

npm install @helios-project/renderer
2

Create a render script

Create render.ts:
import { Renderer } from '@helios-project/renderer';
import { resolve } from 'path';

const renderer = new Renderer({
  width: 1920,
  height: 1080,
  fps: 30,
  mode: 'canvas', // Use canvas rendering strategy
});

const compositionUrl = `file://${resolve('./dist/index.html')}`;
const outputPath = './output.mp4';

console.log('Starting render...');

await renderer.render(compositionUrl, outputPath);

console.log(`Video saved to ${outputPath}`);
3

Update package.json scripts

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "render": "npm run build && npx tsx render.ts"
  }
}
4

Install tsx for running TypeScript

npm install -D tsx
5

Render your video

npm run render
This will:
  1. Build your composition with Vite
  2. Launch headless Chrome
  3. Capture each frame
  4. Encode to MP4 with FFmpeg
Your video will be saved as output.mp4!
Make sure your composition is built before rendering. The renderer needs the bundled files, not source files.

Using animation helpers

Helios includes powerful animation utilities. Let’s enhance our composition:
import { Helios, interpolate, spring } from '@helios-project/core';

helios.subscribe((state: HeliosState) => {
  const { currentFrame } = state;
  
  // Smooth easing with interpolate
  const x = interpolate(
    currentFrame,
    [0, 150],           // Input range (frames)
    [0, canvas.width],  // Output range (pixels)
    { easing: (t) => t * t * (3 - 2 * t) } // Smoothstep easing
  );
  
  // Spring physics for bounce
  const scale = spring({
    frame: currentFrame,
    fps: 30,
    from: 1,
    to: 2,
    config: { tension: 300, friction: 10 }
  });
  
  // Draw with animated values
  ctx.save();
  ctx.translate(x, canvas.height / 2);
  ctx.scale(scale, scale);
  
  ctx.fillStyle = 'royalblue';
  ctx.beginPath();
  ctx.arc(0, 0, 50, 0, Math.PI * 2);
  ctx.fill();
  
  ctx.restore();
});

Available helpers

import { interpolate } from '@helios-project/core';

// Linear interpolation
const opacity = interpolate(
  currentFrame,
  [0, 30],    // Frames 0-30
  [0, 1],     // Opacity 0-100%
);

// With easing
const x = interpolate(
  currentFrame,
  [0, 150],
  [0, 1920],
  { easing: (t) => Math.pow(t, 2) } // Ease in quad
);

// Clamp extrapolation
const scale = interpolate(
  currentFrame,
  [30, 60],
  [1, 2],
  { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' }
);

Next steps

Explore examples

Check out 80+ examples in the GitHub repository covering:
  • GSAP animations
  • Three.js 3D scenes
  • Chart.js visualizations
  • Lottie animations
  • Framer Motion
  • And more

Learn the API

Dive deeper into Helios capabilities:
  • Audio tracks and mixing
  • Captions and subtitles
  • Input props and schemas
  • Timeline markers
  • Distributed rendering

Framework integration

Use Helios with your preferred framework:
  • React with useVideoFrame() hook
  • Vue with composables
  • Svelte with stores
  • Solid.js integration

Production rendering

Deploy Helios for scale:
  • Docker containerization
  • AWS Lambda distributed rendering
  • Google Cloud Run
  • Local orchestrator for parallel rendering

Troubleshooting

Canvas is blank

Make sure you:
  1. Resize the canvas to match the window
  2. Clear the canvas before drawing
  3. Subscribe to Helios state updates

Animation doesn’t update

Verify that:
  1. helios.bindToDocumentTimeline() is called
  2. window.helios is exposed
  3. You’re calling helios.play() or seeking manually

Render produces black frames

Check that:
  1. Your composition is built (npm run build)
  2. The composition URL is correct (use file:// protocol)
  3. The canvas has proper dimensions

TypeScript errors

Add type declarations:
declare global {
  interface Window {
    helios: Helios;
  }
}

Tips for success

1

Start simple

Begin with basic shapes and movements. Add complexity gradually.
2

Use progress values

Convert frames to 0-1 progress for easier math:
const progress = currentFrame / (duration * fps);
3

Preview often

The dev server provides instant feedback. Use it liberally.
4

Expose to window

Always export window.helios so the player and renderer can control your composition.
5

Test different frame rates

30fps is standard, but try 60fps for smoother motion or 24fps for a cinematic feel.
Congratulations! You’ve created your first Helios video. The same patterns you learned here scale to complex, production-ready compositions.

Build docs developers (and LLMs) love