@miraiclip/templates
Parameterized videos for Miraiclip: a template project + a data payload → a hydrated document → export. Batch and personalized video generation, with field schemas that double as validation, UI forms, and LLM tools.
npm install @miraiclip/templates| Version | 0.1.3 |
| Runs in | Anywhere; /render is Node only |
| Exports | 40 |
| Guides | Defining templates, Batch rendering |
@miraiclip/templates
Functions
defineTemplate
Build a template from a document and its declared fields; throws on incoherence.
function defineTemplate(input: Omit<Template, "version">): TemplateGuides: Defining templates, Ad variants, Catalog to product video, Personalized video
describeTemplate
A compact, deterministic template summary for prompts.
function describeTemplate(template: Template): stringGuides: CLI, Data & validation, Defining templates
extractFields
Authoring aid: scan a document and propose its field list — one text
field per distinct placeholder (refine types by hand: numbers, colors,
enums), plus nothing for assets, which are declared intentionally.
function extractFields(doc: ProjectDocument): TemplateField[]Guides: Defining templates
fitClipsToMedia
Shorten video / audio clips that would play past the end of their media — e.g. after a media slot was filled with a clip shorter than the placeholder — and fit transitions to the footage their clips now have around each cut (shortened, or dropped when there's none). Later clips on the track don't move; returns a new document.
function fitClipsToMedia(doc: ProjectDocument): ProjectDocumentGuides: Roadmap, Data & validation, Catalog to product video
hydrate
Hydrate: validate the payload, then return a NEW document with every blank
filled. The template is never mutated. Throws TemplateValidationError on
a bad payload; tryHydrate is the non-throwing variant.
function hydrate(template: Template, data: TemplateData): ProjectDocumentGuides: Data & validation, Defining templates, Ad variants, Catalog to product video
insertCommands
The commands that add source (e.g. hydrate(template, data)) to
target. Pure: nothing is dispatched. Tracks without clips aren't added. The target's settings are left
alone; compare source.settings yourself if the frame size matters.
function insertCommands(target: ProjectDocument, source: ProjectDocument, options?: InsertOptions): InsertPlanGuides: Data & validation
insertDocument
Insert source into project as one undo step; returns the plan (ids, time range).
function insertDocument(project: Project, source: ProjectDocument, options?: InsertOptions): InsertPlanGuides: Roadmap, Data & validation
parseTemplate
Parse and validate untrusted template JSON (a parsed file, an API body).
function parseTemplate(json: unknown): TemplateGuides: Batch rendering, CLI, Defining templates, Ad variants
rowsFromCsv
CSV rows against a template: cells are strings, so values coerce to each field's declared type (numbers, booleans); an empty cell means "not provided" and the field's default applies.
function rowsFromCsv(template: Template, text: string): TemplateData[]Guides: Batch rendering, Data & validation, Personalized video
rowsFromNdjson
One JSON object per non-empty line.
function rowsFromNdjson(text: string): TemplateData[]Guides: Data & validation
scanPlaceholders
Every placeholder site in the document, in a stable order.
function scanPlaceholders(doc: ProjectDocument): PlaceholderSite[]Guides: Defining templates
suggestTemplateFields
Every place in the document that could be a field, in timeline order: text clips, string params of html clips (designed text, backgrounds; params starting with "_" are bookkeeping and skipped), and video / image / audio assets used by clips (media slots). Names are unique and stable for the same document.
function suggestTemplateFields(doc: ProjectDocument): TemplateCandidate[]Guides: Defining templates
templateFromDocument
Make a template from a document: each chosen candidate becomes an optional
field defaulting to its current value (a {{name}} placeholder in the
text or param; asset fields swap the asset's src). The document is not
modified. Hydrating the result with {} gives back the original content.
function templateFromDocument(doc: ProjectDocument, options: TemplateFromDocumentOptions): TemplateGuides: Defining templates
toFieldToolDefinition
The template's fields as one ready-to-send tool definition — the payload an
agent produces is exactly what hydrate takes.
function toFieldToolDefinition(template: Template, options?: ToFieldToolDefinitionOptions): unknownGuides: Tools from the command catalog, Data & validation, Ad variants
tryHydrate
Hydrate with machine-readable failures (the tryDispatch of templates).
function tryHydrate(template: Template, data: TemplateData): HydrateResultGuides: Batch rendering, Data & validation, Ad variants, Catalog to product video
validateData
Validate a payload against the template's fields; returns resolved values with defaults applied.
function validateData(template: Template, data: TemplateData): {
resolved: Resolved;
issues: TemplateIssue[];
}Guides: Data & validation
Classes
TemplateValidationError
Thrown by defineTemplate/parseTemplate/hydrate on invalid input.
Extends Error.
new TemplateValidationError(issues: TemplateIssue[])| Member | Type | Description |
|---|---|---|
issues | TemplateIssue[] |
Guides: Data & validation, Defining templates
Interfaces
AssetField
A media slot: the payload's value replaces the named asset's src (and
optionally durationUs). Hydration never touches clip timing — swapped
video/audio should match the placeholder's duration, or carry durationUs.
Extends FieldBase.
| Member | Type | Description |
|---|---|---|
type | "asset" | |
assetId | string | The asset in the template document this field replaces. |
default? | AssetValue |
BooleanField
Extends FieldBase.
| Member | Type | Description |
|---|---|---|
type | "boolean" | |
default? | boolean |
ColorField
A CSS color string ("#ff8c32", "rgb(...)", "tomato").
Extends FieldBase.
| Member | Type | Description |
|---|---|---|
type | "color" | |
default? | string |
InsertOptions
Putting a (hydrated) template into a project that already has content:
the document becomes a batch of ordinary commands — assets, tracks on top
of the existing ones, clips shifted to the insert time, their keyframes,
effects and transitions — with every id remapped so nothing collides.
insertDocument dispatches the batch as one transaction (one undo step).
| Member | Type | Description |
|---|---|---|
atUs? | number | Timeline position of the inserted document's 0 (default 0). |
idPrefix? | string | Prefix for the new ids (default: derived to avoid every id in the target). |
InsertPlan
| Member | Type | Description |
|---|---|---|
commands | Command[] | |
ids | { clips: Record<string, string>; tracks: Record<string, string>; assets: Record<string, string>; } | Source id → id in the target, for clips, tracks and assets. |
startUs | number | Where the inserted content starts and ends on the target timeline. |
endUs | number |
NumberField
Extends FieldBase.
| Member | Type | Description |
|---|---|---|
type | "number" | |
default? | number | |
min? | number | |
max? | number | |
integer? | boolean |
PlaceholderSite
Placeholder scanning: where {{field}} may appear in a document, and what
a document's placeholders are. The binding surface is deliberately small
and safe — sites whose values are CONTENT, never structure:
- text clip
text - caption word
text - html clip
paramsSTRING values
An html clip's template is NOT a site: its own {{param}} placeholders
belong to the clip's params and are consumed by the rasterizer — template
fields bind through the clip's params instead. Asset fields don't use
placeholders at all; they name an asset id.
| Member | Type | Description |
|---|---|---|
name | string | The placeholder's field name. |
path | string | Where it was found: "clips.intro.text", "clips.card.params.title". |
whole | boolean | True when the site's WHOLE value is one placeholder (typed binding). |
Template
A template: an ordinary ProjectDocument plus the declared blanks. Plain JSON end to end — it serializes, crosses process boundaries, and needs no code to run, exactly like the documents it hydrates.
| Member | Type | Description |
|---|---|---|
version | 1 | |
name | string | |
description? | string | |
category? | string | Library grouping, e.g. "intro", "social", "promo". |
tags? | string[] | |
thumbnail? | string | A preview image: a URL or a small data: URL. |
doc | ProjectDocument | |
fields | TemplateField[] |
Guides: Defining templates
TemplateFromDocumentOptions
| Member | Type | Description |
|---|---|---|
name | string | |
description? | string | |
category? | string | |
tags? | string[] | |
thumbnail? | string | |
fields? | TemplateCandidate[] | The candidates to turn into fields (from suggestTemplateFields, with name / label edited as you like). Default: all of them. |
TemplateIssue
One machine-readable problem with a template or a payload.
| Member | Type | Description |
|---|---|---|
path | string | Where: "fields.headline", "data.name", "doc.clips.intro". |
message | string |
TextField
Extends FieldBase.
| Member | Type | Description |
|---|---|---|
type | "text" | |
default? | string | |
maxLength? | number | |
pattern? | string | A RegExp source the value must match (anchored by the author as needed). |
enum? | string[] | Restrict the value to one of these. |
ToFieldToolDefinitionOptions
The AI surface: a template's fields as an LLM tool, and a compact template
summary for prompts — same philosophy as core's toToolDefinitions and
describeProject. An agent designs the template once (via commands/MCP);
from then on FILLING it is a plain tool call with a typed schema, and no
LLM sits in the render loop.
| Member | Type | Description |
|---|---|---|
style? | "anthropic" | "openai" | Wire shape: "anthropic" (default) → { name, description, input_schema }; "openai" → { type: "function", function: { name, description, parameters } }. |
name? | string | Tool name (default: "render_" + the template name, sanitized). |
Types
AssetValue
An asset payload value: a source alone, or a source with its duration.
type AssetValue = string | {
src: string;
durationUs?: number;
};HydrateResult
tryHydrate's result: a hydrated document, or the issues an agent can self-correct from.
type HydrateResult = {
ok: true;
doc: ProjectDocument;
} | {
ok: false;
issues: TemplateIssue[];
};TemplateCandidate
Something in a document that can become a template field.
type TemplateCandidate = {
kind: "text";
name: string;
label: string;
clipId: string;
value: string;
} | {
kind: "param";
name: string;
label: string;
clipId: string;
param: string;
value: string;
color: boolean;
} | {
kind: "asset";
name: string;
label: string;
assetId: string;
assetKind: "video" | "image" | "audio";
value: string;
};TemplateData
One data row: field name → value.
type TemplateData = Record<string, TemplateValue>;TemplateField
A template field: one declared blank in the document. The declaration is the whole API surface — it drives payload validation, UI form generation, and LLM tool schemas, the same one-source-of-truth pattern as the command catalog.
type TemplateField = TextField | NumberField | BooleanField | ColorField | AssetField;TemplateValue
A payload value for any field.
type TemplateValue = string | number | boolean | AssetValue;@miraiclip/templates/render (Node)
Functions
renderTemplateBatch
Render every row of rows through the template. Rows that fail (bad
payload, missing media) are reported per row and never abort the others,
unless stopOnError asks for that.
function renderTemplateBatch(template: Template, rows: TemplateData[], options: RenderTemplateBatchOptions): Promise<RenderTemplateBatchResult>Guides: Batch rendering, CLI, Ad variants, Catalog to product video
Interfaces
BatchProgress
| Member | Type | Description |
|---|---|---|
rowsDone | number | |
totalRows | number | |
row | BatchRow | The row that just finished. |
BatchRow
Batch rendering (Node-only): hydrate a template once per data row and
export each hydrated document through ONE (or a few) warm headless-Chrome
export sessions — createExportSession keeps the browser alive across
rows, so a row costs an export, not a browser launch.
Import path: @miraiclip/templates/render — kept out of the main entry so
browser bundles never touch playwright.
| Member | Type | Description |
|---|---|---|
index | number | |
data | TemplateData | |
ok | boolean | |
filePath? | string | Set on success. |
bytesWritten? | number | |
issues? | TemplateIssue[] | Set on failure: hydration issues, or the export error message. |
error? | string |
Guides: Batch rendering
RenderTemplateBatchOptions
Extends Omit<ExportFileOptions, "out" \| "onProgress" \| "signal">, Pick<CreateExportSessionOptions, "assets" \| "assetsDir" \| "browser">.
| Member | Type | Description |
|---|---|---|
out | string | ((data: TemplateData, index: number) => string) | Where each row's file goes: a pattern with {field} placeholders (any template field plus {index}), or a function of the row. Parent directories are created. |
concurrency? | number | Warm export sessions (= browsers) working the rows (default 1). |
stopOnError? | boolean | Stop scheduling new rows after the first failure (default: keep going). |
onProgress? | (progress: BatchProgress) => void | |
signal? | AbortSignal |
RenderTemplateBatchResult
| Member | Type | Description |
|---|---|---|
rows | BatchRow[] | |
failed | BatchRow[] | The rows that failed (empty means a clean batch). |
@miraiclip/react
React bindings for Miraiclip: providers, state hooks, playback, timeline behaviour hooks, and unstyled editor components.
@miraiclip/server-export
Server-side export for Miraiclip: run exportProject in headless Chrome from Node — same pipeline as the browser, preview/export parity by construction.