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>
128 lines
3.6 KiB
JSON
128 lines
3.6 KiB
JSON
{
|
|
"version": 1,
|
|
"name": "two-hander-golden-hour",
|
|
"template": {
|
|
"title": "Two-hander — golden hour",
|
|
"description": "The lady and the man face each other on a golden-hour street plate. Wide master, cut at 4.5s to a tighter angled two-shot. 8 seconds, both performers already carrying a clip.",
|
|
"thumb": "backdrops/video/scenegod_plates/suburb_strip_goldenhour.jpg",
|
|
"order": 1
|
|
},
|
|
"fps": 30,
|
|
"duration": 8,
|
|
"entities": [
|
|
{
|
|
"id": "plate",
|
|
"kind": "backdrop",
|
|
"label": "golden hour street",
|
|
"source": {
|
|
"type": "assets",
|
|
"path": "backdrops/video/scenegod_plates/suburb_strip_goldenhour.mp4"
|
|
},
|
|
"params": {
|
|
"mode": "video",
|
|
"video": "backdrops/video/scenegod_plates/suburb_strip_goldenhour.mp4",
|
|
"width": 12,
|
|
"fit": "frustum",
|
|
"fitDist": 14,
|
|
"groundTint": true,
|
|
"videoStart": 0
|
|
},
|
|
"transform": { "pos": [0, 0, -8], "rot": [0, 0, 0], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "man",
|
|
"kind": "character",
|
|
"label": "man",
|
|
"source": { "type": "assets", "path": "characters/test/man.fbx" },
|
|
"params": {},
|
|
"transform": { "pos": [-1, 0, 0], "rot": [0, 0.55, 0], "scale": 1 },
|
|
"tracks": {
|
|
"transform": [],
|
|
"params": [],
|
|
"clips": [
|
|
{
|
|
"path": "animations/test/carrying.fbx",
|
|
"clipIndex": 0,
|
|
"start": 0,
|
|
"in": 0,
|
|
"out": 8,
|
|
"loop": 1,
|
|
"fade": 0
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"id": "lady",
|
|
"kind": "character",
|
|
"label": "lady",
|
|
"source": { "type": "assets", "path": "characters/test/lady.glb" },
|
|
"params": {},
|
|
"transform": { "pos": [1, 0, 0.25], "rot": [0, -0.6, 0], "scale": 1 },
|
|
"tracks": {
|
|
"transform": [],
|
|
"params": [],
|
|
"clips": [
|
|
{
|
|
"path": "animations/test/carrying.fbx",
|
|
"clipIndex": 0,
|
|
"start": 0,
|
|
"in": 2,
|
|
"out": 10,
|
|
"loop": 1,
|
|
"fade": 0
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"id": "cam1",
|
|
"kind": "camera",
|
|
"label": "wide",
|
|
"source": { "type": "none" },
|
|
"params": { "fov": 40 },
|
|
"transform": { "pos": [0, 1.5, 5], "rot": [-0.0898, 0, 0], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "cam2",
|
|
"kind": "camera",
|
|
"label": "closer",
|
|
"source": { "type": "none" },
|
|
"params": { "fov": 32 },
|
|
"transform": { "pos": [1.9, 1.45, 3], "rot": [-0.0875, 0.5862, 0.0485], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "sun",
|
|
"kind": "light",
|
|
"label": "sun",
|
|
"source": { "type": "none" },
|
|
"params": { "type": "key", "color": "#ffb469", "intensity": 2.6, "castShadow": true },
|
|
"transform": { "pos": [-16.18, 3.13, 11.33], "rot": [-0.1858, -0.9517, -0.1519], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
},
|
|
{
|
|
"id": "amb",
|
|
"kind": "light",
|
|
"label": "ambient",
|
|
"source": { "type": "none" },
|
|
"params": {
|
|
"type": "ambient",
|
|
"color": "#ffd9b0",
|
|
"intensity": 0.55,
|
|
"bg": "#d98a52",
|
|
"fog": 0.02
|
|
},
|
|
"transform": { "pos": [0, 3, 0], "rot": [0, 0, 0], "scale": 1 },
|
|
"tracks": { "transform": [], "params": [], "clips": [] }
|
|
}
|
|
],
|
|
"cameraCuts": [
|
|
{ "t": 0, "camera": "cam1" },
|
|
{ "t": 4.5, "camera": "cam2" }
|
|
],
|
|
"audio": []
|
|
}
|