--- name: expocut-template-import description: "Bring outside project files into ExpoCut and send ExpoCut templates back out. Use when the user has a Lottie / Bodymovin JSON, a Final Cut Pro FCPXML (or FCP7 / Premiere xmeml), an Adobe .mogrt, an ASC CDL .cdl/.ccc, an Adobe .cube LUT or an ExpoCut .ectpl file and says \"import this\", \"open my After Effects / Final Cut export on the phone\", \"convert this template\", \"which fonts will it swap\", \"will HEVC / ProRes / alpha work on that Android phone\", or wants \"export to Lottie / FCPXML\". Also covers detect_format, migrate_template for old layer JSON, font fallback (resolve_font_fallback, audit_font_coverage, list_font_aliases) and codec / device-class queries. Do not use for hand-authoring a reel JSON (expocut-reel-templates), applying templates, brand kits or Community submissions (expocut-templates-brand), LUT / CDL grading in the editor (expocut-color-grading), or loudness (expocut-audio-post). CapCut .draft, .aep, .prproj, .drp and OTIO are detected but cannot be imported." license: Free to use and redistribute with attribution to expocut.com. compatibility: Works standalone as guidance; becomes hands-on when paired with the ExpoCut in-app MCP server (private/loopback network only). metadata: author: ExpoCut (expotechin.com) version: "3.0.0" homepage: https://expocut.com/skill.html --- # Template import and interchange with ExpoCut You are the interchange specialist: you turn a foreign project file into an ExpoCut Template JSON, load it onto the timeline, read out what the importer could not reproduce, fix the rest by hand, and round-trip finished templates back out to Lottie or FCPXML. The importer tools are pure functions — nothing on the phone changes until you call `import_template_json`, and every edit after that is undoable in the app. ## When to use / hand off - A file from another tool: this skill. Formats that import today: Lottie / Bodymovin `.json` (plain JSON, not the dotLottie zip), FCPXML `.fcpxml`, FCP7 / Premiere legacy XML (`` root), Adobe `.mogrt`, ASC CDL `.cdl` / `.ccc`, Adobe `.cube`, ExpoCut `.ectpl` as JSON text. - Detected but refused (the reason comes back from `detect_format`): `.otio` (recognised, parser not wired), `.aep`, `.prproj`, `.drp`, `.fcpbundle`, CapCut `.draft`, VN `.vn`. Tell the user which export to make instead: Bodymovin / Lottie from After Effects, FCPXML from Premiere, Resolve or Final Cut. - Hand-authoring or debugging an `.ectpl` reel JSON → expocut-reel-templates. - Applying the bundled template, brand profiles, saving or submitting templates → expocut-templates-brand (`import_template_json` lives there; you call it in step 5 below). - Registering a `.cube` and applying LUTs / CDL grades on layers → expocut-color-grading. - `measure_loudness`, `gain_to_loudness_target`, `build_loudness_plan`, `list_loudness_targets` are registered in this family but belong to the audio workflow → expocut-audio-post. - Fonts and text styling after import → expocut-kinetic-captions. Inspection and export → expocut-editor-ops. ## Before you start 1. Ask where the file is. On the phone (Files app, the app's document directory) → `import_from_file_system { path }`. Pasted or attached in the conversation → `import_foreign_file { filename, text }` for JSON / XML / `.cube` / `.cdl`, or `{ filename, bytesBase64 }` for `.mogrt`. Inputs over 16 MB are refused before parsing. 2. If the extension is missing or suspicious, sniff first: `detect_format { filename: "clip.xml", textHead: "" }`. For a zip pass `isZipContainer: true`. 3. Know what comes back: a Template document (`schemaVersion`, `id`, `name`, `category`, `aspectRatio`, `durationMs`, `slots`, `tracks`, `layers`) plus `warnings[]` with `severity: "info" | "warn"` and a `message`. Media never travels with Lottie / FCPXML / `.mogrt` imports — every clip, photo and audio file becomes an empty slot the user fills. 4. No importer tool needs an open project. `import_template_json` creates and opens one; `describe_canvas`, `capture_canvas`, `update_layer` then act on it. ## Core workflow 1. Detect (optional): `detect_format { filename: "title.mogrt", isZipContainer: true }` → `{ format: "mogrt", confidence: 1, reason }`. A refused type returns `format: "unknown"` with a reason such as `rejected: draft — CapCut draft — no schema, not importable`. Stop there and explain; do not try the importer. 2. Import — one of: `import_from_file_system { path: "file:///…/Documents/anim.json" }` `import_foreign_file { filename: "anim.json", text: "" }` `import_foreign_file { filename: "title.mogrt", bytesBase64: "" }` Success: `{ ok: true, format, template, extraTemplates, warnings }`. Failure: `{ ok: false, format, reason, warnings }` — `reason` is readable ("Expected zip container for .mogrt, got png", "FCPXML contained zero sequences", "OpenTimelineIO import is not yet supported"). 3. Read every warning to the user before touching anything: they list each dropped or approximated feature (per-format list in `references/formats.md`). An FCPXML with several `` elements returns the first as `template` and the rest in `extraTemplates` — ask which one to open. 4. Fonts. Collect the `fontFamily` values from `template.layers`, then `audit_font_coverage { fontNames: ["Bebas Neue", "Proxima Nova", "Georgia"] }` → `{ totalRequested, exact, aliased, fuzzy, histogram }`. For each fuzzy name confirm with `resolve_font_fallback { name: "Proxima Nova", weight: 700, category: "sans-serif" }` → `{ font: { id, label, … }, confidence, reason, exactMatch, requestedWeight }`. Confidence 1 is an exact bundled match, 0.95 the alias table, 0.5–0.85 a category guess, 0.25 the system font. Say the substitution in words ("Proxima Nova → Avenir Next") before applying it. 5. Load it: `import_template_json { template: , name: "Imported title" }`. It validates the document, inflates it, saves a new project and navigates the editor there; returns `{ projectId, layerCount, unfilledRequiredSlots, validationWarnings }`. Add `bindings` to pre-fill slots (recipe 2). Validation failures come back as one error listing every violation — fix the JSON and call again. 6. Review cheaply, then look: `describe_canvas { timeSec: 0 }` (text only: visible layers with bounding boxes in canvas %), then `capture_canvas { timeSec: 0, maxWidth: 512 }`, then a mid-timeline frame with `capture_canvas { timeSec: 2.5, maxWidth: 512, xray: true, grid: true }` for labelled boxes over a 10 % grid. `preview_filmstrip { fromSec: 0, toSec: 5, frames: 6 }` shows motion and pacing in one call. 7. Fix up: `list_layers` for ids, then `update_layer { id: "text0", patch: { fontSize: 42, textColor: "#FFFFFF" } }`, `set_text_font { layerId: "text0", fontFamily: "din-alternate" }`, `remove_layer { id: "shape3" }` for placeholder boxes (ask first), `reorder_layer { layerId: "video0", position: 5 }` when z-order came in wrong. Finish with `save_project`. 8. Out again: get a document with `save_project_as_template { id: "my-title-v1", name: "My title", mode: "snapshot" }` and pass it to `export_template_to_lottie { template: