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