Editor JSON

Structure, capability mapping, and validation strategy for editor state.

Editor JSON is the canonical render input. It includes timeline tracks, assets, clips, transitions, and optional global styling.

Top-Level Structure

Common top-level keys:

  • compositionWidth
  • compositionHeight
  • timebaseTicksPerSecond
  • outputRatio
  • tracks
  • assets
  • items
  • transitions
  • globalBackground
  • brandRuntime
  • deletedAssets

Capability-Mapped Features

The API capability endpoint returns supported values for:

  • animations
  • captionAnimations
  • transitions
  • effects
  • filters
  • backgroundPresets
  • illustrations
  • shapes

Recommended flow:

  1. Fetch GET /v1/editor/capabilities.
  2. Build UI dropdowns from the response.
  3. Validate payload with POST /v1/editor/validate.
  4. Submit export create only after validation passes.

OpenClaw Plugin

If you use the Indream OpenClaw plugin, follow the OpenClaw client guide for uploads, workflow creation, project sync, and export steps.

Example prompt:

Create a short promo video with my uploaded images, add clear on-screen text, and export the final video as MP4.

Use the rest of this page when your integration creates or validates editor JSON directly through the OpenAPI or SDK.

Recommended validate-before-export loop for direct API and SDK usage:

  1. Build the next editor JSON draft from the minimal legal skeleton.
  2. Reconcile every asset reference and track item reference.
  3. Validate with POST /v1/editor/validate.
  4. Fix errors[] by JSON path and code.
  5. Export only after the validation result is valid: true.

Objects and Relationships

assets

Defines raw media resources such as image, video, gif, audio, caption, and lottie assets. Caption assets include timingGranularity (word or line) to describe token-level or line-level timing semantics.

Using uploaded cloud assets

When you upload a file through the OpenAPI upload flow, write these returned fields into editor JSON:

  • fileUrl -> remoteUrl
  • fileKey -> remoteKey

Example:

{
  "assets": {
    "scene-bg": {
      "type": "image",
      "remoteUrl": "https://cdn.example.com/uploads/scene-bg.png",
      "remoteKey": "uploads/scene-bg.png"
    }
  }
}

items

Defines timeline entities such as clips, text, captions, effects, filters, illustrations, and shapes.

tracks

Defines ordered clip references by track. Every item referenced in a track must exist in items.

transitions

Defines transition edges between adjacent clips on the same track.

globalBackground

Defines global none/color/blur/image background settings at composition level.

Keyframe Track Contract

Animatable numeric fields use this shape:

  • value: fallback number for static rendering.
  • keyframes: timeline points in ticks.
{
  "left": {
    "value": 120,
    "keyframes": [
      { "timeTicks": 0, "value": 120 },
      { "timeTicks": 240000, "value": 520 }
    ]
  },
  "top": {
    "value": 80,
    "keyframes": [
      { "timeTicks": 0, "value": 80 },
      { "timeTicks": 240000, "value": 120 }
    ]
  },
  "opacity": {
    "value": 1,
    "keyframes": [
      { "timeTicks": 0, "value": 1 },
      { "timeTicks": 240000, "value": 0.6 }
    ]
  }
}

Use POST /v1/editor/validate to confirm schema and semantic validity before create.

{
  "timebaseTicksPerSecond": 240000,
  "compositionWidth": 1920,
  "compositionHeight": 1080,
  "outputRatio": "16:9",
  "globalBackground": {
    "type": "none"
  },
  "brandRuntime": {
    "brandId": null,
    "logoX": 50,
    "logoY": 50,
    "managedItemIds": [],
    "managedAssetIds": [],
    "introShiftInFrames": 0,
    "overlayTrackId": null,
    "underlayTrackId": null
  },
  "tracks": [
    {
      "id": "HSbB",
      "items": ["CYON"],
      "hidden": false,
      "muted": false
    }
  ],
  "assets": {},
  "items": {
    "CYON": {
      "id": "CYON",
      "type": "text",
      "text": "Hello World",
      "color": "#ffffff",
      "top": { "value": 492, "keyframes": [] },
      "left": { "value": 755, "keyframes": [] },
      "width": { "value": 411, "keyframes": [] },
      "height": { "value": 96, "keyframes": [] },
      "scaleX": { "value": 1, "keyframes": [] },
      "scaleY": { "value": 1, "keyframes": [] },
      "align": "center",
      "opacity": { "value": 1, "keyframes": [] },
      "rotation": { "value": 0, "keyframes": [] },
      "fontFamily": "Roboto",
      "fontSize": 80,
      "lineHeight": 1.2,
      "letterSpacing": 0,
      "resizeOnEdit": true,
      "direction": "ltr",
      "fontStyle": {
        "variant": "normal",
        "weight": "400"
      },
      "isDraggingInTimeline": false,
      "strokeWidth": 0,
      "strokeColor": "#000000",
      "background": null,
      "startTicks": 0,
      "durationTicks": 336000
    }
  },
  "transitions": {},
  "deletedAssets": []
}

Caption Animation Contract

  • Read available presets from GET /v1/editor/capabilities -> captionAnimations.
  • Use items[*].captionAnimations for caption animation configuration on supported text/caption items.
  • Respect assets[*].timingGranularity:
    • word: token/word-timed caption rendering path.
    • line: line-timed caption rendering path.

Invalid Example Patterns

  • Unknown enum value, such as unsupported effectType or filterType.
  • Transition clips are not adjacent in track order.
  • assetId points to a missing asset.
  • Animation or transition duration exceeds clip duration.

Validation Contract

POST /v1/editor/validate returns:

  • valid: overall boolean result.
  • errors[]: stable error code, JSON path, and message.

Example error fields:

  • code: EDITOR_TRANSITION_CLIP_NOT_ADJACENT
  • path: $.transitions.tr_1
  • message: Human-readable reason

Last updated on

On this page