faradayfuture commited on
Commit
ebf6e8c
·
verified ·
1 Parent(s): 35cc946

Harden video sync for network playback (gentle drift correction)

Browse files
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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
- // keep the other cams locked to master when they drift
139
- master.addEventListener('timeupdate',()=>{videos.forEach(v=>{if(v!==master&&Math.abs(v.currentTime-master.currentTime)>0.08){try{v.currentTime=master.currentTime;}catch(e){}}});});
 
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(){