feat(main.py): implement frame caching to improve playback performance

This commit is contained in:
2025-08-20 12:34:56 +02:00
parent e0dd1a8db8
commit ce0232846e

48
main.py
View File

@@ -59,6 +59,10 @@ class MediaGrader:
# Timeline visibility state
self.timeline_visible = True
# Simple frame cache for frequently accessed frames
self.frame_cache = {} # Dict[frame_number: frame_data]
self.cache_size_limit = 50 # Keep it small and simple
# Key repeat tracking with rate limiting
self.last_seek_time = 0
@@ -558,6 +562,32 @@ class MediaGrader:
self.segment_caps = []
self.segment_frames = []
self.segment_positions = []
# Clear frame cache
self.frame_cache.clear()
def get_cached_frame(self, frame_number: int):
"""Get frame from cache or load it if not cached"""
if frame_number in self.frame_cache:
return self.frame_cache[frame_number]
# Load frame and cache it (lazy loading)
if self.current_cap:
original_pos = int(self.current_cap.get(cv2.CAP_PROP_POS_FRAMES))
self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
ret, frame = self.current_cap.read()
self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, original_pos)
if ret:
# Cache the frame (with size limit)
if len(self.frame_cache) >= self.cache_size_limit:
# Remove oldest cached frame
oldest_key = min(self.frame_cache.keys())
del self.frame_cache[oldest_key]
self.frame_cache[frame_number] = frame.copy()
return frame
return None
def update_segment_frames(self):
"""Update frames for all segments during playback"""
@@ -620,14 +650,20 @@ class MediaGrader:
segment_end = min(self.total_frames - 1, segment_start + segment_duration)
target_frame = max(segment_start, min(current_frame + frames_delta, segment_end))
cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
# Load new frame
ret, frame = cap.read()
if ret:
self.segment_frames[i] = frame
# Reset position for next read
# Try cache first, then load if needed
cached_frame = self.get_cached_frame(target_frame)
if cached_frame is not None:
self.segment_frames[i] = cached_frame
cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
else:
# Fall back to normal seeking
cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
ret, frame = cap.read()
if ret:
self.segment_frames[i] = frame
# Reset position for next read
cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
def display_current_frame(self):
"""Display the current cached frame with overlays"""