JSON Structure and Field Rules
1. Top-level structure
The full top-level JSON shape is:
{
"meta": {},
"assets": {},
"tracks": []
}Rules:
metais requiredtracksis required and must contain at least one trackassetsis optional
Not supported:
- Legacy top-level
video - Legacy top-level
audio
2. meta
interface Meta {
version: string;
title?: string;
description?: string;
author?: string;
createdAt?: string;
tags?: string[];
width: number;
height: number;
fps: number;
background?: string | "transparent" | Gradient;
}version
- Type:
string - Required: yes
- Purpose: schema version marker
- Recommended value:
"2.0.0"
title
- Type:
string - Required: no
- Purpose: video title metadata
description
- Type:
string - Required: no
- Purpose: video description metadata
author
- Type:
string - Required: no
- Purpose: author metadata
createdAt
- Type:
string - Required: no
- Purpose: creation-time metadata
tags
- Type:
string[] - Required: no
- Purpose: tagging metadata
width
- Type:
number - Required: yes
- Constraint: positive integer
- Purpose: canvas width
height
- Type:
number - Required: yes
- Constraint: positive integer
- Purpose: canvas height
fps
- Type:
number - Required: yes
- Constraint: positive integer
- Purpose: frame rate
background
- Type:
string | "transparent" | Gradient - Required: no
- Default:
"#000000" - Purpose: global background
Gradient shape:
interface Gradient {
type: "linear" | "radial" | "conic";
angle?: number;
stops: Array<{
offset: number;
color: string;
}>;
}3. assets
interface Assets {
fonts?: FontAsset[];
images?: ImageAsset[];
videos?: VideoAsset[];
audios?: AudioAsset[];
subtitles?: SubtitleAsset[];
}fonts
interface FontAsset {
id: string;
src: string;
family: string;
}Current runtime status:
- It can appear in JSON
- The runtime does not automatically download or register fonts
- Do not treat it as a complete font-loading system
images
interface ImageAsset {
id: string;
src: string;
}videos
interface VideoAsset {
id: string;
src: string;
}audios
interface AudioAsset {
id: string;
src: string;
}subtitles
interface SubtitleAsset {
id: string;
words: SubtitleWord[];
}$ref usage
Resource pools that support $ref:
imagesvideosaudiossubtitles
Example:
{
"src": { "$ref": "video-hero" }
}Or:
{
"words": { "$ref": "subtitle-main" }
}4. tracks
interface Track {
id?: string;
clips: Clip[];
}id
- Type:
string - Required: no
- Purpose: track identifier
clips
- Type:
Clip[] - Required: yes
- Constraint: at least one clip
5. Shared Clip shape
interface BaseClip {
id?: string;
type: ClipType;
start: number;
duration: number;
transform?: Transform;
zIndex?: number;
opacity?: number;
style?: Style;
animations?: Animation[];
keyframes?: Keyframe[];
transition?: Transition;
}Shared core fields:
id
- Type:
string - Required: no
- Purpose: clip identifier
type
- Type:
ClipType - Required: yes
Currently supported:
videoimagetextrectcirclepolygonaudiosubtitlelayouttemplate
start
- Type:
number - Required: yes
- Unit: seconds
- Purpose: clip start time
duration
- Type:
number - Required: yes
- Unit: seconds
- Purpose: clip duration
transform
- Type:
Transform - Required: no
zIndex
- Type:
number - Required: no
- Default:
0
opacity
- Type:
number - Required: no
- Default:
1 - Purpose: shorthand opacity for visible elements
- Compatibility rule:
style.opacityhas higher priority than top-levelopacity
style
- Type:
Style - Required: no
animations
- Type:
Animation[] - Required: no
keyframes
- Type:
Keyframe[] - Required: no
transition
- Type:
Transition - Required: no
6. Coordinate and percentage rules
Percentage coordinates are based on the Revideo-centered coordinate system, not a DOM-style top-left origin.
Examples:
x: "50%"means horizontally centeredy: "50%"means vertically centeredx: "0%"means far leftx: "100%"means far righty: "0%"means topy: "100%"means bottom
7. Minimal valid JSON
{
"meta": {
"version": "2.0.0",
"width": 1920,
"height": 1080,
"fps": 30,
"background": "#000000"
},
"tracks": [
{
"clips": [
{
"type": "text",
"start": 0,
"duration": 3,
"text": "Hello, world",
"transform": {
"x": "50%",
"y": "50%"
},
"style": {
"fontSize": 72,
"fill": "#ffffff",
"textAlign": "center"
}
}
]
}
]
}8. Public integration note
For external integrations, use the flow documented in API and Usage:
- Submit your schema through
POST /api/preview - Send the full schema JSON as the request body
- Missing top-level
metaortracksshould still be treated as invalid input - A wrong field name inside a clip may not always fail at request time
- Some mistakes may only become visible during preview, playback, or rendering