Video
Bannx renders video the same way it renders images: a video template is a set of scenes built in the video editor, with variables you can override per render. The pipeline produces MP4s server-side (frames are rasterized in Node — no per-render browser), plus single-frame stills and bulk generation from data rows.
Authentication note: the video endpoints currently use dashboard session authentication — they power the video editor and are not yet callable with an
Authorization: BearerAPI key.
Concepts
- Project — the serialized editor document:
name,scenes[],tracks,music,assets. The editor keeps this in sync; render endpoints accept it as theprojectpayload alongside the video template'sid. - Scenes — each scene is a timed segment with layers (text, images, video, audio, Lottie). Variables work like image templates: mark a field once, override it per render.
- Renderers — previews run in the editor (HTML or Takumi); server MP4 renders rasterize frames with the Takumi engine in Node, then encode and upload.
Render an MP4
POST /api/video/render
Enqueues a render job and returns a job ID to poll.
Request body:
| Field | Type | Description |
|---|---|---|
id | string | Required. The video template ID. |
project | object | Required. The serialized editor project. |
width | number | 320–3840. Default: 1920. |
height | number | 180–2160. Default: 1080. |
fps | number | 1–60. Default: 30. |
quality | draft | standard | high | Default: standard. draft caps capture width at 960px for fast previews. |
Response: { "jobId": "…" }
GET /api/video/render/:jobId
Poll the job until it finishes.
| Status | Response shape |
|---|---|
| Rendering | { "status": "rendering", "progress": 0.35, "totalFrames": 180, "stage": "frames" } — stages: frames → audio → encode → upload → done |
| Done | { "status": "done", "progress": 1, "url": "https://…/video-media/….mp4", "totalFrames": 180 } |
| Failed | { "status": "error", "progress": 0.2, "error": "…" } |
Progress runs 0–0.8 during frame capture; the remainder covers audio, encoding, and upload. Errors: 400 missing jobId, 404 unknown job.
Render a still frame
POST /api/video/still
Synchronous — returns raw image bytes of one frame. Useful for thumbnails and scene previews.
| Field | Type | Description |
|---|---|---|
project | object | Required. Serialized editor project. |
time | number | Seek position in seconds. Default: 0. |
width | number | 64–3840. Default: 1920. |
height | number | 64–2160. Default: 1080. |
format | png | webp | svg | Default: png. |
Response: raw image body (image/png, image/webp, or image/svg+xml). Video and Lottie layers are omitted from stills (server-side rasterization).
Bulk generation
POST /api/video/bulk
One MP4 per content row — the video equivalent of bulk image generation. Each row's data is merged into the project's variables.
| Field | Type | Description |
|---|---|---|
id | string | Required. Video template ID. |
project | object | Required. Serialized editor project. |
rows | { name, data }[] | Required, at least one. data = variable overrides for that video. |
width, height, fps, quality | — | Same ranges/defaults as single render. |
Response: { "jobId": "…", "total": 12, "creditsNeeded": 120 }
Credits: 10 credits per successful video; failed rows are not billed (402 when the space has insufficient credits). Each row is retried up to 3 times.
GET /api/video/bulk/:jobId/stream
Server-sent events with live progress (every ~500ms):
{ type: 'progress', progress: { total, completed, succeeded, failed, currentItem,
videos: [{ name, status: 'pending'|'rendering'|'done'|'failed', url?, error? }] } }
{ type: 'done', result: { success: true, videos, succeeded, failed } }
{ type: 'error', error: '…' }
Uploading source media (tus)
Video/audio/image assets upload via the tus 1.0 resumable protocol — chunked (8 MB), resumable after network drops, up to 2 GB per file.
| Method | Path | Purpose |
|---|---|---|
POST | /api/video/tus | Create (or resume) an upload. Send Upload-Metadata: filename <base64>, filetype <base64>. |
HEAD | /api/video/tus/:id | Probe the current offset to resume. |
PATCH | /api/video/tus/:id | Append a chunk. The final PATCH responds with the file descriptor: { "url", "name", "kind": "image"|"video"|"audio"|"lottie"|"svg" }. |
DELETE | /api/video/tus/:id | Cancel an in-flight upload. |
Accepted types: PNG, JPEG, GIF, WebP, AVIF, SVG (sanitized), MP4, WebM, MOV, MP3, WAV, OGG, M4A, AAC, WebA, and Lottie JSON. Unsupported types return 415.
Limits
| Limit | Value |
|---|---|
| Resolution | 320×180 – 3840×2160 (stills from 64×64) |
| Frame rate | 1–60 fps |
| Output format | MP4 (H.264); stills as PNG/WebP/SVG |
| Upload size | 2 GB per file (8 MB chunks) |
| Bulk credits | 10 per successful video |