feat(main.py): implement frame caching to improve playback performance
This commit is contained in:
40
main.py
40
main.py
@@ -60,6 +60,10 @@ class MediaGrader:
|
|||||||
# Timeline visibility state
|
# Timeline visibility state
|
||||||
self.timeline_visible = True
|
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
|
# Key repeat tracking with rate limiting
|
||||||
self.last_seek_time = 0
|
self.last_seek_time = 0
|
||||||
self.current_seek_key = None
|
self.current_seek_key = None
|
||||||
@@ -558,6 +562,32 @@ class MediaGrader:
|
|||||||
self.segment_caps = []
|
self.segment_caps = []
|
||||||
self.segment_frames = []
|
self.segment_frames = []
|
||||||
self.segment_positions = []
|
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):
|
def update_segment_frames(self):
|
||||||
"""Update frames for all segments during playback"""
|
"""Update frames for all segments during playback"""
|
||||||
@@ -620,9 +650,15 @@ class MediaGrader:
|
|||||||
segment_end = min(self.total_frames - 1, segment_start + segment_duration)
|
segment_end = min(self.total_frames - 1, segment_start + segment_duration)
|
||||||
|
|
||||||
target_frame = max(segment_start, min(current_frame + frames_delta, segment_end))
|
target_frame = max(segment_start, min(current_frame + frames_delta, segment_end))
|
||||||
cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
|
|
||||||
|
|
||||||
# Load new frame
|
# 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()
|
ret, frame = cap.read()
|
||||||
if ret:
|
if ret:
|
||||||
self.segment_frames[i] = frame
|
self.segment_frames[i] = frame
|
||||||
|
Reference in New Issue
Block a user