QAT-Scaffold preset (Scaffold-GS PLY)

The splatforge-qat-scaffold preset is a post-training Quant-Aware codec for Scaffold-GS PLYs. It has two tiers with different inputs and different deliverables.

What the live single-PLY endpoint delivers

The default endpoint takes a single Scaffold-GS PLY (no GT cameras) and returns a smaller Scaffold-GS PLY using the lossless constant-strip prefix only. Measured on bonsai 30k:

Stripped fields are the eight Scaffold-GS columns the trainer initialises and never updates (nx, ny, nz, opacity, rot_0..rot_3). Bench data lives in benches/encoders/qat-scaffold-gs/.

Full QAT recipe — premium tier (requires GT cameras)

The bench numbers below come from the full QAT recipe: constant-strip plus int8 quant-aware retrain of f_anchor_feat plus int4 per-anchor quant of f_offset. The retrain pass needs the original training images + COLMAP cameras to evaluate against, so it ships as a separate QAT-Bundle preset (~$0.50/scene, ~10 min on A100). Pick QAT-Bundle (premium) in the Try-it preset picker and drop a Scaffold-GS bundle archive — see /docs/qat-bundle for the exact layout and the per-scene expectations table.

Tier-1 of QAT-Bundle ships the int8 f_anchor_feat finetune + lossless constant-strip; int4 offset stacking (the extra ~7 percentage points to hit the headline 37% aggregate) lands in a follow-up. Each job returns honest per-scene numbers in the callback, so the customer always sees the actual ΔPSNR their capture earned.

Bench numbers — full recipe, 6 scenes, 2026-05-16

Aggregate 37.25% PLY-size save across the six trained Mip-NeRF 360 scenes, with a positive PSNR delta on every scene (6/6). Per-scene breakdown:

Scene PLY save Delta PSNR (dB)
bonsai40.51%+0.581
bicycle40.51%+0.087
garden40.51%+0.198
stump33.80%+0.076
treehill33.80%+0.056
flowers33.80%+0.032
Aggregate (6 scenes) 37.25% +0.172 (mean)

Raw bench column lives at benches/encoders/qat-scaffold-gs/ and the per-scene cells are in benches/reports/splatbench-v0.json under qatScaffoldGs. SSIM and LPIPS improve on every scene too — see the leaderboard page for the full matrix.

Endpoint

POST https://api.splatforge.dev/v1/jobs
Authorization: Bearer <api_key>
Content-Type: application/json

{
  "preset": "splatforge-qat-scaffold",
  "blob_url": "https://blob.vercel-storage.com/uploads/<sha>-scaffold.ply",
  "filename": "scaffold.ply"
}

Auth

Every request needs Authorization: Bearer <api_key>. New accounts get a free-tier key via the existing self-serve flow at sales@splatforge.dev: Stripe Checkout submits the email, the webhook issues an API key, and the key shows up in both the receipt email and the account dashboard. No separate QAT-Scaffold signup; the same key gates every preset.

Request / response

Same job shape as every other preset — only preset changes. The API returns a job_id immediately and POSTs the terminal result to your registered callback (or you can poll GET /v1/jobs/<job_id>).

// 202 Accepted
{
  "job_id": "01HZ9X2P8E4QXM6R0M3T7G1K8C",
  "preset": "splatforge-qat-scaffold",
  "status": "queued",
  "estimated_compute_seconds": 360,
  "estimated_cost_usd_cents": 18
}

// terminal callback (or GET /v1/jobs/<id>)
{
  "job_id": "01HZ9X2P8E4QXM6R0M3T7G1K8C",
  "status": "done",
  "output_url": "https://blob.vercel-storage.com/outputs/<sha>-qat.ply",
  "size_bytes_in":  136847392,
  "size_bytes_out":  85946720,
  "ply_save_pct": 37.2,
  "delta_psnr_db": 0.17
}

Input shapes

Output shape

A single Scaffold-GS PLY, smaller than the input. The file is self-contained — any Scaffold-GS-aware decoder can render it because the quantized streams are stored in standard PLY-attribute slots with documented quant scales in the header comment.

Rate limits

TierPer-key request budgetPer-input size
Free 1 scene / 24 h <= 100 MB Scaffold PLY
Paid No daily cap No size cap (subject to Modal-side timeouts on enormous captures — talk to us if you have a >5 GB Scaffold)

Rate limits are enforced per-key by the existing splatforge_rate_limit middleware (PR #33). Free-tier overage returns HTTP 429 with an X-Free-Tier-Reset header pointing at the next midnight UTC window.

Pricing

Use POST /v1/pricing/preview with { "size_bytes": <n>, "preset": "splatforge-qat-scaffold" } to get a quote before submitting the job.

Worker dispatch

The public worker forwards every splatforge-qat-scaffold enqueue to a private Modal app. The operator sets SPLATFORGE_QAT_SCAFFOLD_URL in the splatforge-preset-urls Modal secret to wire the route; GET /healthz on the worker exposes a preset_dispatch_configured.splatforge-qat-scaffold bool so deploys are verifiable without inspecting secrets.

Anti-claims

See also

The on-disk format produced by this preset is documented in the QAT-PLY v1 specification, with a zero-dependency C99 reference decoder and a 10-fixture conformance suite so any third-party renderer can decode SplatForge PLYs bit-exactly without a runtime SplatForge dependency.