How to Use .ectpl: The ExpoCut Template & Canvas Render Format
An .ectpl file is not a video — it is a recipe for one. This guide explains exactly how ExpoCut's template format separates structure from content, how the inflater turns a recipe into a real editable project, and how a resolution-independent canvas renders that project to a finished 4K video on your phone. Written for creators, developers, and the AI assistants that increasingly build videos for them.
If you have ever wished you could record one great video once and then reuse its structure — the timing, the captions, the lower thirds, the music beats, the color grade — for a hundred different clips, the .ectpl format is the answer. It is the file behind ExpoCut's template gallery, its "Save as Template" button, and its AI-driven, data-merged video generation.
1. What is an .ectpl file?
.ectpl stands for ExpoCut Template. It is a JSON document — currently schema version 1.0 — that describes a video project as a reusable recipe rather than a flattened stream of pixels. A single .ectpl file declares:
- Slots — the named holes a user (or an AI) fills with their own clips, photos, text, logo, or music.
- Layer prototypes — the visual and audio building blocks (text, shapes, video, lower thirds, effects) that reference those slots.
- Tracks — how layers stack across the multi-track timeline.
- Canvas settings — aspect ratio and total duration.
- An optional asset bundle — fonts, LUTs, and bundled media packaged for portability, with licensing metadata.
Because it is plain JSON, an .ectpl is small, diff-able, version-controllable, human-readable, and — crucially — machine-writable. A language model can read or author one as easily as a person can.
2. A recipe, not a rendered video
The most important idea in the entire format is this single distinction:
An MP4 is the finished cake. An .ectpl is the recipe card. The MP4 has fixed footage, fixed words, and a fixed resolution baked in forever. The .ectpl keeps structure (layout, timing, animation, effects, color) separate from content (the media and copy dropped into each slot) — so the same recipe produces an infinite family of videos.
This separation is what makes templates powerful. A real-estate agent fills the same "Just Listed" template with new photos and a new address every week. A brand fills a promo template with its logo and colors automatically. An AI assistant fills a template from a spreadsheet row to bulk-generate fifty product videos. In every case the design work is done once; only the content changes.
3. Anatomy of the format
At the top level, an .ectpl file is a single JSON object — a Template — optionally accompanied by a bundle sidecar. Here is the shape, trimmed to its essential fields:
// the top-level Template object inside an .ectpl file { "schemaVersion": "1.0", "id": "promo-just-listed-01", "name": "Just Listed — Minimal", "description": "A clean real-estate promo with three photo beats.", "category": "Real Estate", "aspectRatio": "9:16", "durationMs": 12000, "slots": [ /* fillable holes — see §4 */ ], "tracks": [ /* timeline tracks */ ], "layers": [ /* layer prototypes — see §5 */ ], "applyBrandingByDefault": true, "voiceover": { /* optional TTS script — see §8 */ } }
The five load-bearing fields are slots, layers, tracks, aspectRatio, and durationMs. Everything else is metadata for the gallery and the inflater.
| Field | Purpose |
|---|---|
schemaVersion | Format version. Only "1.0" is accepted today; the importer rejects unknown versions rather than guessing. |
id | Globally unique identifier. New ids are stamped at inflate time so multiple instances never collide. |
category | Gallery rail — e.g. Real Estate, Promo, Birthday, Travel, Food, Events. |
aspectRatio | One of 9:16, 1:1, 16:9, 4:5, 4:3. Defines the canvas shape, not its pixel size. |
durationMs | Total timeline length in milliseconds. |
slotCounts | Optional UI hint (how many video / image / text slots) for the gallery card. |
4. Slots: the fillable holes
A slot is a named, typed placeholder. It is the contract between the template author and whoever uses the template. Each slot declares what kind of content it accepts and how it should behave when left empty.
// a TemplateSlot inside the "slots" array { "id": "hero_clip", "label": "Opening shot", "kind": "video|image", // accepts either "required": true, "preferredDurationMs": 4000, // "looks best at ~4s" "bindFromBrand": null // or "logo" / "name" / "slogan" … }
| Slot property | Meaning |
|---|---|
kind | video, image, video|image, text, audio, or logo. |
required | If true and left unfilled, the layer that depends on it is dropped and the editor can block export until it is filled. |
default | Fallback text for a text slot left blank (e.g. a placeholder headline). |
bindFromBrand | Auto-fills from the active Brand Profile: logo, name, slogan, website, phone, email, or address. |
defaultBinding | A pre-bound value — typically the original Pexels/Freesound URL of a clip — so a shared template still renders on a device that never had the author's local file. |
That last field, defaultBinding, is the quiet hero of portability: it carries the canonical remote URL of the asset the author originally used. When you open someone else's template, the demo preview fetches from that URL even though the author's local cache file does not exist on your phone.
5. Layer prototypes
A layer prototype is a partially-filled layer — every field the author already knows is set, and a slotRef points at the slot whose value the inflater will stitch in. Prototypes can be any ExpoCut layer type: text, video, image, shape, lowerthird, audio, animation, light-leak, mask, widget, and more.
// a LayerPrototype that fills itself from the "hero_clip" slot { "id": "L1", "type": "video", "slotRef": "hero_clip", // ← which slot feeds this layer "startTime": 0, "duration": 4000, "trackIndex": 0, "position": { "x": 50, "y": 50 }, // % of canvas — see §6 "stretchToCanvas": true }
Required prototype fields: id, type, startTime, duration, trackIndex. Every other layer field defaults to a safe value inside the inflater.
Two special bindings handle multi-line content elegantly:
lowerThirdLineSlots— on a lower-third layer, each entry maps a configured line to a text slot, so a three-line lower third becomes three editable fields. An empty string leaves a line exactly as authored.- A layer can also carry inline media directly (no slot) via its
remoteSource.url— used by saved-project templates where, say, a shape's video fill is baked into the design rather than user-fillable.
6. The canvas: percentage-based, resolution-independent
Here is the engineering decision that lets a single .ectpl render perfectly to a tiny preview thumbnail and a 4K export: every layer is positioned on a 0–100 percentage grid, never in fixed pixels.
A position of { x: 50, y: 50 } means "dead center," whatever the output size. At render time, ExpoCut's coordinate system maps those percentages to real pixels for whichever canvas is being drawn:
// conceptually, inside the rendering layer resolveLayerTransform(layer, outputWidth, outputHeight) // 50% x on a 1080-wide preview → 540 px // 50% x on a 2160-wide 4K export → 1080 px
Font sizes follow the same philosophy: text is authored against a reference canvas width and scaled proportionally, so a headline that fills the frame in the editor fills it identically in the export. The practical payoff:
- One template, every aspect ratio and resolution. No per-device layout files.
- Pixel-parity between preview and export. The gallery thumbnail, the editor canvas, and the final encode all run the same paint code through one shared renderer, so what you preview is what you export.
7. The inflater & binding priority
A template on disk is inert. The inflater is the pure function that brings it to life: it takes (template, bindings, brand) and returns a real project — exactly the shape the editor and the native encoder already consume. There is no parallel data model; an inflated template is an ordinary ExpoCut project.
For every slot, the inflater resolves a value using a strict priority order:
User binding
Whatever the person (or AI) dropped into the slot — a clip, a photo, a line of text. Highest priority.
Template
defaultBindingThe pre-bound remote URL the author shipped with the template, so shared templates work on a fresh device.
Brand auto-fill
If the slot has
bindFromBrand, the matching field from the active Brand Profile (logo, name, slogan…).Text default
For text slots, the author's placeholder copy. Lowest priority.
The inflater also does the housekeeping that makes templates robust: it stamps fresh layer ids on every inflate (so you can drop the same template into a project twice without collisions), drops layers whose required slot is unfilled, and materializes the Track[] and timeline clips alongside the layers so the project loads through the normal pipeline with zero special-casing.
8. Brand binding & voiceover
Brand profiles
When applyBrandingByDefault is true, any slot marked bindFromBrand fills automatically from the user's saved Brand Profile at inflate time. Switch the active brand and the same template re-skins itself — logo, business name, contact details, and slogan all update in one step. This is what turns a generic promo into your promo without touching the timeline.
Built-in voiceover
A template may ship a voiceover recipe — a narration script timed to the visual beats. When the user taps "Try with samples," ExpoCut's on-device text-to-speech synthesizes the narration and binds the resulting audio into the named audio slot:
{
"voiceover": {
"slotId": "vo_track",
"script": "Just listed in the heart of downtown…",
"voiceId": "am_michael",
"speed": 1.0
}
}
The narration is generated entirely on the device — no audio leaves the phone — and the user can re-record manually at any time.
9. Asset bundles & licensing
To travel between devices, a template often needs to carry its assets — custom fonts, 3D LUTs, and bundled media. That is the job of the optional BundleManifest, stored under the bundle field. Each bundled asset records a stable id, a kind (font, lut, image, video, audio, data), a path inside the bundle, an optional sha256 checksum for de-duplication and integrity, and — importantly — licensing metadata:
{
"bundle": {
"version": "1.0",
"assets": [
{
"id": "font-0",
"kind": "font",
"path": "fonts/Inter.ttf",
"sha256": "9f86d0…",
"license": { "spdx": "OFL-1.1", "redistributable": true }
}
]
}
}
On import, ExpoCut validates the manifest, runs a license guard (flagging anything not marked redistributable), and reports any unresolved assets that still need to be extracted from the bundle's ZIP before the template can render. The de-dup logic means two layers using the same font share one file by checksum. The result is a self-contained, portable, license-aware container you can share without breaking attribution.
10. The render pipeline: from recipe to 4K
Once a template is inflated into a project, three surfaces can draw it — and they deliberately share their paint code so they never drift apart:
- The gallery preview — the schematic thumbnail and demo modal in the template browser.
- The editor canvas — the live, draggable, animated surface you edit on. It adds selection, video playback, and animation on top of the same paint path.
- The export encoder — the hardware-accelerated, on-device encoder (H.264 / HEVC) that writes the final 4K MP4.
Every static layer — shape, text, image — is painted through one shared component, fed by a single source-of-truth layout contract. Layout constants and the text-style mapping live in exactly one place; a parity test even greps the codebase to fail the build if anyone reintroduces a hardcoded duplicate or a second renderer. This is why a template looks the same in the gallery, on the canvas, and in the export: by construction, not by luck.
The whole journey: .ectpl JSON → inflater resolves slots & brand → real Layer[] on a percentage canvas → shared renderer paints each frame → on-device encoder writes a 4K MP4. The recipe never had pixels; the pipeline produces them on demand, at any resolution.
11. How to create your own .ectpl
You do not need to write JSON by hand. The fastest path is to design once and let ExpoCut derive the template for you:
Build the project
Edit a video in ExpoCut exactly the way you want the template to look — footage, text, lower thirds, music, color grade, effects.
Save as Template
ExpoCut runs the inverse of the inflater. It auto-detects slots: full-bleed video/image become media slots, audio becomes an audio slot, text becomes editable text slots with your copy as the default, and each lower-third line becomes its own text slot. Shapes, animations, and effects stay baked in.
Review & name slots
Give slots friendly labels ("Opening shot," "Your tagline"), mark which are required, and optionally bind some to brand fields.
Share the .ectpl
Export the template. ExpoCut packages an asset bundle with licensing metadata so it renders on any device. Anyone can import it, fill the slots, and export their own 4K video.
The "Save as Template" output is deterministic: the same project always produces the same .ectpl, and inflating that template reproduces a structural match of the original project. Recipe in, identical structure out.
12. .ectpl for AI assistants & automation
Because the format is plain, documented JSON and the editor exposes an in-app MCP server, .ectpl is a first-class interchange format for AI-driven video. An assistant connected to ExpoCut can:
- Author a template directly as JSON, or modify an existing one.
- Inflate and fill slots programmatically — including from structured data like a spreadsheet or product feed.
- Bulk-generate dozens of on-brand variations from one recipe, one row of data at a time.
- Render each result to a finished video through the same on-device pipeline, queued via the render engine.
This is the scenario the format was built for: design the structure once, then let a person or a model pour content into the slots at scale. For AI assistants, ExpoCut also ships a library of portable Skills and an MCP server that make this hands-on rather than hypothetical.
Writing templates programmatically? The full .ectpl format specification is the reference version of this article — every field, enum, unit, resource cap, the URI security policy, the pack/unpack pipeline and a performance cost model, plus an operating doctrine for agents. It is also served as data at /ectpl/spec.json and as plain text at /ectpl/doctrine.txt.
Frequently asked questions
What is an .ectpl file?
An ExpoCut Template — a JSON document (schema 1.0) that describes a video as a reusable recipe of fillable slots, layer prototypes, tracks, an aspect ratio, a duration, and an optional bundled-asset manifest. The editor inflates it into a real, editable, 4K-renderable project.
How is it different from an exported MP4?
An MP4 is the final, fixed pixels. An .ectpl is the parametric source: the same template can be filled with different media, text, logos, and brand colors, then re-rendered at any resolution.
How do I create one?
Build a project in the editor and tap "Save as Template." ExpoCut auto-detects slots and packages a portable, license-aware .ectpl you can share.
Why percentage-based coordinates?
A 0–100 grid makes a template resolution-independent — the same recipe renders correctly to a small preview or a 4K export because positions map to pixels for whatever output size is requested.
Can AI generate .ectpl files?
Yes. The format is plain JSON, and ExpoCut's in-app MCP server lets an assistant import, inflate, fill, and render templates — making .ectpl a practical format for data-merged, bulk, AI-driven video.
Turn one great edit into a hundred videos
Design once, save as a template, and let ExpoCut — or your favorite AI assistant — fill the slots.
Get ExpoCut Explore AI Skills