Spaces:
Running
Running
File size: 9,015 Bytes
31c7d49 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | # 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:
```text
Blob/File/ImageBitmap/ImageData/canvas
-> WebGPU browser generation
-> { ply: Blob, splat: Blob, metadata, count }
```
The reusable implementation is [`examples/direct/image-to-splat.ts`](../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
1. Install the alpha tarballs as described in the [package README](../packages/triposplat-webgpu/README.md), or install `@ai3d/triposplat-webgpu` after publication.
2. Copy `examples/direct/image-to-splat.ts` into the client-side portion of the app.
3. 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.
4. Construct one `ImageToSplatGenerator` per browser tab and reuse it for queued requests.
5. Pass an alpha-bearing image, await `generate()`, and save or upload the returned PLY/`.splat` blobs according to the host product's policy.
6. Call `dispose()` when the page/component is torn down.
```ts
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 `removeBackground` callback in the constructor; or
- pass `inputIsPrepared: true` only 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 `Blob`s 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](gaussian-conventions.md).
## 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`](../examples/direct/model-config-server.mjs) shows a dependency-free Node endpoint:
```sh
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 `GET` the 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](model-hosting.md) for deployment details.
## Error and lifecycle contract
- Call `checkCompatibility()` before a large model download and present its blockers to the user.
- Use one `AbortController` per request. Cancellation terminates unsafe in-flight worker state; the same generator can retry and lazily creates a clean worker.
- `BackgroundRemovalRequiredError` is 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:
1. Put every import and `TripoSplatWebGPU` call behind the platform's browser/client boundary.
2. Accept native browser image objects; do not invent a base64-only API.
3. Run compatibility checking and expose cancellation plus progress.
4. Return or download **both** PLY and `.splat` unless the product explicitly requests one format.
5. Export before disposing the scene. Prefer the supplied adapter, which already guarantees this ordering.
6. Reuse one generator and dispose it on teardown; do not construct a model per render or request.
7. Do not claim opaque JPEG support unless a real local background-removal callback is configured.
8. Do not proxy the 6+ GB model through application compute, and do not upload input images by default.
9. Keep alpha-status and model-quality warnings visible while the package remains pre-release.
10. Validate the final integration in a real target browser against a complete immutable manifest.
A useful implementation request for another agent is:
```text
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](current-status.md) before making production quality, parity, memory, or cross-browser claims.
|