templates/ ships with the repo (two-hander-golden-hour, record-store,
empty-stage), GET /templates + /templates/{name} behind the same slug and
path-traversal guards as /scenes; presentation metadata rides in a template
key that validate_scene ignores and toJSON drops, so loading then saving
yields plain scene JSON.
Test group asserts the three list in order, round-trip, traversal/unknown
rejected, write verbs refused, and every template passes validate_scene with
every referenced asset present on disk - the check that stops a rotten
template shipping. 10 groups green.
Verified live: two-hander loads 7 entities, 8s, both performers animating,
cut fires cam1 to cam2 at 4.5s; other two load clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.3 KiB
JSON
43 lines
1.3 KiB
JSON
{
|
|
"version": 1,
|
|
"name": "empty-stage",
|
|
"template": {
|
|
"title": "Empty stage",
|
|
"description": "A clean 10-second stage: one camera at eye height, a daylight key and ambient, nothing else. Drag your own characters and plates in.",
|
|
"order": 3
|
|
},
|
|
"fps": 30,
|
|
"duration": 10,
|
|
"entities": [
|
|
{
|
|
"id": "cam1",
|
|
"kind": "camera",
|
|
"label": "cam",
|
|
"source": { "type": "none" },
|
|
"params": { "fov": 40 },
|
|
"transform": { "pos": [0, 1.6, 6], "rot": [-0.0997, 0, 0], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "sun",
|
|
"kind": "light",
|
|
"label": "key",
|
|
"source": { "type": "none" },
|
|
"params": { "type": "key", "color": "#fff6e4", "intensity": 3, "castShadow": true },
|
|
"transform": { "pos": [6.58, 16.38, 9.4], "rot": [-1.0222, 0.35, 0.5113], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "amb",
|
|
"kind": "light",
|
|
"label": "ambient",
|
|
"source": { "type": "none" },
|
|
"params": { "type": "ambient", "color": "#dfe9ff", "intensity": 1.15, "bg": "#8fb0d6" },
|
|
"transform": { "pos": [0, 3, 0], "rot": [0, 0, 0], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
}
|
|
],
|
|
"cameraCuts": [{ "t": 0, "camera": "cam1" }],
|
|
"audio": []
|
|
}
|