Timelinx

WebGL Compositor

GPU-accelerated compositing of decoded video frames using WebGL 2

WebGLCompositorAdapter composites decoded video frames into a single output frame using WebGL 2. It applies per-clip transforms (position, scale, rotation, crop), blend modes, and opacity, then writes the result to a canvas.

Import

import { createWebGLCompositor, WebGLCompositorAdapter } from '@timelinx/media-web';

createWebGLCompositor(config)

function createWebGLCompositor(config: WebGLCompositorConfig): WebGLCompositorAdapter

WebGLCompositorConfig

type WebGLCompositorConfig = {
  canvas: HTMLCanvasElement | OffscreenCanvas;
  width?: number;
  height?: number;
  antialias?: boolean;
};
FieldTypeDefaultNotes
canvasHTMLCanvasElement | OffscreenCanvasrequiredThe output canvas.
widthnumbercanvas.widthCompositor internal resolution.
heightnumbercanvas.height
antialiasbooleanfalseWebGL antialias hint.

How It Works

The Compositor contract receives a CompositeRequest:

type CompositeRequest = {
  readonly timelineFrame: TimelineFrame;
  readonly layers: readonly CompositeLayer[];
  readonly width: number;
  readonly height: number;
  readonly quality: PlaybackQuality;
};

Each CompositeLayer has a decoded VideoFrame (from the VideoDecoder), plus transform, opacity, blend mode, and effects:

type CompositeLayer = {
  readonly clipId: ClipId;
  readonly trackId: TrackId;
  readonly trackIndex: number;
  readonly frame: VideoFrameResult;   // decoded bitmap
  readonly transform: ClipTransform;
  readonly opacity: number;
  readonly blendMode: string;
  readonly effects: readonly Effect[];
};

The compositor renders layers bottom-up (highest trackIndex first), applying transform and blend mode for each.


ClipTransform in the Compositor

Each layer's ClipTransform maps to WebGL uniform values:

Transform fieldWebGL operation
x, yTranslation in pixels
scaleX, scaleYScale factors
rotationRotation in degrees (converted to radians)
anchorX, anchorYPivot point (0–1 normalized)
cropLeft/Right/Top/BottomTexture coordinate clipping

Blend Modes

The compositor supports CSS-compatible blend modes via WebGL fragment shaders:

ModeWebGL shader
'normal'Standard alpha compositing
'multiply'RGB channel multiplication
'screen'Inverse multiplication
'overlay'Combination of multiply and screen
'darken'Min of source and destination
'lighten'Max
'color-dodge'
'color-burn'
'hard-light'
'soft-light'
'difference'
'exclusion'

Passing to PipelineConfig

const compositorCanvas = document.getElementById('compositor-canvas') as HTMLCanvasElement;

const engine = new TimelineEngine({
  initialState,
  pipeline: {
    videoDecoder: createWebCodecsDecoder(),
    compositor: createWebGLCompositor({
      canvas: compositorCanvas,
      width: 1920,
      height: 1080,
    }),
  },
  dimensions: { width: 1920, height: 1080 },
});

Match compositor and engine dimensions

Pass the same width and height to both the compositor config and TimelineEngineOptions.dimensions. A mismatch causes clipping or stretching.


Cleanup

compositor.close();

Releases the WebGL context, framebuffers, and textures. Call this when unmounting the editor or when the canvas is removed from the DOM.


OffscreenCanvas for Workers

const offscreen = canvas.transferControlToOffscreen();
const compositor = createWebGLCompositor({ canvas: offscreen });

OffscreenCanvas lets the compositor run in a worker thread, freeing the main thread for UI. Requires Chrome 69+ and careful postMessage ownership transfer.

On this page