HTML Animation Render (Simple)

Render a composition spec into a finished video (mp4): a video base track + custom HTML animation particles composited in one render. Built for full-screen opaque cut-ins / short clips / pure HTML animation (no long base track running through, or particles that fully cover the base) — lighter and faster. The visual vocabulary is not predefined or enumerated — you author the particles freely, as long as they follow the seekable HTML-animation format. Materials are referenced by composition.assets.file_id.

Which endpoint?

  • This endpoint · Simple: particles are full-screen opaque cut-ins / short clips / pure HTML animation (no long base track running through) → use this, lighter and faster.
  • HTML Animation Render (Layered): you have one long base track running through the whole piece (talking head / B-roll) with transparent particles overlaid on top, not covering the subject → use the layered endpoint.
  • Both endpoints take the exact same input spec; pick by your scene.

Particle Format (Important)

Each custom HTML particle must be a self-contained, seekable HTML animation:

  • Its root element must be wrapped in a <template>: <template><div data-composition-id=...>…</div></template>, otherwise the particle cannot be parsed and the whole render fails;
  • It must declare its own data-composition-id / data-width / data-height;
  • Its animation must be registered on a frame-seekable timeline (recommended: GSAP gsap.timeline({paused:true}) registered on window.__timelines).
  • ⚠️ A particle using only plain CSS animation-delay without a registered timeline cannot be rendered frame-by-frame and will freeze at the animation's end state. Author particles in a seekable format.

Create Task

Basics

ItemValue
MethodPOST
Path/task/html_render_simple
Content-Typeapplication/json
AuthAuthorization header (API Key directly)
BillingBy output duration (minutes)

Request Body

FieldTypeRequiredDefaultDescription
compositionobjectYesComposition spec, see below
renderobjectNo{}fps (defaults to composition.fps or 30) / quality (draft/standard/high, default high) / output_format (mp4/webm/qtrle, default mp4)

render object

FieldTypeRequiredDefaultDescription
fpsnumberNocomposition.fps or 30Render frame rate
qualitystringNohighdraft / standard / high
output_formatstringNomp4Output mode (see below): mp4 = composite base + particles into a finished video → .mp4; webm = render the transparent particle layer only (beats-only) as VP8-alpha WebM → .webm; qtrle = render the transparent particle layer only (beats-only) as QuickTime Animation (qtrle, argb) alpha MOV → .mov

output_format modes

  • mp4 (default): the base track and particles are composited into one finished video (.mp4). A video base is processed outside the particle renderer; a composition without a video base keeps the single-pass path.
  • webm: renders only the transparent particle layer (beats-only) as a VP8-alpha WebM (.webm). The base tracks do not participate in the composite (they stay local) — the WebM is meant to be decoded in the client browser via WebCodecs/mediabunny and composited natively on the client over the local base track.
  • qtrle: renders only the transparent particle layer (beats-only) as a QuickTime Animation (qtrle, argb) alpha MOV (.mov), for import into JianYing as a transparent overlay material (JianYing only reliably ingests qtrle; webm / ProRes-alpha show a black background in JianYing).
  • Transparent-layer modes (webm / qtrle): composition.tracks may be empty (mp4 still requires at least 1 track; webm / qtrle relax this); the base tracks are not written into the output, and the output duration equals the end of the last beat.

composition object

FieldTypeRequiredDefaultDescription
video_sizeobjectYes{"width":w,"height":h}
fpsnumberNo30Output frame rate
durationnumberNoautoOutput duration (s); derived from max track/particle end if omitted
assetsobjectYesMaterial refs, must contain file_id: {asset_name: platform_file_id} (base tracks and any file_id-referenced particles)
tracksarrayYesBase tracks (video/audio), at least 1 for mp4; may be empty under the transparent-layer modes (render.output_format = webm / qtrle), where the base does not enter the output
beatsarrayNo[]Custom HTML animation particle overlays

tracks[] base-track object

FieldTypeRequiredDescription
typestringYesvideo or audio
assetstringYesAsset name (key in assets.file_id)
track_indexnumberYesLayer (higher = front; no overlap within a layer)
startnumberYesStart time on the output timeline (s)
durationnumberNoDuration (s); optional for video/audio
mutedbooleanNoVideo only, default true
volumenumberNoAudio only, default 1.0

