SPATIAL_EMBEDDING
Put OpenStrate-powered 3D on your own site. After reconstruction, you get a stable viewer URL — drop it into an iframe on your marketing site, docs, or customer portal. No proprietary plugin: standard HTML, optional streaming for heavy models.
Powered by OpenStrate viewer infrastructure · SiL / Spacial Intelligence Labs
00_MODES
Two integration paths. Local is zero-ops: the user’s browser loads and renders the asset. Stream runs the viewer on your server and delivers H.264 over WebRTC — ideal for large meshes, thin clients, and mobile.
| Mode | Mechanism | Server | Best for |
|---|---|---|---|
| Local | Browser downloads & renders the model | No | Small models, lowest latency |
| Stream | Headless render + WebRTC video + input channel | Yes (embedded-viewer service) | Large models, mobile, no big downloads |
01_LIVE_LAYOUT
On your page, the viewer occupies an iframe inside your layout (hero, product detail, case study,
etc.). Below is the structure users see — the inner region is where your src= points at OpenStrate or your stream host.
02_STREAM_ARCHITECTURE
Stream mode uses a small Node service (Puppeteer + Chrome) that opens the same OpenStrate viewer, captures the WebGL canvas, and negotiates WebRTC with the embedded client. Input is forwarded over a data channel.
┌──────────────────────────────────────────────────────────────┐ │ Visitor browser │ │ ┌─────────────┐ WebSocket ┌────────────────────────┐ │ │ │ client.js │ ◀──────────────▶ │ streaming server │ │ │ │ <video> │ ◀── H.264 WebRTC │ (headless Chrome) │ │ │ │ pointer ───┼── DataChannel ──▶│ renders VIEW_ORIGIN │ │ │ └─────────────┘ └────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘
03_LOCAL_EMBED
Replace YOUR_FILE_ID.glb with the id and extension you
receive after upload (same URL you’d open in a new tab).
<iframe src="https://openstrate.com/view/YOUR_FILE_ID.glb" width="800" height="500" frameborder="0" allow="autoplay; fullscreen" allowfullscreen style="border: none; border-radius: 8px;" ></iframe>
Supported formats
| Extension | Format |
|---|---|
| .glb | glTF binary (meshes + point clouds) |
| .ply | Stanford PLY (point clouds) |
| .stl | STL (meshes) |
| .bin | OpenStrate binary point cloud |
| .omxl | OpenStrate indexed mesh / point cloud |
Responsive 16:9 container
<div style="position: relative; width: 100%; padding-bottom: 56.25%; overflow: hidden; border-radius: 8px;">
<iframe
src="https://openstrate.com/view/YOUR_FILE_ID.glb"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;"
allow="autoplay; fullscreen"
allowfullscreen
></iframe>
</div>
04_STREAM_EMBED
Run the embedded-viewer service where browsers can reach it (HTTPS in production).
Point VIEW_ORIGIN at the host that serves /view/ (typically https://openstrate.com).
cd embedded-viewer npm install STREAM_PORT=8090 VIEW_ORIGIN=https://openstrate.com node server.js
Production-style flags
STREAM_PORT=8090 \ VIEW_ORIGIN=https://openstrate.com \ STREAM_MAX_SESSIONS=8 \ STREAM_POOL_SIZE=3 \ STREAM_USE_GPU=1 \ node server.js
Iframe — swap in your stream host:
<iframe src="https://your-stream-server.com/stream/YOUR_FILE_ID.glb" width="800" height="500" frameborder="0" allow="autoplay; fullscreen" allowfullscreen style="border: none; border-radius: 8px;" ></iframe>
Visibility pause — load the helper once; mark embeds with data-openstrate so streams pause off-screen:
<script src="https://your-stream-server.com/embed-helper.js"></script> <iframe src="https://your-stream-server.com/stream/YOUR_FILE_ID.glb" data-openstrate width="800" height="500" frameborder="0" allow="autoplay; fullscreen" allowfullscreen ></iframe>
Manual postMessage (same contract as the helper):
<script>
const iframe = document.querySelector('#my-viewer');
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
iframe.contentWindow.postMessage({
type: 'openstrate-visibility',
visible: entry.isIntersecting
}, '*');
}
}, { threshold: 0.1 });
observer.observe(iframe);
</script>
05_FULL_PAGE_EXAMPLE
Minimal company page with both a local viewer and a streamed viewer slot.
Expand full HTML example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Models — My Company</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 900px;
margin: 40px auto;
padding: 0 20px;
background: #111;
color: #ddd;
}
h2 { margin: 32px 0 12px; }
.viewer-container {
position: relative;
width: 100%;
padding-bottom: 56.25%;
overflow: hidden;
border-radius: 8px;
background: #0a0a0a;
margin-bottom: 24px;
}
.viewer-container iframe {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
border: none;
}
</style>
</head>
<body>
<h1>Our 3D Scans</h1>
<h2>Office Lobby (local rendering)</h2>
<div class="viewer-container">
<iframe
src="https://openstrate.com/view/abc123.glb"
allow="autoplay; fullscreen"
allowfullscreen
></iframe>
</div>
<h2>Warehouse Scan (streamed)</h2>
<div class="viewer-container">
<iframe
src="https://stream.example.com/stream/def456.glb"
data-openstrate
allow="autoplay; fullscreen"
allowfullscreen
></iframe>
</div>
<script src="https://stream.example.com/embed-helper.js"></script>
</body>
</html>
06_CONFIGURATION
Streaming server environment variables:
| Variable | Default | Description |
|---|---|---|
| STREAM_PORT | 8090 | HTTP + WebSocket port |
| VIEW_ORIGIN | https://openstrate.com | Origin hosting /view/ pages |
| STREAM_WIDTH | 1920 | Render width (px) |
| STREAM_HEIGHT | 1080 | Render height (px) |
| STREAM_USE_GPU | 1 | 1 = GPU (ANGLE/Vulkan), 0 = CPU (SwiftShader) |
| STREAM_MAX_SESSIONS | 4 | Max concurrent streams |
| STREAM_POOL_SIZE | 2 | Pre-warmed Chrome instances |
| STREAM_IDLE_TIMEOUT | 30000 | Ms after last disconnect before cleanup |
Health check — GET
https://your-stream-server.com/health
{
"ok": true,
"sessions": 2,
"maxSessions": 4,
"poolSize": 1,
"poolTarget": 2,
"activeSessions": [
{ "file": "abc123.glb", "clients": 1, "alive": true }
]
}
07_VIEWER_CONTROLS
| Input | Action |
|---|---|
| Left-click drag | Orbit |
| Right-click drag | Pan |
| Scroll wheel | Zoom |
| Pinch (touch) | Zoom |
| One-finger drag (touch) | Orbit |
08_TROUBLESHOOTING
Iframe blank / white — Open the viewer URL directly; check HTTPS and console for mixed content or CORS.
Stream stuck on “Connecting…” — Confirm the server is up, /health returns ok, and WebRTC UDP isn’t blocked (corporate
firewalls; STUN stun.l.google.com:19302 reachable).
Low FPS — Prefer GPU (STREAM_USE_GPU=1), lower STREAM_WIDTH/HEIGHT, reduce concurrent sessions.
Grey model / no color — Vertex colors may be absent; depends on reconstruction and export settings.
09_NEXT_STEP
Need API access, private stream hosting, or SLA-backed embedding?
CONTACT SiL