fix(rsplat): resize images client-side before 3D generation, pass through fal.ai errors
Mobile photos (12MP+) were causing generation failures due to large base64 payloads. Now resizes to max 1024px before sending. Server now returns actual fal.ai error messages instead of generic "3D generation failed". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e5b5c551b1
commit
c5f757d050
|
|
@ -521,15 +521,13 @@ export class FolkSplatViewer extends HTMLElement {
|
|||
submitBtn.disabled = true;
|
||||
actions.style.display = "none";
|
||||
progress.style.display = "block";
|
||||
status.textContent = "";
|
||||
status.textContent = "Preparing image...";
|
||||
|
||||
try {
|
||||
const reader = new FileReader();
|
||||
const dataUrl = await new Promise<string>((resolve) => {
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.readAsDataURL(selectedFile!);
|
||||
});
|
||||
// Resize image to max 1024px to reduce payload and improve API success
|
||||
const dataUrl = await this.resizeImage(selectedFile!, 1024);
|
||||
|
||||
status.textContent = "Generating 3D model...";
|
||||
const res = await fetch("/api/3d-gen", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
|
@ -572,6 +570,30 @@ export class FolkSplatViewer extends HTMLElement {
|
|||
});
|
||||
}
|
||||
|
||||
// ── Image helpers ──
|
||||
|
||||
private resizeImage(file: File, maxSize: number): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
let { width, height } = img;
|
||||
if (width > maxSize || height > maxSize) {
|
||||
const scale = maxSize / Math.max(width, height);
|
||||
width = Math.round(width * scale);
|
||||
height = Math.round(height * scale);
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
resolve(canvas.toDataURL("image/jpeg", 0.9));
|
||||
};
|
||||
img.onerror = () => reject(new Error("Failed to load image"));
|
||||
img.src = URL.createObjectURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
// ── Viewer ──
|
||||
|
||||
private renderViewer() {
|
||||
|
|
|
|||
|
|
@ -998,9 +998,18 @@ app.post("/api/3d-gen", async (c) => {
|
|||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
console.error("[3d-gen] fal.ai error:", err);
|
||||
return c.json({ error: "3D generation failed" }, 502);
|
||||
const errText = await res.text();
|
||||
console.error("[3d-gen] fal.ai error:", res.status, errText);
|
||||
let detail = "3D generation failed";
|
||||
try {
|
||||
const parsed = JSON.parse(errText);
|
||||
if (parsed.detail) {
|
||||
detail = typeof parsed.detail === "string" ? parsed.detail
|
||||
: Array.isArray(parsed.detail) ? parsed.detail[0]?.msg || detail
|
||||
: detail;
|
||||
}
|
||||
} catch {}
|
||||
return c.json({ error: detail }, 502);
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
|
|
|
|||
Loading…
Reference in New Issue