Assets
Register media, images and fonts before clips use them.
An asset describes a source file. Clips point at assets by id. The core stores metadata only: it never fetches or decodes the file. The renderer loads src when it needs it.
project.dispatch({
type: "asset/add",
payload: { id: "intro-mp4", kind: "video", src: "/media/intro.mp4", durationUs: 12_000_000, width: 1920, height: 1080 },
});Kinds
| Kind | Used by | Fields worth setting |
|---|---|---|
video | video clips | durationUs, width, height, fps |
audio | audio clips | durationUs |
image | image clips | width, height |
font | text and caption clips, by family name | family, weight, style, weightRange |
src is any URL the browser can fetch: a path, an https: URL, or an object URL from a file the user picked. See Asset import.
durationUs is what your UI uses to stop a trim at the end of the source. The core doesn't check clips against it.
Fonts
Register one asset per font face. Text clips reference fonts by fontFamily, not by asset id.
project.dispatch({
type: "asset/add",
payload: { id: "inter-400", kind: "font", src: "/fonts/Inter-Regular.woff2", family: "Inter", weight: 400 },
});
project.dispatch({
type: "asset/add",
payload: { id: "inter-700", kind: "font", src: "/fonts/Inter-Bold.woff2", family: "Inter", weight: 700 },
});
project.dispatch({
type: "clip/add",
payload: { kind: "text", id: "title", trackId: "titles", startUs: 0, durationUs: 3_000_000, text: "Hello", fontFamily: "Inter", fontWeight: 700 },
});For a variable font, register one asset with weightRange: [100, 900] instead of one per weight.
Provenance and licenses
Record where an asset came from and its license. The stock and AI audio importers do this for you.
project.dispatch({
type: "asset/add",
payload: {
id: "music-1",
kind: "audio",
src: "https://example.com/morning-walk.mp3",
durationUs: 92_000_000,
name: "Morning Walk",
source: { provider: "openverse", id: "8f2c", url: "https://openverse.org/audio/8f2c" },
license: { id: "CC-BY-4.0", commercial: true, attributionRequired: true },
attribution: "“Morning Walk” by Jane Doe, CC BY 4.0",
},
});Then check before export:
import { creditsFor, licenseReport, usedAssets } from "@miraiclip/core";
const doc = project.getState().doc;
usedAssets(doc); // assets at least one clip uses (fonts count by family)
creditsFor(doc); // credit lines for an end card or description
licenseReport(doc, { commercial: true });
// [{ assetId, kind: "non-commercial" | "unknown-license" | "missing-attribution", message }]The core only reports. Your app decides what to do: block the export, warn, or add a credits card. An asset with no license is flagged only if it has a source (it came from a provider), so the user's own uploads aren't flagged for a missing license.
Commands
| Command | Payload | Notes |
|---|---|---|
asset/add | { id, kind, src, …metadata } | |
asset/remove | { id } | Rejected with asset-in-use while clips use it |
asset/set-property | { id, name?, source?, license?, attribution? } | null clears a field |
src and kind can't change after adding: asset/set-property ignores them. To use a different file, add a new asset and replace the clips that use the old one (clip/remove + clip/add in one transaction). Templates swap files per video through asset fields.