Spaces:
Running
Running
Download app.js from ankanmbz/worldguide-comparison: direct link, hf CLI and curl.
- Browser
- Download file 12.4 kB
-
https://huggingface.co/spaces/ankanmbz/worldguide-comparison/resolve/main/app.js
- Command line
-
hf download hf://spaces/ankanmbz/worldguide-comparison/app.js
-
curl -L -o app.js https://huggingface.co/spaces/ankanmbz/worldguide-comparison/resolve/main/app.js
12.4 kB
| ; | |
| (() => { | |
| const DATASET = "ankanmbz/worldguide-results"; | |
| const REMOTE_BASE = `https://huggingface.co/datasets/${DATASET}/resolve/main/`; | |
| const MODEL_ORDER = ["Our", "Cosmos2.5", "HunyuanVideo-1.5", "MiniMax-H3", "SkyReels", "LTX-2.5", "Barnini", "TempAct", "PhysAgent"]; | |
| const params = new URLSearchParams(location.search); | |
| const local = ["localhost", "127.0.0.1", "[::1]"].includes(location.hostname) && params.get("local") === "1"; | |
| const $ = (id) => document.getElementById(id); | |
| let manifest, selectedId, category = "All", query = "", requestVersion = 0, toastTimer; | |
| let videos = []; | |
| function element(tag, className, text) { | |
| const node = document.createElement(tag); | |
| if (className) node.className = className; | |
| if (text !== undefined) node.textContent = text; | |
| return node; | |
| } | |
| function assetURL(path, poster = false) { | |
| const encoded = path.split("/").map(encodeURIComponent).join("/"); | |
| return local ? new URL((poster ? "./" : "../") + encoded, location.href).href : REMOTE_BASE + encoded; | |
| } | |
| function announce(message) { $("playback-status").textContent = message; } | |
| function toast(message) { | |
| clearTimeout(toastTimer); | |
| $("toast").textContent = message; | |
| $("toast").hidden = false; | |
| toastTimer = setTimeout(() => { $("toast").hidden = true; }, 3500); | |
| } | |
| function pauseAll() { | |
| requestVersion++; | |
| videos.forEach(video => video.pause()); | |
| announce("All videos paused."); | |
| } | |
| function filteredSamples() { | |
| return manifest.samples.filter(sample => | |
| (category === "All" || sample.category === category) && | |
| `${sample.title} ${sample.category}`.toLowerCase().includes(query) | |
| ); | |
| } | |
| function renderList() { | |
| const samples = filteredSamples(); | |
| const fragment = document.createDocumentFragment(); | |
| for (const sample of samples) { | |
| const button = element("button", "sample-button"); | |
| button.type = "button"; | |
| button.dataset.sampleId = sample.id; | |
| button.setAttribute("aria-pressed", String(sample.id === selectedId)); | |
| button.setAttribute("aria-controls", "comparison"); | |
| const preview = sample.videos.Our || Object.values(sample.videos)[0]; | |
| const image = element("img", "sample-thumbnail"); | |
| image.src = assetURL(preview.poster, true); | |
| image.alt = ""; | |
| image.loading = "lazy"; | |
| image.width = 58; | |
| image.height = 42; | |
| const text = element("span", "sample-text"); | |
| text.append(element("span", "sample-name", sample.title), element("span", "sample-subtitle", sample.category)); | |
| button.append(image, text); | |
| if (sample.id === selectedId) button.append(element("span", "sample-current-dot")); | |
| button.addEventListener("click", () => { | |
| selectSample(sample.id); | |
| if (matchMedia("(max-width: 800px)").matches) { | |
| $("sample-browser").open = false; | |
| $("comparison").focus({ preventScroll: true }); | |
| $("comparison").scrollIntoView({ behavior: "instant", block: "start" }); | |
| } | |
| }); | |
| fragment.append(button); | |
| } | |
| $("sample-list").replaceChildren(fragment); | |
| $("sample-count").textContent = String(samples.length); | |
| $("browse-hint").hidden = samples.length <= 5; | |
| $("browse-hint").textContent = `Scroll to browse all ${samples.length} samples ↓`; | |
| $("empty-results").hidden = samples.length > 0; | |
| } | |
| function renderCategories() { | |
| const fragment = document.createDocumentFragment(); | |
| for (const name of ["All", ...new Set(manifest.samples.map(sample => sample.category))]) { | |
| const button = element("button", "category-button", name); | |
| button.type = "button"; | |
| button.setAttribute("aria-pressed", String(name === category)); | |
| button.addEventListener("click", () => { | |
| category = name; | |
| for (const peer of $("categories").children) peer.setAttribute("aria-pressed", String(peer === button)); | |
| renderList(); | |
| }); | |
| fragment.append(button); | |
| } | |
| $("categories").replaceChildren(fragment); | |
| } | |
| function makeCard(model, sample) { | |
| const metadata = sample.videos[model.id]; | |
| const label = model.id === "Our" ? "WorldGuide" : model.id === "Barnini" ? "Bernini*" : model.label; | |
| const card = element("article", `video-card${model.ours ? " ours" : ""}`); | |
| card.dataset.model = model.id; | |
| const heading = element("div", "card-heading"); | |
| const title = element("h3", "", label); | |
| title.id = `model-${model.id}`; | |
| heading.append(title, element("span", "model-dot")); | |
| const frame = element("div", "video-frame"); | |
| const video = element("video"); | |
| video.controls = true; | |
| video.muted = true; | |
| video.defaultMuted = true; | |
| video.playsInline = true; | |
| video.preload = "none"; | |
| video.poster = assetURL(metadata.poster, true); | |
| video.src = assetURL(metadata.path); | |
| video.setAttribute("aria-label", `${label}: ${sample.title}`); | |
| video.playbackRate = Number($("playback-speed").value); | |
| frame.append(video); | |
| const footer = element("div", "card-footer"); | |
| const specs = element("span", "video-specs mono"); | |
| specs.append(element("span", "", `${metadata.duration.toFixed(1)}s`), element("span", "", `${metadata.width} × ${metadata.height}`)); | |
| const open = element("a", "", "Open video ↗"); | |
| open.href = video.src; | |
| open.target = "_blank"; | |
| open.rel = "noopener noreferrer"; | |
| open.setAttribute("aria-label", `Open ${label} video`); | |
| footer.append(specs, open); | |
| const error = element("div", "video-error"); | |
| error.hidden = true; | |
| error.setAttribute("role", "status"); | |
| error.append(element("span", "", "Video couldn’t load.")); | |
| const retry = element("button", "text-button", "Retry"); | |
| retry.type = "button"; | |
| retry.addEventListener("click", () => { | |
| error.hidden = true; | |
| video.load(); | |
| video.play().catch(() => { if (video.isConnected) error.hidden = false; }); | |
| }); | |
| error.append(retry); | |
| video.addEventListener("error", () => { error.hidden = false; }); | |
| video.addEventListener("playing", () => { error.hidden = true; }); | |
| card.append(heading, frame, footer, error, | |
| window.WorldGuideRatings.createPanel({ sampleId: sample.id, modelId: model.id, label })); | |
| videos.push(video); | |
| return card; | |
| } | |
| function selectSample(id, updateURL = true) { | |
| const sample = manifest.samples.find(item => item.id === id) || manifest.samples[0]; | |
| pauseAll(); | |
| // Release previous requests when moving between samples. | |
| videos.forEach(video => { video.removeAttribute("src"); video.load(); }); | |
| videos = []; | |
| selectedId = sample.id; | |
| $("sample-title").textContent = sample.title; | |
| $("sample-category").textContent = sample.category; | |
| $("sample-position").textContent = `${manifest.samples.indexOf(sample) + 1} / ${manifest.samples.length}`; | |
| document.title = `${sample.title} — WorldGuide`; | |
| const models = MODEL_ORDER.map(id => manifest.models.find(model => model.id === id)); | |
| $("video-grid").replaceChildren(...models.map(model => makeCard(model, sample))); | |
| renderList(); | |
| announce(`${sample.title}. ${models.length} model videos ready to play.`); | |
| if (updateURL) { | |
| const url = new URL(location.href); | |
| url.searchParams.set("sample", sample.id); | |
| history.replaceState(null, "", url); | |
| } | |
| } | |
| async function playAll() { | |
| const version = ++requestVersion; | |
| announce("Loading and playing all videos."); | |
| const results = await Promise.allSettled(videos.map(video => { | |
| if (video.ended) video.currentTime = 0; | |
| return video.play(); | |
| })); | |
| if (version !== requestVersion) return; | |
| const failed = results.filter(result => result.status === "rejected").length; | |
| if (failed) toast("Some videos couldn’t start. Try their individual play controls."); | |
| announce(failed ? "Some videos could not start." : "All videos playing."); | |
| } | |
| function moveSample(delta) { | |
| const index = manifest.samples.findIndex(sample => sample.id === selectedId); | |
| selectSample(manifest.samples[(index + delta + manifest.samples.length) % manifest.samples.length].id); | |
| $("sample-list").querySelector('[aria-pressed="true"]')?.scrollIntoView({ block: "nearest" }); | |
| } | |
| async function copyLink() { | |
| const url = new URL(location.href); | |
| url.searchParams.delete("local"); | |
| url.searchParams.set("sample", selectedId); | |
| // A Space can be framed, but its direct URL is still a valid share link. | |
| try { | |
| await navigator.clipboard.writeText(url.href); | |
| toast("Comparison link copied."); | |
| } catch { | |
| window.prompt("Copy this comparison link:", url.href); | |
| } | |
| } | |
| function validate(data) { | |
| if (data.schemaVersion !== 1 || data.dataset !== DATASET || !Array.isArray(data.samples) || !data.samples.length || !Array.isArray(data.models) || data.models.length !== MODEL_ORDER.length) throw new Error("Invalid collection manifest"); | |
| const ids = new Set(); | |
| const modelIds = new Set(data.models.map(model => model.id)); | |
| if (modelIds.size !== MODEL_ORDER.length || !MODEL_ORDER.every(id => modelIds.has(id))) throw new Error("Invalid model list"); | |
| for (const sample of data.samples) { | |
| if (typeof sample.id !== "string" || ids.has(sample.id) || typeof sample.title !== "string" || typeof sample.category !== "string") throw new Error("Invalid sample"); | |
| ids.add(sample.id); | |
| for (const model of data.models) { | |
| const video = sample.videos?.[model.id]; | |
| if (!video || !Number.isFinite(video.duration) || video.duration <= 0 || !Number.isFinite(video.width) || !Number.isFinite(video.height)) throw new Error("Missing video metadata"); | |
| for (const path of [video.path, video.poster]) { | |
| if (typeof path !== "string" || path.startsWith("/") || path.split("/").includes("..") || path.includes(":")) throw new Error("Invalid asset path"); | |
| } | |
| } | |
| } | |
| return data; | |
| } | |
| async function fetchManifest(url) { | |
| const response = await fetch(url, { signal: AbortSignal.timeout(12000) }); | |
| if (!response.ok) throw new Error(`Manifest request failed: ${response.status}`); | |
| return validate(await response.json()); | |
| } | |
| async function init() { | |
| try { | |
| if (local) manifest = await fetchManifest("./manifest.json"); | |
| else { | |
| try { manifest = await fetchManifest(REMOTE_BASE + "manifest.json"); } | |
| catch { manifest = await fetchManifest("./manifest.json"); } | |
| } | |
| $("sample-total").textContent = String(manifest.samples.length); | |
| $("model-total").textContent = String(manifest.models.length); | |
| $("video-total").textContent = String(manifest.samples.length * manifest.models.length); | |
| renderCategories(); | |
| selectSample(params.get("sample"), false); | |
| $("comparison").setAttribute("aria-busy", "false"); | |
| for (const id of ["previous", "next", "play-all", "pause-all", "restart", "copy-link"]) $(id).disabled = false; | |
| } catch (error) { | |
| console.error("WorldGuide collection failed to load:", error.message); | |
| $("comparison-content").hidden = true; | |
| $("load-error").hidden = false; | |
| $("comparison").setAttribute("aria-busy", "false"); | |
| } | |
| } | |
| $("sample-browser").open = !matchMedia("(max-width: 800px)").matches; | |
| $("sample-search").addEventListener("input", event => { query = event.target.value.trim().toLowerCase(); if (manifest) renderList(); }); | |
| $("clear-filters").addEventListener("click", () => { category = "All"; query = ""; $("sample-search").value = ""; renderCategories(); renderList(); $("sample-search").focus(); }); | |
| $("previous").addEventListener("click", () => moveSample(-1)); | |
| $("next").addEventListener("click", () => moveSample(1)); | |
| $("play-all").addEventListener("click", playAll); | |
| $("pause-all").addEventListener("click", pauseAll); | |
| $("restart").addEventListener("click", () => { pauseAll(); videos.forEach(video => { video.currentTime = 0; }); announce("All videos reset to the beginning."); }); | |
| $("playback-speed").addEventListener("change", event => { videos.forEach(video => { video.playbackRate = Number(event.target.value); }); }); | |
| $("copy-link").addEventListener("click", copyLink); | |
| $("reload").addEventListener("click", () => location.reload()); | |
| window.addEventListener("popstate", () => { if (manifest) selectSample(new URLSearchParams(location.search).get("sample"), false); }); | |
| window.addEventListener("pagehide", pauseAll); | |
| init(); | |
| })(); | |