rydlrKE commited on
Commit
0868661
·
verified ·
1 Parent(s): ea75fd7

Improve playback loop smoothness

Browse files
Files changed (1) hide show
  1. kimodo/demo/app.py +29 -19
kimodo/demo/app.py CHANGED
@@ -626,10 +626,13 @@ class Demo:
626
  self._apply_constraint_overlay_visibility(session)
627
 
628
  def run(self) -> None:
629
- update_counter = 0
630
- cuda_check_interval = 300
631
  while True:
632
- last_update_time = time.time()
 
 
 
633
  if self.models:
634
  # the max playback speed is 2x the model fps (from gui_playback_speed_buttons)
635
  playback_fps = max(bundle.model_fps for bundle in self.models.values()) * 2.0
@@ -639,25 +642,32 @@ class Demo:
639
  # update each client session independently
640
  # copy to a list first to avoid changing size if client disconnects
641
  for client_id, session in list(self.client_sessions.items()):
642
- update_interval = int(playback_fps / (session.playback_speed * session.model_fps))
643
- new_frame_idx = session.frame_idx
644
- if session.playing and update_counter % update_interval == 0:
645
- if session.frame_idx >= session.max_frame_idx:
646
- new_frame_idx = 0
647
- else:
648
- new_frame_idx = session.frame_idx + 1
649
-
650
- # make sure the client is still active before updating the frame
651
- if self.client_active(client_id):
652
- self.set_frame(client_id, new_frame_idx)
653
-
654
- if update_counter % cuda_check_interval == 0:
 
 
 
 
 
 
 
 
655
  self.check_cuda_health()
 
656
 
657
- time_remaining = max(0, 1.0 / playback_fps - (time.time() - last_update_time))
658
  time.sleep(time_remaining)
659
- update_counter += 1
660
- update_counter %= playback_fps # wrap around to 0 every second
661
 
662
  def configure_theme(
663
  self,
 
626
  self._apply_constraint_overlay_visibility(session)
627
 
628
  def run(self) -> None:
629
+ last_loop_time = time.perf_counter()
630
+ last_cuda_check_time = 0.0
631
  while True:
632
+ loop_start_time = time.perf_counter()
633
+ delta_time = loop_start_time - last_loop_time
634
+ last_loop_time = loop_start_time
635
+
636
  if self.models:
637
  # the max playback speed is 2x the model fps (from gui_playback_speed_buttons)
638
  playback_fps = max(bundle.model_fps for bundle in self.models.values()) * 2.0
 
642
  # update each client session independently
643
  # copy to a list first to avoid changing size if client disconnects
644
  for client_id, session in list(self.client_sessions.items()):
645
+ if not session.playing:
646
+ continue
647
+ if session.model_fps <= 0:
648
+ continue
649
+
650
+ # Time-based stepping keeps playback smooth even if loop cadence jitters.
651
+ session.playback_time_accumulator += max(0.0, delta_time) * max(0.0, session.playback_speed)
652
+ frame_period = 1.0 / session.model_fps
653
+ if session.playback_time_accumulator < frame_period:
654
+ continue
655
+
656
+ frames_to_advance = int(session.playback_time_accumulator / frame_period)
657
+ session.playback_time_accumulator -= frames_to_advance * frame_period
658
+ frame_count = max(1, session.max_frame_idx + 1)
659
+ new_frame_idx = (session.frame_idx + frames_to_advance) % frame_count
660
+
661
+ # make sure the client is still active before updating the frame
662
+ if self.client_active(client_id):
663
+ self.set_frame(client_id, new_frame_idx)
664
+
665
+ if loop_start_time - last_cuda_check_time >= 5.0:
666
  self.check_cuda_health()
667
+ last_cuda_check_time = loop_start_time
668
 
669
+ time_remaining = max(0.0, 1.0 / playback_fps - (time.perf_counter() - loop_start_time))
670
  time.sleep(time_remaining)
 
 
671
 
672
  def configure_theme(
673
  self,