beats[] particle object

FieldTypeRequiredDescription
idstringNoUnique identifier
startnumberYesEnter time (s)
durationnumberYesOn-screen duration (s)
track_indexnumberYesOverlay layer (z-order)
opaquebooleanNoWhether the particle is full-screen opaque (covers the base). For simple scenes usually true (full-screen cut-in); pure HTML animation may also be transparent
htmlstringone ofInline: the particle HTML source directly in the field (self-contained, one call)
html_assetstringone ofReference: the particle HTML is uploaded; put its key in assets.file_id

Each particle must provide either html (inline) or html_asset (file_id reference).

Request Example

curl -X POST https://api.ai-mcn.tv:10000/task/html_render_simple \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "composition": {
      "video_size": {"width": 1920, "height": 1080},
      "fps": 30,
      "duration": 5.0,
      "assets": {"file_id": {"base": "78246108192718854"}},
      "tracks": [
        {"type": "video", "asset": "base", "track_index": 0, "start": 0, "duration": 5.0, "muted": true}
      ],
      "beats": [
        {"id": "b1", "start": 0.5, "duration": 4.0, "track_index": 10, "opaque": true,
         "html": "<template><div data-composition-id=\"p1\" data-width=\"1920\" data-height=\"1080\">...particle HTML with a GSAP timeline registration...</div></template>"}
      ]
    },
    "render": {"fps": 30, "quality": "high"}
  }'

Success Response

{"code": 200, "msg": "success", "data": {"task_id": "537489015178500", "task_type": "html_render_simple", "status": "queued"}}

Query Task Result

ItemValue
MethodGET
Path/task/html_render_simple/{task_id}
AuthAuthorization header

Response (output_result)

FieldTypeDescription
file_idstringOutput file ID
download_urlstringDownload path
durationnumberOutput duration (s)
video_sizeobject{"width":w,"height":h}

The output file depends on render.output_format: mp4 → the composited finished video (.mp4); webm / qtrle → the transparent particle layer only (.webm / .mov), to be composited over your local base track on the client / imported into JianYing — not a composited mp4.

Error Codes

CodeHTTPDescriptionFix
6013400Missing compositionProvide required params
6016400Invalid spec (particle missing html/html_asset, too many clips, duration ≤ 0, render out of range)Fix per response
6004404A file in assets.file_id does not existCheck file ID / upload
6014400Base-track material type mismatchCheck material type
6502401Auth failedCheck Authorization header
6201 / 6202402Quota / balance insufficientTop up

Limits

  • Output format: render.output_format must be one of mp4 / webm / qtrle (default mp4); any other value is rejected as out-of-range render. Under the transparent-layer modes (webm / qtrle) the base does not enter the output, composition.tracks may be empty, and the output is the beats-only transparent particle layer (.webm / .mov).
  • Base-track fitting (mp4): If the base track and composition.video_size have different aspect ratios, the base is scaled proportionally and padded to fit the canvas; it is not cropped.
  • Base-track audio (mp4): muted defaults to true for a video base track, so its audio is silent unless you explicitly set muted: false. A separate type: "audio" track is unaffected.
  • Base-track trimming limitation (mp4): Only the first video track is used. Its start / duration are applied, but media_start and later video tracks are not applied to source trimming or assembly.
  • Audio timeline limitation (mp4 with a video base): A separate audio track takes precedence, but only the first one is used; its start / duration / media_start / volume and additional audio tracks are not applied. When muted: false uses the video base's original audio, that audio is not shifted or trimmed by the video track's timeline fields.
  • Particles must be seekable: each particle must be wrapped in a <template>, declare data-composition-id, and register a frame-seekable timeline (see "Particle Format"); plain-CSS particles without registration will freeze.
  • Clip cap: base tracks + particles ≤ 200.
  • Billed by output duration (minutes); frame-by-frame rendering, so render time scales with duration/complexity — poll every 5–10 s.
  • Best for: full-screen opaque cut-ins / short clips / pure HTML animation; for a long base track running through the piece + transparent particle overlays (subject on camera + graphics that don't cover them), use HTML Animation Render (Layered).
  • Complementary to timeline render: use Timeline Render for single-track hard cuts; use this for a video base + custom animation particles.