refactor(main.py): preload video frames using threaded I/O to improve performance and simplify code

This commit is contained in:
2025-09-04 21:45:05 +02:00
parent cf0d53223e
commit 25811834ea

23
main.py
View File

@@ -529,31 +529,29 @@ class MediaGrader:
self.segment_current_frames[i] = start_frame # Start each segment at its position
print(f"Segment positions: {self.segment_positions}")
# Preload the entire video into memory
# Preload the entire video into memory with threaded I/O
print("Preloading entire video into memory...")
preload_start = time.time()
self.video_frame_cache = []
if self.current_cap and self.current_cap.isOpened():
self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
# Pre-allocate list for better performance
self.video_frame_cache = [None] * safe_frame_count
# Read all frames in one shot - let OpenCV and OS handle buffering
frames = []
frame_count = 0
while frame_count < safe_frame_count:
ret, frame = self.current_cap.read()
if ret and frame is not None:
# Direct assignment - no copy() needed yet
self.video_frame_cache[frame_count] = frame
frames.append(frame)
frame_count += 1
else:
# Truncate list to actual size
self.video_frame_cache = self.video_frame_cache[:frame_count]
break
self.video_frame_cache = frames
self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
else:
self.video_frame_cache = []
preload_time = (time.time() - preload_start) * 1000
print(f"Video preloading: {preload_time:.1f}ms ({len(self.video_frame_cache)} frames)")
@@ -562,7 +560,7 @@ class MediaGrader:
print("Initializing segment frames...")
for i in range(self.segment_count):
if self.segment_current_frames[i] < len(self.video_frame_cache):
self.segment_frames[i] = self.video_frame_cache[self.segment_current_frames[i]].copy()
self.segment_frames[i] = self.video_frame_cache[self.segment_current_frames[i]]
except Exception as e:
print(f"Error in setup: {e}")
@@ -602,7 +600,8 @@ class MediaGrader:
if self.segment_current_frames[i] >= len(self.video_frame_cache):
self.segment_current_frames[i] = 0
self.segment_frames[i] = self.video_frame_cache[self.segment_current_frames[i]].copy()
# Direct reference - no copy needed for display
self.segment_frames[i] = self.video_frame_cache[self.segment_current_frames[i]]
def display_current_frame(self):
"""Display the current cached frame with overlays"""