feat(main.py): implement frame caching to improve playback performance
This commit is contained in:
48
main.py
48
main.py
@@ -60,6 +60,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
|
||||
self.current_seek_key = None
|
||||
@@ -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"""
|
||||
|
Reference in New Issue
Block a user