fix(rsplat): resize images with sharp before fal.ai submission

Phone photos (3-4MB, 4000px+) were failing with "Invalid image" on
fal.ai Hunyuan3D. Now resizes to max 1024px JPEG with sharp before
submitting, and uses PUBLIC_ORIGIN HTTPS URL instead of data URI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-16 20:36:59 -07:00
parent 05b8e2676a
commit d999c98b98
1 changed files with 14 additions and 8 deletions

View File

@ -7,6 +7,7 @@
*/
import { resolve } from "node:path";
import sharp from "sharp";
import { Hono } from "hono";
import { cors } from "hono/cors";
import type { ServerWebSocket } from "bun";
@ -738,22 +739,27 @@ async function process3DGenJob(job: Gen3DJob) {
const MODEL = "fal-ai/hunyuan3d-v21";
try {
// 1. Read staged image from disk and convert to data URI for reliable fal.ai delivery
// 1. Resize staged image with sharp (max 1024px) for reliable fal.ai processing
let imageInput = job.imageUrl;
const stagedMatch = job.imageUrl.match(/\/(?:api\/files|data\/files)\/generated\/([^?#]+)/);
if (stagedMatch) {
try {
const dir = resolve(process.env.FILES_DIR || "./data/files", "generated");
const file = Bun.file(resolve(dir, stagedMatch[1]));
const srcPath = resolve(dir, stagedMatch[1]);
const file = Bun.file(srcPath);
if (await file.exists()) {
const buf = Buffer.from(await file.arrayBuffer());
const ext = stagedMatch[1].split(".").pop()?.toLowerCase() || "jpg";
const mime = ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : "image/jpeg";
imageInput = `data:${mime};base64,${buf.toString("base64")}`;
console.log(`[3d-gen] Using data URI (${Math.round(buf.length / 1024)}KB) instead of URL`);
const resizedBuf = await sharp(srcPath)
.resize(1024, 1024, { fit: "inside", withoutEnlargement: true })
.jpeg({ quality: 90 })
.toBuffer();
const resizedName = `stage-resized-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.jpg`;
await Bun.write(resolve(dir, resizedName), resizedBuf);
// Use public HTTPS URL for the resized image
imageInput = `${PUBLIC_ORIGIN}/api/files/generated/${resizedName}`;
console.log(`[3d-gen] Resized image: ${Math.round(resizedBuf.length / 1024)}KB → ${imageInput}`);
}
} catch (e: any) {
console.warn(`[3d-gen] Data URI fallback failed, using URL:`, e.message);
console.warn(`[3d-gen] Resize failed, using original URL:`, e.message);
}
}