Spaces:
Running
Running
Harden video sync for network playback (gentle drift correction)
Browse files- ep0/viewer.html +3 -2
- ep1/viewer.html +3 -2
- ep2/viewer.html +3 -2
- ep3/viewer.html +3 -2
- ep4/viewer.html +3 -2
- ep5/viewer.html +3 -2
ep0/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|
ep1/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|
ep2/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|
ep3/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|
ep4/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|
ep5/viewer.html
CHANGED
|
@@ -135,8 +135,9 @@ let playing=false;
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
-
|
| 139 |
-
master.addEventListener('
|
|
|
|
| 140 |
|
| 141 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 142 |
function update(){
|
|
|
|
| 135 |
function seekTo(t){videos.forEach(v=>{try{v.currentTime=t;}catch(e){}});}
|
| 136 |
playBtn.onclick=()=>{playing=!playing;if(playing){videos.forEach(v=>v.play());playBtn.textContent='❚❚';requestAnimationFrame(loop);}else{videos.forEach(v=>v.pause());playBtn.textContent='▶︎';}};
|
| 137 |
seek.oninput=()=>{const t=seek.value/1000*DUR;seekTo(t);update();};
|
| 138 |
+
function resyncOthers(){const t=master.currentTime;videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-t)>0.25){try{v.currentTime=t;}catch(e){}}});}
|
| 139 |
+
master.addEventListener('seeked',resyncOthers);
|
| 140 |
+
setInterval(()=>{if(!master.paused)resyncOthers();},1000);
|
| 141 |
|
| 142 |
function frameAt(t){let i=Math.round(t*S.fps);return Math.max(0,Math.min(S.n-1,i));}
|
| 143 |
function update(){
|