Narratomidocs
Cast and assets

Assets

The asset kinds the studio accepts, the file types and size caps for each, how quotas are counted, and what the built-in packs are licensed under.

Every file your story loads is an asset: an entry in the project library with a name, a kind, and a content hash. Uploads are content addressed, which is why replacing a file does not break a published version and why uploading the same file twice costs storage once.

The library lives in the right dock, under Assets. Pick an Upload kind first, since that select decides what the next upload becomes, then click Upload.

Kinds

KindWhat it is forAccepted file types
avatarA character body, staged and posed..glb, .vrm
environmentThe set a scene is staged in..glb, .vrm
clipAn animation clip, played by an animation stage direction..glb, .vrm
propAn object a stage direction places on a mark or in a hand. See Props..glb
audioMusic, ambience, blip sounds, voice lines.MPEG, MP3, OGG, WAV
videoA fullscreen cutaway movie.MP4, WebM
imageA fullscreen cutaway still.PNG, JPEG, WebP

Model kinds are validated as binary glTF 2.0. The picker hints .glb,.vrm by extension because browsers report those files as application/octet-stream, which matches everything on disk. Audio, video and image are checked by content type on the server; the allowlist above is the whole list, and anything else is refused with a 415.

There is no transcoding. What you upload is what the player's video or img element receives, which is why the container list is short: those are the ones every target browser decodes natively.

Limits

LimitDefaultNotes
Per file50 MBChecked in the browser before the upload starts, and again on the server.
Per project500 MBCounted over distinct content hashes.
Per account0.5 GB free, 5 GB Creator, 20 GB TeamPooled across every project the account owns.

Both the per-file cap and the per-project quota are deployment settings, so a self-hosted instance can differ. If a proxy or a deployment enforces a lower cap than the page knows about, the panel re-states the refusal using the cap the server actually applied.

"Counted over distinct content hashes" is the honest part of content addressing: if the same file is already in the project under another name, adding it again costs nothing. See Plan limits for the rest of the tiers.

What upload does to the file

  1. Refuses anything over the per-file cap, before hashing.
  2. Refuses a content type that is not on the kind's allowlist.
  3. For model kinds, runs the Khronos glTF validator. Structural errors reject the upload; common mesh-data complaints that every runtime loads anyway are muted. External buffers and images are refused, so a model must be self-contained.
  4. For avatar, detects a tier: vrm if the file carries the VRM or VRMC_vrm extension, humanoid-glb if the node names cover hips, spine and head, static otherwise. Only vrm and humanoid-glb avatars render on stage; a static one falls back to the capsule stand-in.
  5. For avatar, parses the expression names the model can actually play, so the expression stage direction can offer them by name.
  6. For clip, parses the animation names inside the file, so the clip picker can offer them by name.
  7. Hashes the bytes with SHA-256, skips the blob write if that hash already exists, and writes the row.

Rename, replace, delete

Rename changes the label only. Nothing references an asset by name.

Replace uploads a new file under the same asset id and keeps the row's own kind. The id now points at a new hash. Bundles reference hashes, not ids, so already-published versions keep serving the old file. This is the supported way to update an avatar or fix a mispainted texture.

Delete removes the row from your library. The blob itself only goes away when nothing else references that hash, neither another asset row nor a published version. The confirmation says so: "Frees quota only if no published version uses it."

Built-in packs

Every project also lists the starter packs. They show a built-in badge, cannot be renamed, replaced or deleted, and do not count against your storage, since they belong to no project.

The packs are CC0 only. That is a project rule, not a coincidence: each file is fetched with a recorded source URL, license string, SHA-256 and byte size, and the license string names where the CC0 claim came from (the VRM's own embedded metadata, the source project's license field, or the host's license page). Hover the badge, or open the inspector, to read the provenance for a given file.

If you upload your own assets, licensing is on you. Nothing in the studio checks it.

Missing assets

The compiler collects every asset id a story references and flags an id that is not in the library as MISSING_ASSET, naming the place: a scene's environment or ambient, a cast avatar, a line's voice audio, a cutaway. Filtering the panel does not cause this; the filter is view-only and the live compile always sees the full list.

On this page