Jonna Marie Matthiesen commited on
Commit Β·
234ef1f
1
Parent(s): 4db51d5
Fix video loading time, prebuffer vids
Browse files- demo/demo.js +34 -49
demo/demo.js
CHANGED
|
@@ -208,21 +208,22 @@ async function renderDemo(data, container, optimizedOrg, dataFile, modelColors)
|
|
| 208 |
const videoWrap = document.createElement("div");
|
| 209 |
videoWrap.className = "demo-video-wrap";
|
| 210 |
|
| 211 |
-
|
|
|
|
|
|
|
| 212 |
const v = document.createElement("video");
|
| 213 |
v.loop = true;
|
| 214 |
v.muted = true;
|
| 215 |
v.playsInline = true;
|
| 216 |
v.preload = "auto";
|
| 217 |
v.className = "demo-video";
|
|
|
|
|
|
|
|
|
|
| 218 |
return v;
|
| 219 |
-
}
|
| 220 |
|
| 221 |
-
let
|
| 222 |
-
let videoB = makeVideoEl();
|
| 223 |
-
videoB.style.opacity = "0";
|
| 224 |
-
videoWrap.appendChild(videoA);
|
| 225 |
-
videoWrap.appendChild(videoB);
|
| 226 |
|
| 227 |
const arrowLeft = document.createElement("button");
|
| 228 |
arrowLeft.className = "demo-arrow demo-arrow-left";
|
|
@@ -238,8 +239,6 @@ async function renderDemo(data, container, optimizedOrg, dataFile, modelColors)
|
|
| 238 |
videoWrap.appendChild(arrowRight);
|
| 239 |
card.appendChild(videoWrap);
|
| 240 |
|
| 241 |
-
let isFirstClip = true;
|
| 242 |
-
|
| 243 |
// Device selector (centered under video)
|
| 244 |
card.appendChild(deviceSelector);
|
| 245 |
|
|
@@ -348,51 +347,36 @@ async function renderDemo(data, container, optimizedOrg, dataFile, modelColors)
|
|
| 348 |
clipSetup.textContent = clip.inference_setup || "";
|
| 349 |
clipSetup.style.display = clip.inference_setup ? "" : "none";
|
| 350 |
|
| 351 |
-
// Video β
|
| 352 |
-
|
|
|
|
| 353 |
videoWrap.style.display = "";
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
} else {
|
| 362 |
-
|
| 363 |
-
videoB.src = clip.video;
|
| 364 |
-
videoB.style.opacity = "0";
|
| 365 |
-
videoB.load();
|
| 366 |
-
|
| 367 |
-
videoB.addEventListener("loadeddata", function onLoaded() {
|
| 368 |
-
videoB.removeEventListener("loadeddata", onLoaded);
|
| 369 |
-
videoB.play();
|
| 370 |
-
|
| 371 |
-
// Wait for actual frame render before fading
|
| 372 |
-
const startFade = () => {
|
| 373 |
-
videoB.style.opacity = "1";
|
| 374 |
-
videoA.style.opacity = "0";
|
| 375 |
-
// After transition, pause old and swap roles
|
| 376 |
-
setTimeout(() => {
|
| 377 |
-
videoA.pause();
|
| 378 |
-
videoA.removeAttribute("src");
|
| 379 |
-
videoA.load();
|
| 380 |
-
// Swap roles
|
| 381 |
-
const tmp = videoA;
|
| 382 |
-
videoA = videoB;
|
| 383 |
-
videoB = tmp;
|
| 384 |
-
}, 300);
|
| 385 |
-
};
|
| 386 |
-
|
| 387 |
-
if (videoB.requestVideoFrameCallback) {
|
| 388 |
-
videoB.requestVideoFrameCallback(startFade);
|
| 389 |
-
} else {
|
| 390 |
-
startFade();
|
| 391 |
-
}
|
| 392 |
-
});
|
| 393 |
}
|
| 394 |
} else {
|
| 395 |
videoWrap.style.display = "none";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
}
|
| 397 |
|
| 398 |
// Prompt
|
|
@@ -422,6 +406,7 @@ async function renderDemo(data, container, optimizedOrg, dataFile, modelColors)
|
|
| 422 |
renderOutputs();
|
| 423 |
|
| 424 |
updateArrows();
|
|
|
|
| 425 |
}
|
| 426 |
|
| 427 |
// ββ Toggle open/close βββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 208 |
const videoWrap = document.createElement("div");
|
| 209 |
videoWrap.className = "demo-video-wrap";
|
| 210 |
|
| 211 |
+
// Pre-create and buffer a <video> element for every clip
|
| 212 |
+
const clipVideos = clips.map(clip => {
|
| 213 |
+
if (!clip.video) return null;
|
| 214 |
const v = document.createElement("video");
|
| 215 |
v.loop = true;
|
| 216 |
v.muted = true;
|
| 217 |
v.playsInline = true;
|
| 218 |
v.preload = "auto";
|
| 219 |
v.className = "demo-video";
|
| 220 |
+
v.style.opacity = "0";
|
| 221 |
+
v.src = clip.video;
|
| 222 |
+
videoWrap.appendChild(v);
|
| 223 |
return v;
|
| 224 |
+
});
|
| 225 |
|
| 226 |
+
let activeVideoIdx = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
|
| 228 |
const arrowLeft = document.createElement("button");
|
| 229 |
arrowLeft.className = "demo-arrow demo-arrow-left";
|
|
|
|
| 239 |
videoWrap.appendChild(arrowRight);
|
| 240 |
card.appendChild(videoWrap);
|
| 241 |
|
|
|
|
|
|
|
| 242 |
// Device selector (centered under video)
|
| 243 |
card.appendChild(deviceSelector);
|
| 244 |
|
|
|
|
| 347 |
clipSetup.textContent = clip.inference_setup || "";
|
| 348 |
clipSetup.style.display = clip.inference_setup ? "" : "none";
|
| 349 |
|
| 350 |
+
// Video β switch between pre-buffered video elements
|
| 351 |
+
const newVideo = clipVideos[currentClipIdx];
|
| 352 |
+
if (newVideo) {
|
| 353 |
videoWrap.style.display = "";
|
| 354 |
+
const oldVideo = activeVideoIdx >= 0 ? clipVideos[activeVideoIdx] : null;
|
| 355 |
+
|
| 356 |
+
const showNew = () => {
|
| 357 |
+
newVideo.style.opacity = "1";
|
| 358 |
+
newVideo.play();
|
| 359 |
+
if (oldVideo && oldVideo !== newVideo) {
|
| 360 |
+
oldVideo.style.opacity = "0";
|
| 361 |
+
oldVideo.pause();
|
| 362 |
+
oldVideo.currentTime = 0;
|
| 363 |
+
}
|
| 364 |
+
activeVideoIdx = currentClipIdx;
|
| 365 |
+
};
|
| 366 |
+
|
| 367 |
+
// If enough data is buffered, show immediately; otherwise wait
|
| 368 |
+
if (newVideo.readyState >= 3) {
|
| 369 |
+
showNew();
|
| 370 |
} else {
|
| 371 |
+
newVideo.addEventListener("canplay", showNew, { once: true });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
}
|
| 373 |
} else {
|
| 374 |
videoWrap.style.display = "none";
|
| 375 |
+
if (activeVideoIdx >= 0 && clipVideos[activeVideoIdx]) {
|
| 376 |
+
clipVideos[activeVideoIdx].style.opacity = "0";
|
| 377 |
+
clipVideos[activeVideoIdx].pause();
|
| 378 |
+
}
|
| 379 |
+
activeVideoIdx = -1;
|
| 380 |
}
|
| 381 |
|
| 382 |
// Prompt
|
|
|
|
| 406 |
renderOutputs();
|
| 407 |
|
| 408 |
updateArrows();
|
| 409 |
+
|
| 410 |
}
|
| 411 |
|
| 412 |
// ββ Toggle open/close βββββββββββββββββββββββββββββββββββββββββββββββ
|