Open Source · Apache-2.0WebCodecs + WebGL2

Browser-Native
Video Infrastructure

elah provides the timeline, rendering, and editing foundation for professional creative applications built entirely on the web. Engine-first, renderer-agnostic, scalable from prototype to production — in the browser and on your server.

Framework-agnostic core ·Next.jsReactReact Native · experimentalMore frameworks coming soon
Time model
Integer frames
Renderer
WebGL2 / OffscreenCanvas
Decode
WebCodecs + mediabunny
Audio
Web Audio API
elah · Full Editor
MEDIA LIBRARY
intro.mp4
bg-music.mp3
logo.png
title.txt
00:00:02:15
0s
5s
10s
15s
20s
25s
30s
35s
40s
45s
50s
55s
VIDEO
AUDIO
TEXT
Architecture

Built for precision.

Every layer of the stack is designed around one principle: determinism. Same input, same output, every time.

Frame-Accurate Time Model

All time is integer frames — no floating-point drift, no sync bugs. Same project + same frame = same pixels, always.

ImmerZustand

WebCodecs Decode Pipeline

Push-based StreamingFrameProducer with ahead-of-playhead decoding. Frames are copied to ImageBitmap so the hardware output pool never starves.

WebCodecsImageBitmapmediabunny

WebGL2 GPU Renderer

GpuRenderer turns each resolved Scene into sorted textured-quad draws composited by zIndex. Supports VideoLayer, ImageLayer, and TextLayer.

WebGL2OffscreenCanvasGLSL

Pure Resolver Architecture

resolveTimeline(frame, project) → Scene is deterministic and side-effect-free. Runs identically in preview, tests, and export workers.

Pure functionWorker-safe

Zero-Drift Export — Browser & Server

The export worker steps resolveTimeline frame-by-frame in the browser — and @elah/cli runs the exact same pipeline headlessly on your server. Bit-identical output, by construction.

Web WorkerMP4@elah/cli

Interactive Transform Overlays

Click-select, drag-move, corner-drag uniform scale for video and image clips. Text clips support drag, resize, inline-edit, and rotation.

ReactCSS transforms

Full Edit History

Every edit goes through TimelineEngine.commit() — Immer-backed structural sharing with batching, undo/redo, and typed events.

ImmerUndo/Redo

Fade & Transition System

Snapshot-overlay architecture. Resolver sets opacity; CSS handles preview via TransitionOverlay; export mirrors with globalAlpha. Renderer-agnostic.

CSSglobalAlpha

Renderer-Agnostic Core

The data model and resolver know nothing about DOM, Canvas, or WebGL. Swap rendering backends without touching state or timeline logic.

TypeScriptInterfaces
Data Flow

One mutation funnel.
One pure resolver.

REACT UI
TimelinePreviewAssetPanelTransformOverlay
ENGINE LAYER
TimelineEnginePlaybackEngineAudioPlaybackController
PURE RESOLVER
resolveTimeline(frame, project) → Scene
RENDERERS
GpuRenderer (WebGL2)ExportWorker (OffscreenCanvas)
MEDIA PIPELINE
StreamingFrameProducerWebCodecsmediabunny demux
Interactive

Launch a playground.

Explore the editor live. Each playground is a fully functional deployment of the SDK.

live

Full Editor

Complete editor with asset panel, GPU-accelerated preview, interactive overlays, timeline, and export pipeline. The full @elah/editor composition.

WebGL2WebCodecsTimelineExportAudio
Launch Playground
live

Timeline Only

Isolated timeline UI demo. Explore tracks, clips, snapping, keyboard shortcuts, and the TimelineEngine without the full editor stack.

TimelineReactZustand
Launch Playground
preview

Full Editor Demo

Guided demo with pre-loaded sample media. Walks through the major features — cut, trim, text, transitions, and export — in a single session.

Full StackDemoSample Media
Launch Playground
Integration

Drop in. Wire. Ship.

The full editor composes in fewer than 20 lines. Bring your own demuxer factory and the preview handles decode, render, playback, and audio automatically.

EditorProvider wires all engines with a single fps prop

Preview mounts the WebGL2 renderer and drives the RAF loop

Timeline handles all interaction: drag, trim, split, snap

AssetPanel manages the media library and drag-drop import

exportVideo() runs the full pipeline in a dedicated worker

App.tsx@elah/editor
import {
  EditorProvider,
  AssetPanel,
  Preview,
  Timeline,
  createDefaultDemuxerFactory,
} from '@elah/editor'

const demuxerFactory = createDefaultDemuxerFactory()

export default function App() {
  return (
    <EditorProvider fps={30}>
      <div style={{ display: 'flex', height: '100vh',
                    flexDirection: 'column' }}>
        <div style={{ display: 'flex', flex: 1 }}>
          <AssetPanel style={{ width: 240 }} />
          <Preview
            demuxerFactory={demuxerFactory}
            style={{ flex: 1 }}
          />
        </div>
        <Timeline fps={30} style={{ height: 240 }} />
      </div>
    </EditorProvider>
  )
}
FAQ

Common questions.

Does elah need a server to edit or export video?

No — by default everything runs in the browser: decoding (WebCodecs), rendering (WebGL2), and MP4 export (a Web Worker drawing to an OffscreenCanvas), so footage never leaves the user’s machine. When you want server-side rendering — batch jobs, AI-generated video, CI — @elah/cli runs the exact same export pipeline headlessly on your own hardware, with bit-identical output.

Can elah render video on a server?

Yes. npx @elah/cli serve starts a self-hosted HTTP render server: POST a seconds-based JSON spec to /render and get MP4 bytes back. It keeps a warm headless Chrome and runs core’s real exportVideo pipeline, so server output is frame-identical to the browser. There is also elah build / elah export for one-shot CLI renders, and a Node library API.

What can I build with elah?

An embeddable video editor inside your own product: the SDK ships EditorProvider, Preview, AssetPanel, and Timeline React components on top of a headless TypeScript engine, so you can compose a full editor in under 20 lines or drive the engine directly.

Is the exported video identical to the preview?

Yes. Preview and export run the same pure resolver — resolveTimeline(frame, project) → Scene — and the same placement math, so the frame you scrub is the frame you ship. Same project, same frame, same pixels.

How is elah different from Remotion?

Remotion turns React components into video — programmatic composition rendered by headless Chromium. elah is an editing engine: an integer-frame timeline data model with undo history, drag/trim/split UI, and a GPU export pipeline that runs in the user’s browser or headlessly via @elah/cli. The difference is the editing foundation, not where rendering happens.

Which frameworks does elah support?

The core engine is framework-agnostic TypeScript with zero React imports. React and Next.js bindings ship today via @elah/editor and @elah/timeline; React Native support is experimental, with more frameworks planned.

Is elah open source?

Yes — elah is open source under the Apache-2.0 license, copyright Elah Labs Private Limited. It’s free to use, modify, embed, self-host, and ship in commercial products, including hosted and white-label offerings. Paid support and services are available if you want them, but nothing is gated behind a license.

What export formats does elah support?

MP4 with H.264 video by default (VP9 and VP8 are also available) and AAC or Opus audio, at any aspect ratio — 9:16, 16:9, 1:1, or a custom stage — up to the project’s native resolution.

Ready to build

Start building professional
video tooling on the web.

elah is open source. Drop in the timeline and preview components, wire your demuxer, and ship.