Spaces:
Running
Running
ego viewer: guard/throttle slave-video sync (fixes head_fisheye_left seek-storm on cold load)
Browse files- egoSample/mego.html +26 -4
egoSample/mego.html
CHANGED
|
@@ -168,7 +168,11 @@ function loadSig(slug){
|
|
| 168 |
const done=()=>{ SIG=window.EPDATA[slug]; if(!SIG) return; sizeCanvases(); drawCharts();
|
| 169 |
let fv=0; for(let k=0;k<SIG.n;k++){ if(SIG.handL.valid[k]>0.5&&SIG.handR.valid[k]>0.5){ fv=k/SIG.fps; break; } }
|
| 170 |
if(master && master.currentTime<0.05 && fv>0) setTime(fv); else if(master){ updateUI(master.currentTime||0); blitMain(); }
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
if(window.EPDATA[slug]){ done(); return; }
|
| 173 |
const s=document.createElement('script'); s.id='sigjs'; s.src='epdata/'+slug+'.js';
|
| 174 |
s.onload=done; s.onerror=()=>{ SIG=null; };
|
|
@@ -349,18 +353,36 @@ function wire(){
|
|
| 349 |
setTime(0);
|
| 350 |
}
|
| 351 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
function setTime(t){
|
| 353 |
const dur=EP.duration; t=Math.max(0,Math.min(dur-0.01,t));
|
| 354 |
-
|
|
|
|
| 355 |
updateUI(t); blitMain(t);
|
| 356 |
}
|
| 357 |
function tick(){
|
| 358 |
if(!playing) return;
|
| 359 |
const t=master.currentTime, dur=EP.duration;
|
| 360 |
-
|
| 361 |
updateUI(t);
|
| 362 |
blitMain(t);
|
| 363 |
-
if(t>=dur-0.05){
|
| 364 |
raf=requestAnimationFrame(tick);
|
| 365 |
}
|
| 366 |
/* draw the main (head_fisheye) frame + projected hand skeleton into one canvas */
|
|
|
|
| 168 |
const done=()=>{ SIG=window.EPDATA[slug]; if(!SIG) return; sizeCanvases(); drawCharts();
|
| 169 |
let fv=0; for(let k=0;k<SIG.n;k++){ if(SIG.handL.valid[k]>0.5&&SIG.handR.valid[k]>0.5){ fv=k/SIG.fps; break; } }
|
| 170 |
if(master && master.currentTime<0.05 && fv>0) setTime(fv); else if(master){ updateUI(master.currentTime||0); blitMain(); }
|
| 171 |
+
// start playback only once the master tile can actually play, so the per-frame
|
| 172 |
+
// slave sync chases a real timestamp instead of hammering seeks against t=0
|
| 173 |
+
const go=()=>{ if(_toggle && !playing) _toggle(); };
|
| 174 |
+
if(!master) {} else if(master.readyState>=3) go();
|
| 175 |
+
else master.addEventListener('canplay', go, {once:true}); };
|
| 176 |
if(window.EPDATA[slug]){ done(); return; }
|
| 177 |
const s=document.createElement('script'); s.id='sigjs'; s.src='epdata/'+slug+'.js';
|
| 178 |
s.onload=done; s.onerror=()=>{ SIG=null; };
|
|
|
|
| 353 |
setTime(0);
|
| 354 |
}
|
| 355 |
|
| 356 |
+
// --- slave-video sync (k>0). Guarded + throttled so a still-buffering panel
|
| 357 |
+
// (e.g. head_fisheye_left on a cold load) doesn't get a `currentTime=` write on
|
| 358 |
+
// every rAF while its previous seek is still in flight — that restarts the seek
|
| 359 |
+
// endlessly and the panel just replays its first few hundred ms.
|
| 360 |
+
let _lastSync=0;
|
| 361 |
+
function seekSlave(v,t){
|
| 362 |
+
if(v.seeking) return; // a seek is already pending — never stack another
|
| 363 |
+
if(v.readyState<1) return; // no metadata yet, nothing to seek to
|
| 364 |
+
try{ if(v.fastSeek) v.fastSeek(t); else v.currentTime=t; }catch(e){}
|
| 365 |
+
}
|
| 366 |
+
function syncSlaves(t,force){
|
| 367 |
+
const now=performance.now();
|
| 368 |
+
if(!force && now-_lastSync<180) return; // ~5 Hz correction, not 60 Hz
|
| 369 |
+
_lastSync=now;
|
| 370 |
+
for(let k=1;k<vids.length;k++){ const v=vids[k];
|
| 371 |
+
if(Math.abs(v.currentTime-t)>0.18) seekSlave(v,t); }
|
| 372 |
+
}
|
| 373 |
function setTime(t){
|
| 374 |
const dur=EP.duration; t=Math.max(0,Math.min(dur-0.01,t));
|
| 375 |
+
try{ if(Math.abs(master.currentTime-t)>0.05) master.currentTime=t; }catch(e){}
|
| 376 |
+
syncSlaves(t,true);
|
| 377 |
updateUI(t); blitMain(t);
|
| 378 |
}
|
| 379 |
function tick(){
|
| 380 |
if(!playing) return;
|
| 381 |
const t=master.currentTime, dur=EP.duration;
|
| 382 |
+
syncSlaves(t,false);
|
| 383 |
updateUI(t);
|
| 384 |
blitMain(t);
|
| 385 |
+
if(t>=dur-0.05){ try{master.currentTime=0;}catch(e){} syncSlaves(0,true); updateUI(0); }
|
| 386 |
raf=requestAnimationFrame(tick);
|
| 387 |
}
|
| 388 |
/* draw the main (head_fisheye) frame + projected hand skeleton into one canvas */
|