Spaces:
Running
Running
Auto-start synced playback once videos are ready (muted autoplay, falls back to paused if blocked)
Browse files- egoSample/demo02/viewer.html +27 -0
- egoSample/demo05/viewer.html +27 -0
- egoSample/demo07/viewer.html +27 -0
- egoSample/demo08/viewer.html +27 -0
- egoSample/demo09/viewer.html +27 -0
- egoSample/demo10/viewer.html +27 -0
- ep0/viewer.html +28 -1
- ep1/viewer.html +28 -1
- ep2/viewer.html +28 -1
- ep3/viewer.html +28 -1
- ep4/view.html +28 -1
- ep5/viewer.html +28 -1
egoSample/demo02/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
egoSample/demo05/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
egoSample/demo07/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
egoSample/demo08/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
egoSample/demo09/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
egoSample/demo10/viewer.html
CHANGED
|
@@ -278,4 +278,31 @@ if(master){master.addEventListener('loadedmetadata',update);master.addEventListe
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
</script></body></html>
|
|
|
|
| 278 |
// keep orbit responsive even when paused
|
| 279 |
setInterval(()=>{if((hSt.dirty||dSt.dirty)&&master){hSt.dirty=dSt.dirty=false;const t=master.currentTime;drawHand(idxAt(HANDS.t,t));drawHead(idxAt(HEAD.t,t));}},60);
|
| 280 |
window.addEventListener('load',update);update();
|
| 281 |
+
|
| 282 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 283 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 284 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 285 |
+
button keeps working exactly as before. */
|
| 286 |
+
(function(){
|
| 287 |
+
var started=false, iv=null;
|
| 288 |
+
function vlist(){try{return Object.values(videos);}catch(e){return [];}}
|
| 289 |
+
function autoStart(){
|
| 290 |
+
if(started||playing)return;
|
| 291 |
+
var vs=vlist();
|
| 292 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 293 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 294 |
+
vs.forEach(function(v){v.muted=true;});
|
| 295 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 296 |
+
playing=true; playBtn.innerHTML='❙❙'; requestAnimationFrame(loop);
|
| 297 |
+
}).catch(function(){
|
| 298 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='▶';
|
| 299 |
+
});
|
| 300 |
+
}
|
| 301 |
+
vlist().forEach(function(v){
|
| 302 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 303 |
+
});
|
| 304 |
+
window.addEventListener('load',autoStart);
|
| 305 |
+
iv=setInterval(autoStart,400);
|
| 306 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 307 |
+
})();
|
| 308 |
</script></body></html>
|
ep0/viewer.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,4 +230,31 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 0 · 18.2s · 545 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|
ep1/viewer.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,4 +230,31 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 1 · 18.8s · 563 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|
ep2/viewer.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,4 +230,31 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 2 · 18.7s · 562 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|
ep3/viewer.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,4 +230,31 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 3 · 20.5s · 614 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|
ep4/view.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,5 +230,32 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
| 234 |
<!-- rev2 regular-file -->
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 4 · 22.4s · 673 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|
| 261 |
<!-- rev2 regular-file -->
|
ep5/viewer.html
CHANGED
|
@@ -50,7 +50,7 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
-
<div class="sub"><code>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
@@ -230,4 +230,31 @@ window.addEventListener('resize',()=>update());
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</script></body></html>
|
|
|
|
| 50 |
<header>
|
| 51 |
<a class="back" href="../teleop.html">← all episodes</a>
|
| 52 |
<h1>Pick up the water bottle and put it in the basket</h1>
|
| 53 |
+
<div class="sub"><code>a2</code> · episode 5 · 18.4s · 553 frames @ 30fps · teleop</div>
|
| 54 |
</header>
|
| 55 |
<div class="layout">
|
| 56 |
<div class="panel"><div class="camgrid" id="camgrid"></div></div>
|
|
|
|
| 230 |
master.addEventListener('loadedmetadata',update);
|
| 231 |
master.addEventListener('seeked',update);
|
| 232 |
window.addEventListener('load',update);
|
| 233 |
+
|
| 234 |
+
/* auto-start playback: first-time visitors shouldn't have to find the play
|
| 235 |
+
button. Videos are muted, which is what browser autoplay policies require;
|
| 236 |
+
if a browser still refuses, we roll back to the paused state so the manual
|
| 237 |
+
button keeps working exactly as before. */
|
| 238 |
+
(function(){
|
| 239 |
+
var started=false, iv=null;
|
| 240 |
+
function vlist(){try{return videos;}catch(e){return [];}}
|
| 241 |
+
function autoStart(){
|
| 242 |
+
if(started||playing)return;
|
| 243 |
+
var vs=vlist();
|
| 244 |
+
if(!vs.length||!vs.every(function(v){return v.readyState>=2;}))return;
|
| 245 |
+
started=true; if(iv){clearInterval(iv);iv=null;}
|
| 246 |
+
vs.forEach(function(v){v.muted=true;});
|
| 247 |
+
Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
|
| 248 |
+
playing=true; playBtn.textContent='\u275a\u275a'; requestAnimationFrame(loop);
|
| 249 |
+
}).catch(function(){
|
| 250 |
+
vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.textContent='\u25b6\ufe0e';
|
| 251 |
+
});
|
| 252 |
+
}
|
| 253 |
+
vlist().forEach(function(v){
|
| 254 |
+
v.addEventListener('canplay',autoStart); v.addEventListener('loadeddata',autoStart);
|
| 255 |
+
});
|
| 256 |
+
window.addEventListener('load',autoStart);
|
| 257 |
+
iv=setInterval(autoStart,400);
|
| 258 |
+
setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
|
| 259 |
+
})();
|
| 260 |
</script></body></html>
|