mirror of
https://github.com/vibegif/vibegif.lol.git
synced 2026-04-07 02:12:12 +00:00
Fix: robust bg-removal test w/ logs
This commit is contained in:
115
test.html
115
test.html
@@ -11,7 +11,7 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
body, input, select, button, a, label {
|
body, input, select, button, a, label, code, pre {
|
||||||
font-family: "Stain", sans-serif;
|
font-family: "Stain", sans-serif;
|
||||||
}
|
}
|
||||||
.checker {
|
.checker {
|
||||||
@@ -27,18 +27,19 @@
|
|||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white text-neutral-800 min-h-screen">
|
<body class="bg-white text-neutral-800 min-h-screen">
|
||||||
<main class="max-w-5xl mx-auto px-4 py-8 flex flex-col gap-6">
|
<main class="max-w-6xl mx-auto px-4 py-8 flex flex-col gap-6">
|
||||||
<header class="flex items-center justify-between">
|
<header class="flex items-center justify-between">
|
||||||
<h1 class="text-4xl tracking-tight">bg test<span class="text-neutral-400">.lol</span></h1>
|
<h1 class="text-4xl tracking-tight">bg test<span class="text-neutral-400">.lol</span></h1>
|
||||||
<a href="/" class="text-sm underline text-neutral-500 hover:text-neutral-800">back to vibegif</a>
|
<a href="/" class="text-sm underline text-neutral-500 hover:text-neutral-800">back to vibegif</a>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<p class="text-neutral-500">
|
<p class="text-neutral-500">
|
||||||
Upload image(s), run <code>@imgly/background-removal</code>, compare results. First run may take longer (model download).
|
Upload image(s), run <code>@imgly/background-removal</code>, inspect output + logs.
|
||||||
|
First run can take longer due model download.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<section class="grid md:grid-cols-4 gap-4">
|
<section class="grid md:grid-cols-5 gap-4">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2 md:col-span-2">
|
||||||
<label class="text-xs text-neutral-400 uppercase tracking-wider">Files</label>
|
<label class="text-xs text-neutral-400 uppercase tracking-wider">Files</label>
|
||||||
<input id="inp-files" type="file" accept="image/*" multiple class="border border-neutral-300 rounded-lg px-3 py-2" />
|
<input id="inp-files" type="file" accept="image/*" multiple class="border border-neutral-300 rounded-lg px-3 py-2" />
|
||||||
</div>
|
</div>
|
||||||
@@ -73,12 +74,18 @@
|
|||||||
<p id="status" class="text-sm text-neutral-500"></p>
|
<p id="status" class="text-sm text-neutral-500"></p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="border border-neutral-200 rounded-xl p-3">
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<p class="text-xs text-neutral-400 uppercase tracking-wider">debug log</p>
|
||||||
|
<button id="btn-clear-log" class="text-xs underline text-neutral-500 hover:text-neutral-800">clear log</button>
|
||||||
|
</div>
|
||||||
|
<pre id="log" class="text-xs whitespace-pre-wrap break-words max-h-56 overflow-auto bg-neutral-50 rounded-lg p-3"></pre>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="results" class="grid md:grid-cols-2 gap-4"></section>
|
<section id="results" class="grid md:grid-cols-2 gap-4"></section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import removeBackground from "https://esm.sh/@imgly/background-removal@1.7.0";
|
|
||||||
|
|
||||||
const el = {
|
const el = {
|
||||||
files: document.getElementById("inp-files"),
|
files: document.getElementById("inp-files"),
|
||||||
type: document.getElementById("sel-type"),
|
type: document.getElementById("sel-type"),
|
||||||
@@ -86,14 +93,36 @@
|
|||||||
quality: document.getElementById("inp-quality"),
|
quality: document.getElementById("inp-quality"),
|
||||||
run: document.getElementById("btn-run"),
|
run: document.getElementById("btn-run"),
|
||||||
clear: document.getElementById("btn-clear"),
|
clear: document.getElementById("btn-clear"),
|
||||||
|
clearLog: document.getElementById("btn-clear-log"),
|
||||||
status: document.getElementById("status"),
|
status: document.getElementById("status"),
|
||||||
|
log: document.getElementById("log"),
|
||||||
results: document.getElementById("results")
|
results: document.getElementById("results")
|
||||||
};
|
};
|
||||||
|
|
||||||
const objectUrls = new Set();
|
const objectUrls = new Set();
|
||||||
|
let removeBackgroundFn = null;
|
||||||
|
let loadingLibPromise = null;
|
||||||
|
|
||||||
|
const now = () => new Date().toLocaleTimeString();
|
||||||
|
|
||||||
|
const appendLog = (...args) => {
|
||||||
|
const line = `[${now()}] ${args.map((v) => {
|
||||||
|
if (v instanceof Error) return `${v.name}: ${v.message}`;
|
||||||
|
if (typeof v === "object") {
|
||||||
|
try { return JSON.stringify(v); } catch { return String(v); }
|
||||||
|
}
|
||||||
|
return String(v);
|
||||||
|
}).join(" ")}`;
|
||||||
|
console.log("[bg-test]", ...args);
|
||||||
|
if (el.log) {
|
||||||
|
el.log.textContent += (el.log.textContent ? "\n" : "") + line;
|
||||||
|
el.log.scrollTop = el.log.scrollHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const setStatus = (msg) => {
|
const setStatus = (msg) => {
|
||||||
el.status.textContent = msg || "";
|
el.status.textContent = msg || "";
|
||||||
|
appendLog("STATUS:", msg || "");
|
||||||
};
|
};
|
||||||
|
|
||||||
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
||||||
@@ -164,12 +193,14 @@
|
|||||||
const revokeAllUrls = () => {
|
const revokeAllUrls = () => {
|
||||||
for (const url of objectUrls) URL.revokeObjectURL(url);
|
for (const url of objectUrls) URL.revokeObjectURL(url);
|
||||||
objectUrls.clear();
|
objectUrls.clear();
|
||||||
|
appendLog("revoked object urls");
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearResults = () => {
|
const clearResults = () => {
|
||||||
revokeAllUrls();
|
revokeAllUrls();
|
||||||
el.results.innerHTML = "";
|
el.results.innerHTML = "";
|
||||||
setStatus("");
|
el.status.textContent = "";
|
||||||
|
appendLog("cleared results");
|
||||||
};
|
};
|
||||||
|
|
||||||
const setBusy = (busy) => {
|
const setBusy = (busy) => {
|
||||||
@@ -178,10 +209,62 @@
|
|||||||
el.run.style.cursor = busy ? "not-allowed" : "pointer";
|
el.run.style.cursor = busy ? "not-allowed" : "pointer";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function loadLib() {
|
||||||
|
if (removeBackgroundFn) return removeBackgroundFn;
|
||||||
|
if (loadingLibPromise) return loadingLibPromise;
|
||||||
|
|
||||||
|
const urls = [
|
||||||
|
"https://esm.sh/@imgly/background-removal@1.7.0?bundle",
|
||||||
|
"https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/+esm"
|
||||||
|
];
|
||||||
|
|
||||||
|
loadingLibPromise = (async () => {
|
||||||
|
let lastErr = null;
|
||||||
|
|
||||||
|
for (const url of urls) {
|
||||||
|
try {
|
||||||
|
appendLog("trying import:", url);
|
||||||
|
const mod = await import(url);
|
||||||
|
const fn = mod?.default || mod?.removeBackground || mod?.imglyRemoveBackground;
|
||||||
|
if (typeof fn !== "function") {
|
||||||
|
throw new Error(`No usable remove function export. keys=${Object.keys(mod || {}).join(",")}`);
|
||||||
|
}
|
||||||
|
removeBackgroundFn = fn;
|
||||||
|
appendLog("library loaded from:", url);
|
||||||
|
return removeBackgroundFn;
|
||||||
|
} catch (err) {
|
||||||
|
lastErr = err;
|
||||||
|
appendLog("import failed:", url, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw lastErr || new Error("Failed to load @imgly/background-removal from all CDNs.");
|
||||||
|
})();
|
||||||
|
|
||||||
|
return loadingLibPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatErr(err) {
|
||||||
|
if (!err) return "Unknown error";
|
||||||
|
if (err instanceof Error) return `${err.name}: ${err.message}`;
|
||||||
|
try { return JSON.stringify(err); } catch { return String(err); }
|
||||||
|
}
|
||||||
|
|
||||||
el.clear.addEventListener("click", clearResults);
|
el.clear.addEventListener("click", clearResults);
|
||||||
|
el.clearLog.addEventListener("click", () => { el.log.textContent = ""; });
|
||||||
|
|
||||||
|
window.addEventListener("error", (e) => {
|
||||||
|
appendLog("window.error:", e.message || e.error || e);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("unhandledrejection", (e) => {
|
||||||
|
appendLog("unhandledrejection:", formatErr(e.reason));
|
||||||
|
});
|
||||||
|
|
||||||
el.run.addEventListener("click", async () => {
|
el.run.addEventListener("click", async () => {
|
||||||
const files = [...(el.files.files || [])];
|
const files = [...(el.files.files || [])];
|
||||||
|
appendLog("run clicked. files:", files.map(f => `${f.name} (${f.size} bytes)`));
|
||||||
|
|
||||||
if (!files.length) {
|
if (!files.length) {
|
||||||
setStatus("pick at least one image first.");
|
setStatus("pick at least one image first.");
|
||||||
el.files.focus();
|
el.files.focus();
|
||||||
@@ -192,15 +275,20 @@
|
|||||||
setBusy(true);
|
setBusy(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
setStatus("loading @imgly/background-removal...");
|
||||||
|
const removeBackground = await loadLib();
|
||||||
|
|
||||||
const outputType = el.type.value;
|
const outputType = el.type.value;
|
||||||
const outputFormat = el.format.value;
|
const outputFormat = el.format.value;
|
||||||
const quality = clamp(Number.parseFloat(el.quality.value || "0.9") || 0.9, 0, 1);
|
const quality = clamp(Number.parseFloat(el.quality.value || "0.9") || 0.9, 0, 1);
|
||||||
|
appendLog("config:", { outputType, outputFormat, quality });
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const file = files[i];
|
const file = files[i];
|
||||||
setStatus(`processing ${i + 1}/${files.length}: ${file.name} ...`);
|
setStatus(`processing ${i + 1}/${files.length}: ${file.name} ...`);
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
|
debug: true,
|
||||||
output: {
|
output: {
|
||||||
type: outputType,
|
type: outputType,
|
||||||
format: outputFormat,
|
format: outputFormat,
|
||||||
@@ -209,11 +297,15 @@
|
|||||||
progress: (key, current, total) => {
|
progress: (key, current, total) => {
|
||||||
if (!total) return;
|
if (!total) return;
|
||||||
const pct = Math.round((current / total) * 100);
|
const pct = Math.round((current / total) * 100);
|
||||||
setStatus(`downloading model assets (${key}) ${pct}% — file ${i + 1}/${files.length}`);
|
el.status.textContent = `downloading model assets (${key}) ${pct}% — file ${i + 1}/${files.length}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
appendLog("calling removeBackground for:", file.name);
|
||||||
|
const started = performance.now();
|
||||||
const outBlob = await removeBackground(file, config);
|
const outBlob = await removeBackground(file, config);
|
||||||
|
const ms = Math.round(performance.now() - started);
|
||||||
|
appendLog("done:", file.name, `in ${ms}ms`, `blob=${outBlob.type} ${outBlob.size} bytes`);
|
||||||
|
|
||||||
const originalUrl = URL.createObjectURL(file);
|
const originalUrl = URL.createObjectURL(file);
|
||||||
const outputUrl = URL.createObjectURL(outBlob);
|
const outputUrl = URL.createObjectURL(outBlob);
|
||||||
@@ -232,14 +324,17 @@
|
|||||||
|
|
||||||
setStatus(`done ✓ processed ${files.length} image${files.length > 1 ? "s" : ""}.`);
|
setStatus(`done ✓ processed ${files.length} image${files.length > 1 ? "s" : ""}.`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
const msg = formatErr(err);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
setStatus(`error: ${err?.message || String(err)}`);
|
setStatus(`error: ${msg}`);
|
||||||
|
appendLog("FATAL:", msg, err?.stack || "");
|
||||||
} finally {
|
} finally {
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("beforeunload", revokeAllUrls);
|
window.addEventListener("beforeunload", revokeAllUrls);
|
||||||
|
appendLog("test page booted");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user