All docs
JSON format
JSON schema reference
Every field in an openCanviz JSON file, with types and defaults, plus the full JSON Schema to validate against.
Last updated
This page lists every field openCanviz reads from a JSON file, then gives the full JSON Schema (draft 2020-12). Validate your file against the schema before you import it. The schema lives at https://opencanviz.com/schema/v1.json, and the full text is at the end of this page. For the big picture, start with The openCanviz JSON format.
Fields marked "set by openCanviz" in the schema are filled in by the app. Leave them out of files you write.
Project
The top-level object. Use this form for any video, and always for more than one scene.
| Field | Type | What it does |
$schema | string | Optional. Set it to https://opencanviz.com/schema/v1.json so code editors check the file and suggest fields. Import ignores it. |
title | string | Project name. Defaults to "Imported project". |
artboard | object | The video frame. Always include it. See Artboard below. |
diagrams | array of scenes | Required. The scenes, in playback order. |
sceneNames | array of strings | One name per scene. Missing names become "Scene 1", "Scene 2" and so on. |
transitions | array | Entry i is the transition between scene i and scene i + 1, or null for a hard cut. |
showCaptions | boolean | Show step captions on screen. Default true. |
captionStyle | object | How captions look. See Caption style below. |
sketchMode | boolean | Draw every shape and line in a hand-drawn style. Default false. |
floatEnabled | boolean | Give non-text nodes a gentle idle bob. Default false. |
flowEnabled | boolean | Run edge flow animations. Default true. |
meta.openAtLastStep | boolean | Open the editor on the last step instead of the first. |
Single-scene form: instead of diagrams, you may put nodes, edges, steps, narration and paths at the top level, next to title, artboard and captionStyle. It behaves like a project with one scene.
Artboard
| Field | Type | What it does |
x, y | number | Top-left corner of the frame on the canvas. |
width, height | number | Frame size in pixels: 1920 by 1080 for 16:9, 1080 by 1920 for 9:16, 1080 by 1080 for 1:1. |
background | color | Background color of the video. |
Center the frame on the origin by setting x to minus half the width and y to minus half the height.
Scene
Each entry in diagrams.
| Field | Type | What it does |
nodes | array of nodes | Required. Every node in the scene as it looks in step 0, including nodes that appear later at opacity 0. |
edges | array of edges | Required. Every edge in the scene as it looks in step 0. |
steps | array of steps | Required, at least one. A scene with no steps shows nothing when it plays. |
narration | array of clips | Narration lines, at most one per step. |
paths | object | Motion paths by id, for pathFollow actions. Each has id and points, a list of at least two x, y points. |
background | color | A flat background for this scene only. |
Node
Fields every node can use. id, kind, x, y, w and h are required.
| Field | Type | What it does |
id | string | Unique within the scene, the same in every step. |
kind | string | The node type. See Node kinds below. |
x, y | number | Top-left corner, in pixels. |
w, h | number | Width and height. A node under 10 by 10 pixels, or under 2 pixels in either direction, is not drawn. |
fill, stroke | color | Fill and outline color. |
strokeWidth | number | Outline width in pixels. |
strokeDashArray | array of numbers | Dash pattern for the outline, for example [8, 6]. |
cornerRadius | number | Rounded corners on rect. |
opacity | number | 0 to 1. Default 1. Use 0 for nodes that appear in a later step. |
zIndex | number | Higher numbers draw in front. |
label | string | Text drawn inside a shape. |
labelColor, labelFontSize | color, number | Label color and size. |
labelFontWeight | string | normal or bold. |
labelFontStyle, labelTextAlign | string | normal or italic; left, center or right. |
labelFontFamily, labelPadding | string, number | Label font and inner padding. |
rotationZ | number | Rotation in degrees. |
scaleX, scaleY | number | Scale. Default 1. |
glow | number | Glow strength, 0 to 1. |
rough, roughness | boolean, number | Hand-drawn look for this node only. |
parentId | string | Id of a group node that holds this node. |
Fields for text nodes:
| Field | Type | What it does |
text | string | The text. Use \n for a line break. |
fontSize, fontFamily, fontWeight | number, string, number | Font size, family and weight such as 400 or 700. |
fontStyle | string | normal or italic. |
color | color | Text color. |
textAlign | string | left, center or right. |
verticalAlign | string | top, middle or bottom. |
lineHeight, letterSpacing | number | Line spacing and letter spacing. |
wrap | string | word, char, ellipsis or clip. |
autoFit | string | none, shrink or grow. |
typeProgress | number | Typewriter reveal: 0 shows no text, 1 shows all of it. |
syntaxStyle, highlightedLines | string, array | Code styling (none, pseudo, python, javascript) and line numbers to highlight. |
Fields for other kinds:
| Field | Used by | What it does |
value, progressColor | progress | Fill amount from 0 to 1, and the fill color. |
points, innerRadius | star, polygon | Number of points or sides, and the inner radius. |
startAngle, endAngle | wedge | Angles of the slice. |
pointerSide | callout | Side of the pointer: N, E, S or W. |
asset | svg | An icon by name, for example "asset": { "type": "icon", "source": "iconify", "ref": "mdi:database" }. |
iconStyle | svg, icon | outline or solid. |
cellValues, cellColors | algo-array, algo-grid | Cell contents and colors. |
Node kinds
| Group | Kinds |
| Shapes | rect, circle, diamond, triangle, polygon, star, arrow, cylinder, callout, wedge, chevron, funnel |
| Text and data | text, progress |
| Pictures | svg, icon, glyph, lottie |
| Layout | group |
| UML | uml-actor, uml-lifeline, uml-class, uml-note |
| Algorithms and charts | algo-array, algo-pointer, algo-grid, algo-variable, algo-tree, algo-linked-list, algo-graph, algo-chart, algo-chart-line, algo-chart-scatter |
For most videos, rect, circle, cylinder, text, progress and svg icons are enough.
Edge
An edge needs an id and two ends. Each end is either a node id (from, to) or a fixed point (fromXY, toXY).
| Field | Type | What it does |
id | string | Unique within the scene. |
from, to | string | Ids of the start and end nodes. Both must be in the scene's nodes, or the edge is removed when the project opens. |
fromXY, toXY | point | A fixed start or end point, x and y in pixels. |
fromPort, toPort | string | Which side of the node to attach to: N, E, S or W. |
stroke | color | Line color. |
width | number | Line width in pixels. This is width, not strokeWidth. |
opacity | number | 0 to 1. |
trim | number | How much of the line is drawn, from the start: 0 is none, 1 is all. Default 1. |
arrow | string | none, end, start or both. |
endArrowType, startArrowType | string | triangle, open-triangle, diamond-filled, diamond-hollow, circle or bar. |
strokeStyle | string | solid, dashed or dotted. |
lineType | string | straight, curved or elbowed. |
label, labelColor, labelFontSize | string, color, number | Text on the line. |
labelPosition | string | center, above or below. |
animationStyle | string | Motion along the line: flow, ball, pulse or none. |
flowSpeed | number | Speed of that motion. |
waypoints | array of points | Points the line passes through. |
Step
| Field | Type | What it does |
id | string | Optional name for the step. |
durationMs | number | Length of the step in milliseconds. 0 or missing counts as 900. |
caption | string | The line shown on screen during this step. |
note | string | A private note, not shown in the video. |
delta | boolean | true means the step lists only changes. Set it on every step after step 0. |
nodes | array | Step 0: every node in full. Later steps: id plus only the fields that change. |
edges | array | Same as nodes, for edges. |
addNodes, addEdges | array | Full new nodes or edges that first appear in this step. |
removeNodeIds, removeEdgeIds | array of strings | Ids to remove in this step. They fade or draw out. |
actions | array | Timed effects inside the step. See Actions below. |
easing | easing | Easing for the automatic change from the previous step. Default ease. |
transitions | object | Per node id: morph, instant, fade, flip-x or flip-y. instant snaps the change. |
delays | object | Per node id: milliseconds to wait before its automatic change starts. |
camera | camera | Where the view moves in this step: x, y (the world point at the center) and zoom (1 is 100 percent). |
cameraDurationMs, cameraOffsetMs, cameraEasing | number, number, easing | Timing of the camera move. |
Changes between steps animate on their own. Numbers and colors such as x, y, w, h, opacity, fontSize, value, fill, stroke, color and labelColor tween across the whole step. Nodes added with addNodes fade in, removed nodes fade out, and added edges draw in.
Actions
Each action has a type, a target (kind is node or edge, plus the id), and optional offsetMs (delay from the start of the step) and durationMs. An action controls only the properties it covers; everything else keeps its automatic change.
| Type | Fields | What it does |
visibility | mode, durationMs (default 200), slideDistance (default 150), ease | Shows or hides a node. Modes: fadeIn, fadeOut, show, hide, slideInLeft, slideInRight, slideInUp, slideInDown, slideOutLeft, slideOutRight, slideOutUp, slideOutDown. |
transformTween | from, to, ease, iterations | Tweens the node properties named in to, such as opacity, scaleX, scaleY, rotationZ, fill, value or typeProgress. |
positionTween | from, to (points), ease | Moves a node from one point to another. |
edgeTween | from, to, ease | Tweens an edge's trim, trimStart, stroke, width or opacity. Use trim 0 to 1 to draw a line in. |
pathFollow | pathId, from, to (0 to 1), rotateToTangent | Moves a node along a path from the scene's paths. |
Slide modes name the side: slideInLeft enters from the left and slideOutLeft leaves to the left. slideInUp enters from above and slideInDown enters from below.
A transformTween with a to.x or to.y always starts from the node's current position; from.x and from.y are ignored. Other from values, such as scaleX, are used.
Narration clip
| Field | Type | What it does |
id | string | Unique within the scene. |
text | string | What the voice says. Usually the same as the step's caption. |
stepIndex | integer | Which step, counting from 0. |
voice | object | provider "openai", plus voiceId and voiceName. Voice ids: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer, verse. |
speed | number | Speaking rate. Default 1. |
Clips import as text. Click Generate All Scenes in the Narration panel to record them.
Scene transition
| Field | Type | What it does |
kind | string | crossfade, slideDown, slideUp, slideLeft, slideRight, pushUp, pushDown, pushLeft, pushRight, travelOffUp, travelOffDown, travelOffLeft, travelOffRight, scribbleWipe, scribbleWipeLeft, scribbleWipeUp, scribbleWipeDown, colorWipe, colorWipeLeft, colorWipeUp, colorWipeDown or morph. |
durationMs | number | Length of the transition. |
color | color | Wipe color, for the colorWipe kinds only. |
Caption style
| Field | Type | What it does |
variant | string | band (a lower-third strip behind the text) or display (heavy outlined capitals on the picture, one word lit at a time). |
fontScale, fontWeight | number | Text size multiplier and weight. |
textColor, bandColor | color | Text color and strip color. |
bandOpacity | number | Strip opacity, 0 to 1. Default 0.74. |
highlightColor, outlineColor | color | For display: the color of the word being spoken, and the letter outline. |
Easing values
linear, ease, ease-in, ease-out, spring, bounce, elastic, back, back-in and step.
Full JSON Schema
The same schema as https://opencanviz.com/schema/v1.json. It describes the fields above; fields it does not list are passed through unchanged.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://opencanviz.com/schema/v1.json",
"title": "openCanviz project JSON",
"description": "The JSON that openCanviz accepts on Import (Create > Import > Paste JSON or Mermaid). Two shapes are accepted: a project with a diagrams array (one entry per scene), or a single scene with nodes, edges and steps at the top level. Add \"$schema\": \"https://opencanviz.com/schema/v1.json\" to a file to get editor autocomplete. Fields not listed here are passed through; leave out anything marked as set by openCanviz.",
"type": "object",
"anyOf": [
{
"$ref": "#/$defs/projectDocument"
},
{
"$ref": "#/$defs/singleSceneDocument"
}
],
"$defs": {
"projectDocument": {
"title": "Project (recommended)",
"type": "object",
"required": [
"diagrams"
],
"properties": {
"$schema": {
"type": "string",
"description": "Optional. \"https://opencanviz.com/schema/v1.json\" for editor autocomplete; openCanviz ignores it."
},
"title": {
"type": "string",
"description": "Project name shown on the Projects page. Defaults to \"Imported project\"."
},
"artboard": {
"$ref": "#/$defs/artboard"
},
"diagrams": {
"type": "array",
"minItems": 1,
"description": "Scenes, in playback order.",
"items": {
"$ref": "#/$defs/scene"
}
},
"sceneNames": {
"type": "array",
"items": {
"type": "string"
},
"description": "One name per scene, same order as diagrams. Missing names default to \"Scene N\"."
},
"transitions": {
"type": "array",
"description": "Index i is the transition between scene i and scene i+1. Length should be diagrams.length - 1. null means a hard cut.",
"items": {
"anyOf": [
{
"$ref": "#/$defs/sceneTransition"
},
{
"type": "null"
}
]
}
},
"showCaptions": {
"type": "boolean",
"description": "Show step captions on screen. Default true."
},
"captionStyle": {
"$ref": "#/$defs/captionStyle"
},
"sketchMode": {
"type": "boolean",
"description": "Draw every shape and edge in a hand-drawn style. Default false."
},
"floatEnabled": {
"type": "boolean",
"description": "Gentle idle bob on non-text nodes in every scene. Default false."
},
"floatOffScenes": {
"type": "array",
"items": {
"type": "boolean"
},
"description": "Per scene: true keeps that scene still when floatEnabled is on."
},
"floatOnScenes": {
"type": "array",
"items": {
"type": "boolean"
},
"description": "Per scene: true makes that scene float even when floatEnabled is off."
},
"flowEnabled": {
"type": "boolean",
"description": "Run edge flow animations. Default true."
},
"meta": {
"type": "object",
"properties": {
"openAtLastStep": {
"type": "boolean",
"description": "Open the editor on the last step instead of the first."
}
}
}
}
},
"singleSceneDocument": {
"title": "Single scene (flat)",
"type": "object",
"required": [
"nodes"
],
"properties": {
"$schema": {
"type": "string",
"description": "Optional. \"https://opencanviz.com/schema/v1.json\" for editor autocomplete; openCanviz ignores it."
},
"title": {
"type": "string"
},
"artboard": {
"$ref": "#/$defs/artboard"
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/$defs/node"
}
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/edge"
}
},
"steps": {
"type": "array",
"items": {
"$ref": "#/$defs/step"
},
"prefixItems": [
{
"$ref": "#/$defs/firstStep"
}
]
},
"paths": {
"$ref": "#/$defs/paths"
},
"narration": {
"type": "array",
"items": {
"$ref": "#/$defs/narrationClip"
}
},
"camera": {
"$ref": "#/$defs/camera"
},
"showCaptions": {
"type": "boolean"
},
"captionStyle": {
"$ref": "#/$defs/captionStyle"
},
"meta": {
"type": "object",
"properties": {
"openAtLastStep": {
"type": "boolean"
}
}
}
}
},
"color": {
"type": "string",
"description": "CSS color: \"#rrggbb\", \"#rgb\", \"rgba(r,g,b,a)\", \"transparent\" or \"none\". Hex is safest."
},
"easing": {
"type": "string",
"enum": [
"linear",
"ease",
"ease-in",
"ease-out",
"spring",
"bounce",
"elastic",
"back",
"back-in",
"step"
]
},
"artboard": {
"type": "object",
"description": "The video frame, in world coordinates. x and y are its top-left corner.",
"required": [
"x",
"y",
"width",
"height",
"background"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"width": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Frame width in px, for example 1920 for 16:9 or 1080 for 9:16 and 1:1."
},
"height": {
"type": "number",
"exclusiveMinimum": 0
},
"background": {
"$ref": "#/$defs/color"
}
}
},
"camera": {
"type": "object",
"required": [
"x",
"y",
"zoom"
],
"properties": {
"x": {
"type": "number",
"description": "World x at the center of the view."
},
"y": {
"type": "number",
"description": "World y at the center of the view."
},
"zoom": {
"type": "number",
"exclusiveMinimum": 0,
"description": "1 = 100%."
}
}
},
"scene": {
"type": "object",
"required": [
"nodes",
"edges",
"steps"
],
"properties": {
"nodes": {
"type": "array",
"description": "Every node in the scene, as it looks in step 0. Usually identical to steps[0].nodes.",
"items": {
"$ref": "#/$defs/node"
}
},
"edges": {
"type": "array",
"description": "Every edge in the scene, as it looks in step 0. Usually identical to steps[0].edges.",
"items": {
"$ref": "#/$defs/edge"
}
},
"steps": {
"type": "array",
"minItems": 1,
"description": "The timeline. Step 0 is a full snapshot; later steps list changes.",
"items": {
"$ref": "#/$defs/step"
},
"prefixItems": [
{
"$ref": "#/$defs/firstStep"
}
]
},
"paths": {
"$ref": "#/$defs/paths"
},
"narration": {
"type": "array",
"description": "Narration lines, at most one per step. Text only; record the audio in the Narration panel.",
"items": {
"$ref": "#/$defs/narrationClip"
}
},
"background": {
"$ref": "#/$defs/color",
"description": "Flat background color for this scene only."
}
}
},
"node": {
"type": "object",
"required": [
"id",
"kind",
"x",
"y",
"w",
"h"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Unique within the scene. Keep the same id across steps."
},
"kind": {
"type": "string",
"enum": [
"rect",
"circle",
"diamond",
"triangle",
"polygon",
"star",
"arrow",
"cylinder",
"text",
"callout",
"wedge",
"chevron",
"funnel",
"progress",
"svg",
"icon",
"group",
"glyph",
"lottie",
"uml-actor",
"uml-lifeline",
"uml-class",
"uml-note",
"algo-array",
"algo-pointer",
"algo-grid",
"algo-variable",
"algo-tree",
"algo-linked-list",
"algo-graph",
"algo-chart",
"algo-chart-line",
"algo-chart-scatter"
]
},
"x": {
"type": "number",
"description": "Left edge, world px."
},
"y": {
"type": "number",
"description": "Top edge, world px."
},
"w": {
"type": "number",
"minimum": 0,
"description": "Width px. Nodes under 10 x 10 px, or under 2 px in either direction, are not drawn."
},
"h": {
"type": "number",
"minimum": 0
},
"label": {
"type": "string",
"description": "Text drawn inside a shape."
},
"labelColor": {
"$ref": "#/$defs/color"
},
"labelFontSize": {
"type": "number"
},
"labelFontWeight": {
"enum": [
"normal",
"bold"
]
},
"labelFontStyle": {
"enum": [
"normal",
"italic"
]
},
"labelFontFamily": {
"type": "string"
},
"labelPadding": {
"type": "number"
},
"labelTextAlign": {
"enum": [
"left",
"center",
"right"
]
},
"fill": {
"$ref": "#/$defs/color"
},
"stroke": {
"$ref": "#/$defs/color"
},
"strokeWidth": {
"type": "number",
"minimum": 0
},
"strokeDashArray": {
"type": "array",
"items": {
"type": "number"
}
},
"cornerRadius": {
"type": "number",
"minimum": 0
},
"opacity": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"zIndex": {
"type": "number",
"description": "Higher draws in front."
},
"text": {
"type": "string",
"description": "Content of a text node. Use \\n for line breaks."
},
"fontFamily": {
"type": "string"
},
"fontSize": {
"type": "number"
},
"fontWeight": {
"type": "number",
"minimum": 100,
"maximum": 900
},
"fontStyle": {
"enum": [
"normal",
"italic"
]
},
"lineHeight": {
"type": "number"
},
"letterSpacing": {
"type": "number"
},
"color": {
"$ref": "#/$defs/color",
"description": "Text color of a text node."
},
"textAlign": {
"enum": [
"left",
"center",
"right"
]
},
"verticalAlign": {
"enum": [
"top",
"middle",
"bottom"
]
},
"wrap": {
"enum": [
"word",
"char",
"ellipsis",
"clip"
]
},
"autoFit": {
"enum": [
"none",
"shrink",
"grow"
]
},
"typeProgress": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Typewriter reveal of a text node, 1 = all text."
},
"highlightedLines": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0
}
},
"syntaxStyle": {
"enum": [
"none",
"pseudo",
"python",
"javascript"
]
},
"rotationZ": {
"type": "number",
"description": "2D rotation in degrees."
},
"rotationX": {
"type": "number"
},
"rotationY": {
"type": "number"
},
"scaleX": {
"type": "number"
},
"scaleY": {
"type": "number"
},
"pivotX": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"pivotY": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"parentId": {
"type": "string",
"description": "Id of a group node that contains this node."
},
"rough": {
"type": "boolean"
},
"roughness": {
"type": "number",
"minimum": 0,
"maximum": 3
},
"glow": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"pointerSide": {
"enum": [
"N",
"E",
"S",
"W"
]
},
"points": {
"type": "integer",
"minimum": 3
},
"innerRadius": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"startAngle": {
"type": "number"
},
"endAngle": {
"type": "number"
},
"value": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"progressColor": {
"$ref": "#/$defs/color"
},
"asset": {
"type": "object",
"description": "For kind svg: an icon by reference, for example {\"type\":\"icon\",\"source\":\"iconify\",\"ref\":\"mdi:database\"}.",
"required": [
"type",
"source"
],
"properties": {
"type": {
"enum": [
"icon",
"lottie",
"image",
"svg"
]
},
"source": {
"enum": [
"iconify",
"lottie-library",
"lottie-icons",
"bundled",
"url",
"user",
"embedded"
]
},
"ref": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"iconStyle": {
"enum": [
"outline",
"solid"
]
},
"cellValues": {
"type": "array",
"items": {
"type": "string"
}
},
"cellColors": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/$defs/color"
},
{
"type": "null"
}
]
}
},
"_selected": {
"description": "Set by openCanviz, leave out."
},
"_animatedProps": {
"description": "Set by openCanviz, leave out."
},
"illuOf": {
"description": "Set by openCanviz, leave out."
},
"imageFailed": {
"description": "Set by openCanviz, leave out."
}
}
},
"edge": {
"type": "object",
"required": [
"id"
],
"anyOf": [
{
"required": [
"from",
"to"
]
},
{
"required": [
"fromXY",
"toXY"
]
},
{
"required": [
"from",
"toXY"
]
},
{
"required": [
"fromXY",
"to"
]
}
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"from": {
"type": "string",
"description": "Id of the start node. Must exist in the scene."
},
"to": {
"type": "string",
"description": "Id of the end node. Must exist in the scene."
},
"fromXY": {
"$ref": "#/$defs/point"
},
"toXY": {
"$ref": "#/$defs/point"
},
"fromPort": {
"enum": [
"N",
"E",
"S",
"W"
]
},
"toPort": {
"enum": [
"N",
"E",
"S",
"W"
]
},
"stroke": {
"$ref": "#/$defs/color"
},
"width": {
"type": "number",
"minimum": 0,
"description": "Line width in px. This is width, not strokeWidth."
},
"opacity": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"trim": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "How much of the line is drawn, from the start. 0 = none, 1 = all."
},
"trimStart": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"arrow": {
"enum": [
"none",
"end",
"start",
"both"
]
},
"endArrowType": {
"enum": [
"triangle",
"open-triangle",
"diamond-filled",
"diamond-hollow",
"circle",
"bar"
]
},
"startArrowType": {
"enum": [
"triangle",
"open-triangle",
"diamond-filled",
"diamond-hollow",
"circle",
"bar"
]
},
"arrowSize": {
"type": "number"
},
"strokeStyle": {
"enum": [
"solid",
"dashed",
"dotted"
]
},
"lineType": {
"enum": [
"straight",
"curved",
"elbowed"
]
},
"router": {
"enum": [
"AUTO",
"VHV",
"HVH"
]
},
"cornerRadius": {
"type": "number"
},
"label": {
"type": "string"
},
"labelColor": {
"$ref": "#/$defs/color"
},
"labelFontSize": {
"type": "number"
},
"labelPosition": {
"enum": [
"center",
"above",
"below"
]
},
"labelPositionT": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"labelBgColor": {
"$ref": "#/$defs/color"
},
"animationStyle": {
"enum": [
"flow",
"ball",
"pulse",
"none"
]
},
"flowSpeed": {
"type": "number"
},
"waypoints": {
"type": "array",
"items": {
"$ref": "#/$defs/point"
}
},
"zIndex": {
"type": "number"
},
"_animatedProps": {
"description": "Set by openCanviz, leave out."
}
}
},
"point": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
}
},
"paths": {
"type": "object",
"description": "Motion paths by id, used by pathFollow actions.",
"additionalProperties": {
"type": "object",
"required": [
"id",
"points"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"points": {
"type": "array",
"minItems": 2,
"items": {
"$ref": "#/$defs/point"
}
},
"closed": {
"type": "boolean"
},
"length": {
"description": "Set by openCanviz, leave out."
},
"cum": {
"description": "Set by openCanviz, leave out."
}
}
}
},
"nodePatch": {
"type": "object",
"description": "In step 0: a full node. In a delta step: id plus only the fields that change.",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
}
}
},
"edgePatch": {
"type": "object",
"description": "In step 0: a full edge. In a delta step: id plus only the fields that change.",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
}
}
},
"step": {
"type": "object",
"required": [
"durationMs",
"nodes",
"edges"
],
"properties": {
"id": {
"type": "string"
},
"note": {
"type": "string",
"description": "Private note, not shown in the video."
},
"caption": {
"type": "string",
"description": "The narration line for this step. Shown as an on-screen caption."
},
"durationMs": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Step length in ms. 0 or missing is treated as 900."
},
"delta": {
"type": "boolean",
"description": "true = this step lists only changes. Put it on every step after step 0."
},
"easing": {
"$ref": "#/$defs/easing",
"description": "Easing for the automatic tween from the previous step. Default ease."
},
"propertyEasings": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/easing"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/$defs/nodePatch"
}
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/edgePatch"
}
},
"addNodes": {
"type": "array",
"items": {
"$ref": "#/$defs/node"
},
"description": "Delta steps: full new nodes that appear in this step."
},
"removeNodeIds": {
"type": "array",
"items": {
"type": "string"
}
},
"addEdges": {
"type": "array",
"items": {
"$ref": "#/$defs/edge"
}
},
"removeEdgeIds": {
"type": "array",
"items": {
"type": "string"
}
},
"actions": {
"type": "array",
"items": {
"$ref": "#/$defs/action"
}
},
"transitions": {
"type": "object",
"description": "Per node id: how the node changes into this step.",
"additionalProperties": {
"enum": [
"morph",
"instant",
"fade",
"flip-x",
"flip-y"
]
}
},
"delays": {
"type": "object",
"description": "Per node id: delay in ms before its automatic tween starts.",
"additionalProperties": {
"type": "number",
"minimum": 0
}
},
"camera": {
"$ref": "#/$defs/camera"
},
"cameraDurationMs": {
"type": "number",
"minimum": 0
},
"cameraEasing": {
"$ref": "#/$defs/easing"
},
"cameraOffsetMs": {
"type": "number",
"minimum": 0
},
"cameraEnd": {
"$ref": "#/$defs/camera"
},
"_addedNodeIds": {
"description": "Set by openCanviz, leave out."
},
"_removedNodeIds": {
"description": "Set by openCanviz, leave out."
},
"_addedEdgeIds": {
"description": "Set by openCanviz, leave out."
},
"_removedEdgeIds": {
"description": "Set by openCanviz, leave out."
}
}
},
"nodeTarget": {
"type": "object",
"required": [
"kind",
"id"
],
"properties": {
"kind": {
"const": "node"
},
"id": {
"type": "string"
}
}
},
"edgeTarget": {
"type": "object",
"required": [
"kind",
"id"
],
"properties": {
"kind": {
"const": "edge"
},
"id": {
"type": "string"
}
}
},
"action": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"visibility",
"transformTween",
"positionTween",
"edgeTween",
"pathFollow",
"pathAnimate",
"algoSwap",
"containerTransform",
"voiceOver"
]
}
},
"oneOf": [
{
"$ref": "#/$defs/visibilityAction"
},
{
"$ref": "#/$defs/transformTweenAction"
},
{
"$ref": "#/$defs/positionTweenAction"
},
{
"$ref": "#/$defs/edgeTweenAction"
},
{
"$ref": "#/$defs/pathFollowAction"
},
{
"$ref": "#/$defs/otherAction"
}
]
},
"timing": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Optional. Generated when missing."
},
"offsetMs": {
"type": "number",
"minimum": 0,
"description": "Delay from the start of the step."
},
"durationMs": {
"type": "number",
"minimum": 0
},
"disabled": {
"type": "boolean"
}
}
},
"visibilityAction": {
"allOf": [
{
"$ref": "#/$defs/timing"
}
],
"type": "object",
"required": [
"type",
"target",
"mode"
],
"properties": {
"type": {
"const": "visibility"
},
"target": {
"$ref": "#/$defs/nodeTarget"
},
"mode": {
"enum": [
"show",
"hide",
"fadeIn",
"fadeOut",
"slideInLeft",
"slideInRight",
"slideInUp",
"slideInDown",
"slideOutLeft",
"slideOutRight",
"slideOutUp",
"slideOutDown"
]
},
"durationMs": {
"type": "number",
"minimum": 0,
"description": "Default 200."
},
"slideDistance": {
"type": "number",
"description": "Slide modes: distance in px. Default 150."
},
"iterations": {
"type": "integer",
"minimum": 1
},
"ease": {
"$ref": "#/$defs/easing"
}
}
},
"tweenProps": {
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"w": {
"type": "number"
},
"h": {
"type": "number"
},
"scaleX": {
"type": "number"
},
"scaleY": {
"type": "number"
},
"rotationX": {
"type": "number"
},
"rotationY": {
"type": "number"
},
"rotationZ": {
"type": "number"
},
"opacity": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"fill": {
"$ref": "#/$defs/color"
},
"stroke": {
"$ref": "#/$defs/color"
},
"strokeWidth": {
"type": "number"
},
"strokeTrimStart": {
"type": "number"
},
"strokeTrimEnd": {
"type": "number"
},
"typeProgress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"drawProgress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"blur": {
"type": "number",
"minimum": 0
},
"value": {
"type": "number"
}
}
},
"transformTweenAction": {
"allOf": [
{
"$ref": "#/$defs/timing"
}
],
"type": "object",
"required": [
"type",
"target",
"to"
],
"properties": {
"type": {
"const": "transformTween"
},
"target": {
"$ref": "#/$defs/nodeTarget"
},
"from": {
"$ref": "#/$defs/tweenProps",
"description": "Start values. from.x and from.y are ignored; position always starts where the node is."
},
"to": {
"$ref": "#/$defs/tweenProps",
"description": "End values. Only the properties named here are controlled by this action; set the same end values in the step's snapshot."
},
"ease": {
"$ref": "#/$defs/easing"
},
"iterations": {
"type": "integer",
"minimum": 1,
"maximum": 10
},
"isRelative": {
"type": "boolean",
"description": "Advanced, not recommended. Use an absolute to.x and to.y instead."
},
"dx": {
"type": "number",
"description": "Used only with isRelative."
},
"dy": {
"type": "number",
"description": "Used only with isRelative."
}
}
},
"positionTweenAction": {
"allOf": [
{
"$ref": "#/$defs/timing"
}
],
"type": "object",
"required": [
"type",
"target",
"from",
"to",
"durationMs"
],
"properties": {
"type": {
"const": "positionTween"
},
"target": {
"$ref": "#/$defs/nodeTarget"
},
"from": {
"$ref": "#/$defs/point"
},
"to": {
"$ref": "#/$defs/point"
},
"ease": {
"$ref": "#/$defs/easing"
},
"isRelative": {
"type": "boolean"
},
"dx": {
"type": "number"
},
"dy": {
"type": "number"
}
},
"description": "Moves a node from one point to another. transformTween with to.x and to.y is simpler and starts from wherever the node is."
},
"edgeTweenAction": {
"allOf": [
{
"$ref": "#/$defs/timing"
}
],
"type": "object",
"required": [
"type",
"target",
"to"
],
"properties": {
"type": {
"const": "edgeTween"
},
"target": {
"$ref": "#/$defs/edgeTarget"
},
"from": {
"$ref": "#/$defs/edgeTweenProps"
},
"to": {
"$ref": "#/$defs/edgeTweenProps"
},
"ease": {
"$ref": "#/$defs/easing"
}
}
},
"edgeTweenProps": {
"type": "object",
"properties": {
"trim": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"trimStart": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"stroke": {
"$ref": "#/$defs/color"
},
"width": {
"type": "number"
},
"opacity": {
"type": "number",
"minimum": 0,
"maximum": 1
}
}
},
"pathFollowAction": {
"allOf": [
{
"$ref": "#/$defs/timing"
}
],
"type": "object",
"required": [
"type",
"target",
"pathId",
"from",
"to"
],
"properties": {
"type": {
"const": "pathFollow"
},
"target": {
"$ref": "#/$defs/nodeTarget"
},
"pathId": {
"type": "string",
"description": "Key of an entry in the scene's paths."
},
"from": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"to": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"ease": {
"$ref": "#/$defs/easing"
},
"rotateToTangent": {
"type": "boolean"
}
}
},
"otherAction": {
"type": "object",
"description": "pathAnimate, algoSwap, containerTransform and voiceOver are accepted but are advanced; prefer the actions above.",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"pathAnimate",
"algoSwap",
"containerTransform",
"voiceOver"
]
}
}
},
"narrationClip": {
"type": "object",
"required": [
"id",
"text",
"stepIndex",
"voice"
],
"properties": {
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"stepIndex": {
"type": "integer",
"minimum": 0,
"description": "Index of the step this line belongs to."
},
"voice": {
"type": "object",
"required": [
"provider",
"voiceId",
"voiceName"
],
"properties": {
"provider": {
"type": "string",
"description": "Use \"openai\"."
},
"voiceId": {
"type": "string",
"description": "For example alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer or verse."
},
"voiceName": {
"type": "string"
}
}
},
"speed": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Playback rate. Default 1."
},
"audioData": {
"description": "Set by openCanviz, leave out."
},
"audioUrl": {
"description": "Set by openCanviz, leave out."
},
"audioDurationMs": {
"description": "Set by openCanviz, leave out."
},
"words": {
"description": "Set by openCanviz, leave out."
}
}
},
"sceneTransition": {
"type": "object",
"required": [
"kind",
"durationMs"
],
"properties": {
"kind": {
"enum": [
"crossfade",
"slideDown",
"slideUp",
"slideLeft",
"slideRight",
"pushUp",
"pushDown",
"pushLeft",
"pushRight",
"travelOffUp",
"travelOffDown",
"travelOffLeft",
"travelOffRight",
"scribbleWipe",
"scribbleWipeLeft",
"scribbleWipeUp",
"scribbleWipeDown",
"colorWipe",
"colorWipeLeft",
"colorWipeUp",
"colorWipeDown",
"morph"
]
},
"durationMs": {
"type": "number",
"exclusiveMinimum": 0
},
"color": {
"$ref": "#/$defs/color",
"description": "colorWipe kinds only."
}
}
},
"captionStyle": {
"type": "object",
"properties": {
"variant": {
"enum": [
"band",
"display"
]
},
"fontScale": {
"type": "number",
"exclusiveMinimum": 0
},
"fontWeight": {
"type": "number"
},
"textColor": {
"$ref": "#/$defs/color"
},
"bandColor": {
"$ref": "#/$defs/color"
},
"bandOpacity": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"highlightColor": {
"$ref": "#/$defs/color"
},
"outlineColor": {
"$ref": "#/$defs/color"
}
}
},
"firstStep": {
"description": "Step 0: a full snapshot. Every node and edge in full.",
"allOf": [
{
"$ref": "#/$defs/step"
}
],
"properties": {
"nodes": {
"type": "array",
"items": {
"$ref": "#/$defs/node"
}
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/edge"
}
}
}
}
}
}