Slopcamera

How-to guides

Render and edit spatial scenes

Patch named entities, use hardware rendering, import a saved world, or prepare a shot composition.

A spatial scene is an editable JSON document: named entities, calibrated cameras, asset manifests, and animation channels rendered through the local Three.js renderer. You inspect stable entity IDs, apply typed patches to retained source, and read receipts that name the exact source, request, runtime, and output behind every frame.

The slopcamera scene commands ship in the verified release. Source inspection and patching run under Bun; rendering also needs the admitted local Chrome runtime, and video encoding needs FFmpeg and FFprobe. Check slopcamera help scene and slopcamera doctor --json for this machine's contract.

Create and inspect a scene

slopcamera scene init product.scene.json --json
slopcamera scene inspect product.scene.json --json
slopcamera scene evaluate product.scene.json --camera camera_hero --time-us 1000000 --json

The starter contains a turning product on a pedestal, ambient and directional lights, and a calibrated 960 × 540 perspective camera. inspect reports entity IDs, cameras, assets, and known bounds without decoding asset bytes. evaluate samples the world state at an absolute microsecond without launching a renderer. slopcamera scene check product.scene.json validates the source on its own.

Render frames, contact sheets, and video

Save a render request as frame.json:

{
  "cameraId": "camera_hero",
  "selection": { "kind": "frame", "timeUs": 1000000 },
  "mode": { "kind": "beauty" }
}
slopcamera scene plan product.scene.json --request frame.json --json
slopcamera scene render product.scene.json --request frame.json --json

plan validates the source and estimates bounded work without opening a browser. render writes the output, the retained source and assets, and a receipt under the ignored artifacts/slopcamera/generated root, verifying asset bytes and native runtime identity first. Unsupported asset features fail explicitly rather than rendering a degraded frame.

SelectionRequest fieldsResult
frametimeUsOne PNG at the camera's calibrated resolution
contact-sheettimesUs, columns, cellWidth, cellHeight, fitA sampled grid; each cell renders at camera resolution, then resizes
videorange (startUs, endUs), frameRateLossless qtrle MOV with straight alpha

Frame sampling uses the rational frame rate before one-microsecond quantization, and ranges are half-open. Final delivery converts scene footage through the ordinary project compositor described in Edit and deliver video.

Render on the GPU

slopcamera scene render product.scene.json --request frame.json --profile three-webgl2-hardware-v1 --json

three-webgl2-hardware-v1 requires macOS and WebGL2 through ANGLE Metal, with matching observations from the active graphics context and browser. It rejects software or unknown fallback, and the receipt records the actual device, operating system, browser, and graphics capabilities. This profile accelerates scene rasterization only: it does not select a hardware video encoder or promise identical pixels across graphics drivers.

The same profile works on scene plan and scene project prepare-render. Alternatively set executionProfile inside the render request or profile inside a preparation request; a --profile flag must agree with an existing request field. When both are absent, the historical software contract is preserved.

Use three-spark-webgl2-hardware-v1 when the scene contains splats. Its pinned Spark and Three dependency closure runs in a separate bounded worker and WASM runtime, renders beauty output only, and keeps the same explicit scene clock and linear compositing as the other profiles. Frame publication fails on context loss or unsettled work.

Patch named entities

Read sceneSha256 from scene inspect and pin it in the patch document:

{
  "kind": "slopcamera.spatial-scene-patch",
  "schemaVersion": 1,
  "expectedSceneSha256": "<digest from inspection>",
  "operations": [
    { "kind": "set-color", "entityId": "entity_product", "color": "#f97316" }
  ]
}
slopcamera scene patch product.scene.json --patch patch.json --output product-orange.scene.json --json

A stale digest rejects the edit, and the command requires a new output path, so both revisions stay available. The operation vocabulary covers transforms (set-transform), hierarchy (reparent-entity), names (rename-entity), materials (set-color, set-opacity), cameras (set-camera), animation channels (set-channel, remove-channel), membership (add-entity, remove-entity), declared per-shot overrides (set-override, remove-override), asset manifests (add-asset, replace-asset), mesh representations (set-mesh-geometry), and generated output (replace-generator-output).

Camera changes alter view identity without touching evaluated world state, and an animated property cannot receive a conflicting constant override. Imported GLB entities in source-material mode accept transform edits; color and opacity edits require entity-material mode and are rejected when they would have no effect. Inspecting, seeking, and patching never rerun generator source; replacing generated output is an explicit operation that carries new provenance. After set-mesh-geometry or an asset replacement, inspect controls again because the new representation can remove editability, and set the new GLB node and clip addresses in the same patch.

Import a saved world

scene world import takes exact local payload references plus a declared normalization, and it works without a provider account:

slopcamera scene world import --input import.json --source-root . --output-root artifacts/slopcamera/generated/courtyard --json

