Authoring
Write a Kinetograph project with compositions, Remotion APIs, native elements, effects, fonts and assets.
A project is a TypeScript or TSX file. It draws each frame from the frame number and the props it is given. This page covers what a project can use. For the first steps, see First video.
Compositions
The entry file calls registerRoot with a function that returns one or more Compositions:
registerRoot(() => (
<Composition id="Card" component={Card} durationInFrames={60} fps={30} width={640} height={360} />
));| Prop | Meaning |
|---|---|
id | The name that --comp selects. Without --comp, the first composition is used. |
component | The component that draws a frame. |
durationInFrames, fps, width, height | The length, frame rate and size. |
defaultProps | The props used when --props does not set them. |
background | The background colour of every frame. The default is transparent. |
margin | The least margin, in pixels, around the canvas for effects that draw past its edge. |
--props takes a JSON object. The component gets defaultProps with the --props values merged over them. getInputProps() returns the --props object.
npx kinetograph render src/index.tsx --comp Card --props '{"title":"Hello"}'Remotion APIs
Import the API from @kinetographdev/core, which comes with npm install kinetograph. It includes Remotion's names. A Remotion project keeps its remotion and @remotion/* imports, and the CLI maps them onto the same code.
Most projects use these:
- Time:
useCurrentFrame,useVideoConfig,Sequence,Series,Loop,Freeze. - Motion:
interpolate,interpolateColors,spring,Easing. - Layout and files:
AbsoluteFill,Img,staticFile,delayRender. - Random values:
random(seed). The same seed gives the same value every time.
What works lists what is supported. To move a project, see Migrate from Remotion.
Determinism
A frame is a function of the frame number. Date.now(), Math.random(), timers and requestAnimationFrame follow the frame clock, not the real one. Use random('name') for a value that must be the same in every render. Do not read the system time.
Native elements
These elements come from @kinetographdev/core. They draw in the engine, not in the DOM.
| Element | Draws |
|---|---|
Layer | A group of layers. Takes layout for flexbox and preserve3d for 3D. |
Rect, Ellipse, Shape, Path | Shapes, with fill, stroke and, for Rect, radius. |
Text | Text in a registered font. Takes font, size, color, maxWidth, align and chars. |
Image | A PNG or JPEG. |
Noise, MeshGradient | Noise and mesh gradients. |
Canvas | A Canvas 2D drawing, made in draw(ctx). |
GlslShader | A GLSL fragment shader, with uniforms. |
Lottie | A Lottie animation, from src or animationData. |
Camera | The perspective for 3D turns. |
Scene3D, Camera3D, lights, Mesh, Model, Extrude, Text3D | The 3D layer. |
Video, OffthreadVideo, Audio, Gif | Video, GIF and sound files. |
Every element takes the common props: id, x, y, scale, rotation, anchorX, anchorY, rotateX, rotateY, z, opacity, blendMode, effects, clip, mask, matte and motionBlur. The full table is in AUTHORING.md, section 6.3.
A shape with a gradient fill and a drop shadow:
import { Rect, dropShadow, linearGradient } from '@kinetographdev/core';
<Rect
width={220}
height={300}
fill={linearGradient(['#fafafa', '#d9d9d9'], { angle: 160 })}
effects={[dropShadow({ y: 8, blur: 12, color: '#00000030' })]}
/>Raw text outside Text is an error. A Text layer with no registered font also fails the render.
Effects
Pass effects as effects={[...]} on any layer. They run in order on the layer's own pixels, before the layer is blended.
Blur and glow (blur, backdropBlur, glow), shadows (dropShadow, insetShadow), colour (saturate, contrast, grayscale, gradientMap, lut and others) and texture (grain, dither, halftone, displace, cornerPin, shader and others) are built in.
npx kinetograph effects lists each effect with its parameters. linearGradient, radialGradient and conicGradient work as fills and as text colours.
Fonts
A text layer uses a font by family name. Register the font before the text uses it.
Google Fonts download once and are kept in ~/.cache/kinetograph/fonts:
import { loadFont } from '@remotion/google-fonts/Inter';
const { fontFamily } = loadFont('normal', { weights: ['400'] });For a font file in the project, use loadFont from @remotion/fonts, with staticFile for the path. Then use font="Brand" on a Text element:
import { loadFont } from '@remotion/fonts';
import { staticFile } from 'remotion';
loadFont({ family: 'Brand', url: staticFile('fonts/DMSans-Medium.ttf') });Assets
staticFile('name') gives the path of a file in public/, next to the entry. If there is no public/ folder there, it looks next to the nearest package.json. The src of Image, Video, Audio and Gif takes these paths. See Project layout.
Canvas and shaders
Canvas runs draw(ctx) with a fresh Canvas 2D context on every frame. What it paints must come from the props and the frame, not from what was painted before.
GlslShader takes a fragment shader in GLSL ES 100 or 300 es. Compute its uniforms from the frame, for example uniforms={{ time: frame / fps }}.
See AUTHORING.md, sections 6.5 and 6.7, and What works.
2.5D and 3D
For depth without a 3D scene, put a Camera in the composition and turn a Layer with rotateX or rotateY. Set preserve3d on the layer that holds the turned children:
For example, <Camera perspective={1400} /> with <Layer rotateY={spin} preserve3d>.
For a full 3D scene, use Scene3D, Camera3D, the lights and Mesh or Model. Rotations there are in degrees. See AUTHORING.md, section 6.6. Groups that intersect in 3D are drawn in painter's order; see What works.
To check your work as you write, see First video and the CLI reference.