Spaces:
Running
Direct and agent integration
Use this guide when adding local image-to-3D generation to an existing web product. The stable application boundary is intentionally small:
Blob/File/ImageBitmap/ImageData/canvas
-> WebGPU browser generation
-> { ply: Blob, splat: Blob, metadata, count }
The reusable implementation is examples/direct/image-to-splat.ts. It accepts browser image sources, exports both portable formats, and disposes the large in-memory Gaussian scene deterministically.
Runtime boundary: inference runs in a current WebGPU-capable Chromium browser. Node.js, serverless functions, React Server Components, and edge workers may provide configuration or host assets, but they must not call
generate(). Do not upload a user's image to a backend unless the product explicitly requires and discloses that behavior.
Five-minute onboarding
- Install the alpha tarballs as described in the package README, or install
@ai3d/triposplat-webgpuafter publication. - Copy
examples/direct/image-to-splat.tsinto the client-side portion of the app. - Host the complete, immutable model manifest and artifacts on an object CDN. This is currently about 6.465 GB; do not proxy it through an application function.
- Construct one
ImageToSplatGeneratorper browser tab and reuse it for queued requests. - Pass an alpha-bearing image, await
generate(), and save or upload the returned PLY/.splatblobs according to the host product's policy. - Call
dispose()when the page/component is torn down.
import { ImageToSplatGenerator } from './image-to-splat'
const generator = new ImageToSplatGenerator({
modelBaseUrl: 'https://cdn.example.com/triposplat/v1/',
cache: 'opfs',
})
const report = await ImageToSplatGenerator.checkCompatibility()
if (!report.supported) throw new Error(report.blockers.join('\n'))
const output = await generator.generate(file, {
steps: 4,
seed: 42,
onProgress: ({ message }) => console.info(message),
})
saveBlob(output.ply, 'object.ply')
saveBlob(output.splat, 'object.splat')
await generator.dispose()
Inputs
The package accepts Blob, File, ImageBitmap, ImageData, HTMLImageElement, HTMLCanvasElement, and OffscreenCanvas. Prefer a File/Blob from a local picker or drag-and-drop surface; no base64 conversion is needed.
An alpha-bearing subject image works directly. A normal opaque JPEG does not contain a foreground mask and fails with BackgroundRemovalRequiredError. Until a qualified remover is bundled, either:
- request a transparent PNG/WebP from the user;
- provide a validated browser-local
removeBackgroundcallback in the constructor; or - pass
inputIsPrepared: trueonly for the exact preprocessed 1024×1024 opaque RGB-on-black representation.
Never set inputIsPrepared merely to bypass the error for a raw photograph.
Outputs
ImageToSplatResult owns two browser Blobs and JSON-compatible metadata:
| Field | Meaning |
|---|---|
ply |
Binary little-endian 17-float 3DGS PLY |
splat |
De-facto 32-byte browser .splat records |
count |
Number of exported Gaussians; currently 262,144 |
metadata |
Coordinate, encoding, model revision, seed, and generation settings |
elapsedMs |
Generation plus both encodes |
Use blob.arrayBuffer() for APIs that need bytes, URL.createObjectURL(blob) for browser downloads/viewers, or send the blob to object storage only when remote persistence is an intentional product feature. The .splat extension is ambiguous across tools; consumers must support the layout documented in Gaussian conventions.
Platform recipes
Vite, Vue, Svelte, Angular, and plain bundled apps
Import the adapter only from client code. Keep one instance in application scope, generate from event handlers, and dispose it on application teardown. Vite resolves the package worker automatically.
React
Create the generator in a client component or provider, retain it in a ref, and dispose it in the effect cleanup. Keep output blobs or object URLs in state; never put the canonical scene's typed arrays in React state.
Next.js
Place the adapter behind a file containing 'use client', or dynamically import the client component with SSR disabled. A Route Handler may return the public model URL, but generation cannot run in a Server Component or Route Handler.
Server-rendered and multi-tenant products
Expose only non-secret public configuration to the client. examples/direct/model-config-server.mjs shows a dependency-free Node endpoint:
TRIPOSPLAT_MODEL_BASE_URL=https://cdn.example.com/triposplat/v1/ \
node examples/direct/model-config-server.mjs
Mount createTripoSplatConfigHandler() in an existing Node server, or implement the same JSON response in another backend. Do not expose signing secrets. Use the package's custom fetch, request-init options, or short-lived signed artifact URLs when model access is private.
Native mobile and desktop shells
Run the client integration inside a Chromium WebView that exposes WebGPU, module workers, Canvas/OffscreenCanvas, and adequate storage. A native Node/Electron main process cannot substitute for the browser renderer. Always execute checkCompatibility() on the target shell.
Model hosting requirements
- Preserve every external-data path exactly as declared by its ONNX graph and manifest.
- Serve immutable versioned files from an object CDN with CORS, byte ranges, and correct content lengths.
- Allow the app origin to
GETthe manifest, graph files, and sidecars. - Prefer
cache: 'opfs'; the first run downloads and verifies the declared artifacts. - Do not bundle model payloads into npm packages, serverless functions, or the application JavaScript bundle.
- Treat the model URL as public unless access is enforced with short-lived browser-compatible authorization.
See Model hosting for deployment details.
Error and lifecycle contract
- Call
checkCompatibility()before a large model download and present its blockers to the user. - Use one
AbortControllerper request. Cancellation terminates unsafe in-flight worker state; the same generator can retry and lazily creates a clean worker. BackgroundRemovalRequiredErroris an input/action error, not a WebGPU failure.- Show load and generation progress; initial verified artifact loading can be long.
- Generation calls on one model are serialized. Implement a visible queue or cancel/replace policy rather than creating concurrent model instances.
- Keep returned blobs only as long as needed. Revoke object URLs created for previews/downloads.
- Call
dispose()exactly once during teardown; it is idempotent.
Instructions for coding agents
When adapting this example to another codebase, preserve these invariants:
- Put every import and
TripoSplatWebGPUcall behind the platform's browser/client boundary. - Accept native browser image objects; do not invent a base64-only API.
- Run compatibility checking and expose cancellation plus progress.
- Return or download both PLY and
.splatunless the product explicitly requests one format. - Export before disposing the scene. Prefer the supplied adapter, which already guarantees this ordering.
- Reuse one generator and dispose it on teardown; do not construct a model per render or request.
- Do not claim opaque JPEG support unless a real local background-removal callback is configured.
- Do not proxy the 6+ GB model through application compute, and do not upload input images by default.
- Keep alpha-status and model-quality warnings visible while the package remains pre-release.
- Validate the final integration in a real target browser against a complete immutable manifest.
A useful implementation request for another agent is:
Integrate @ai3d/triposplat-webgpu using docs/agent-integration.md and
examples/direct/image-to-splat.ts. Keep inference client-only, reuse one
ImageToSplatGenerator, accept File/Blob input, show compatibility/progress/
cancellation, expose both PLY and .splat downloads, handle opaque-input errors,
and dispose resources on teardown. Do not proxy models or upload user images.
Acceptance checks:
- an alpha-bearing image reaches all five generation stages;
- cancel followed by retry works without a page reload;
- both non-empty blobs download with the expected extensions;
- the reported count and metadata are available to the host app;
- opaque input gives a clear background-removal action;
- page/component teardown disposes the generator;
- network inspection shows only configured app/model requests unless remote output storage was deliberately added.
This remains an alpha integration. Review Current status before making production quality, parity, memory, or cross-browser claims.