The import input declares:

  • splat: a root-relative path, byte length, and SHA-256; an optional collider uses the same payload reference shape.
  • identities: stable assetId, entityId, and name, plus colliderAssetId exactly when a collider is present.
  • normalization: metersPerUnit, sourceUp, sourceHandedness: "right", and a complete transform with position, XYZW rotation, and uniform scale.
  • provenance: kind: "saved" or "worldlabs-marble". World Labs provenance additionally requires worldId, the exact retained collider, and the provider receipt whose world and payload identities must match the import.

The output is an import manifest, retained asset manifests, and one splat entity. Add every returned asset and that entity to a scene, and save the scene JSON inside the import output directory so the returned payload paths resolve. Scene rendering retains the metadata and any collider with the splat even after the original import directory disappears. A collider is retained as approximate geometry: it is not automatically visible, and it has no validated physics semantics.

Splat entities use world placement and a uniform, unsheared world scale, and the Spark profile requires a perspective camera. The profile admits opaque 3D meshes, alpha-tested surfaces, and camera-view overlays alongside splats; it rejects interleaved transparent 3D surfaces. Captured appearance is not relightable and has no independently editable material or object structure.

Historical slopcamera.world-labs-provenance receipts remain readable and are validated locally for imported worlds; the paid World Labs generation commands have been removed. Use the provider's returned scale and ground metadata when available. Missing metadata is unknown, so calibrate the import explicitly rather than labeling an assumed scale as measured.

Direct a project through shots

A shot binds a retained scene digest, a camera, a project range, a scene start time, and once, loop, or freeze playback; shot ranges use the project's source clock. Snapshot the existing project basis and inspect the migration schema before writing the request:

slopcamera scene project snapshot <project-id> --json
slopcamera operations show spatial.project.migrate --json
slopcamera scene project migrate <project-id> --input migrate.json --json

The migration request carries expected from that snapshot, a fresh transactionId (transaction_ plus 32 hexadecimal characters), scenes containing {sceneSha256, document}, and shots. Install declared asset payloads at their manifest paths inside the project directory first: sizes and digests must match, and migration does not search arbitrary source directories or download assets. Keep shot ranges within the existing project duration.

Migration publishes one V2 project head over an immutable aggregate that retains the original media project and edit plan. Legacy project writers reject V2 heads, so plan ordinary media edits before migration. scene project patch applies a scene patch across all shots or an explicit shotIds list through retarget, and scene project restore publishes a revision that returns to a retained scene digest without rewinding the project head. After an ambiguous publication, scene project reconcile verifies immutable evidence for the exact retained attempt before allowing recovery.

Deliver a frozen composition

scene project prepare-render freezes the projection, render plan, native toolchain, cadence, and output request into one prepared file:

slopcamera scene project prepare-render <project-id> --input prepare.json --output prepared-render.json --json

Preparation holds the project's lease and validates every shot before native work starts. Cameras must match the requested dimensions; preparation does not silently resize them. The full-frame policy (full-frame-above-legacy-video-below-overlays) rejects overlapping shots, and the initial path rejects legacy zooms and enabled click, cursor, keystroke, or typed-text effects. syncPolicy: "require-verified" rejects unverified placement synchronization; allow-unverified is an explicit choice for deliveries that accept the existing timing uncertainty.

The prepared file feeds the durable directed-scene workflow:

slopcamera workflows plan directed-scene --input prepared-render.json --json
slopcamera workflows run directed-scene --input prepared-render.json --json

Workflow planning and execution bind a build identity over the installed host source tree, so these commands require the installed Bun package or a checkout rather than a copied standalone executable; Run or recover a workflow covers the run model. The run verifies encoded dimensions, pixel format, frame timestamps, and audio duration before publishing, and a later project edit does not invalidate an already prepared composition. A changed source artifact or toolchain rejects the render. Output paths are project-relative and never overwrite another render.

Know the bounds

BoundLimit
Scene source2 MiB with up to 4,096 entities, 128 assets, and 64 cameras
One render1,800 frames, 1.1 billion rendered pixels, 256 MiB of source payloads, 256 MiB of output
Contact sheet64 samples
Preparation window32 frames
Staged asset and frame budget8 GiB, excluding the browser runtime, caches, and process memory
Project program64 shots sharing the frame, pixel, and staging budgets, plus 1 GiB of distinct shot video
Saved worldsgzip SPZ v2/v3 with flags=0 and no antialiasing, 500,000 aggregate splats, 128 MiB compressed and 64 MiB decompressed per source

These are first-release admission bounds, not claims about unlimited scene or world scale. Scenes use right-handed Y-up coordinates in meters, camera-local negative Z, and XYZW quaternions; author time in integer microseconds. The renderer rejects external GLB resources, unsupported extensions, skins, morph targets, sparse accessors, compressed meshes, cubic animation, WOFF2 fonts, and unsupported HDR or color profiles. For what each renderer contributes and where its limits sit, see the engine stack and the capability reference.