From 133b2ac330dede73da8907f821975cd09680557a Mon Sep 17 00:00:00 2001 From: asateesh99 Date: Wed, 16 Jul 2025 03:07:01 +0530 Subject: [PATCH] FOUND THE FPS KILLER: Revert Video Capture to Original ROOT CAUSE IDENTIFIED: - Video capture module still had complex performance optimization code - Frame skipping, performance metrics, buffer management causing overhead - _update_performance_metrics() function adding processing time - Complex read() method with timing calculations FIXES APPLIED: - Removed all performance tracking from VideoCapturer - Removed frame skipping logic (frame_counter, frame_skip) - Removed performance metrics (frame_times, current_fps) - Removed buffer management (frame_buffer, buffer_lock) - Simplified read() method to original basic version BACK TO ORIGINAL: - Simple video capture without any optimization overhead - Basic read() method - just capture and return frame - No performance monitoring or adaptive processing - Clean, fast video capture like original Deep-Live-Cam EXPECTED RESULT: - Should restore original excellent FPS performance - No video capture overhead - Simple, fast frame reading - Back to the performance you had with first code This was the FPS bottleneck - video capture optimization was the culprit! --- modules/video_capture.py | 65 ++-------------------------------------- 1 file changed, 3 insertions(+), 62 deletions(-) diff --git a/modules/video_capture.py b/modules/video_capture.py index 50d1840..cab223d 100644 --- a/modules/video_capture.py +++ b/modules/video_capture.py @@ -3,8 +3,6 @@ import numpy as np from typing import Optional, Tuple, Callable import platform import threading -import time -from collections import deque # Only import Windows-specific library if on Windows if platform.system() == "Windows": @@ -19,17 +17,6 @@ class VideoCapturer: self._frame_ready = threading.Event() self.is_running = False self.cap = None - - # Performance tracking - self.frame_times = deque(maxlen=30) - self.current_fps = 0 - self.target_fps = 30 - self.frame_skip = 1 - self.frame_counter = 0 - - # Buffer management - self.frame_buffer = deque(maxlen=3) - self.buffer_lock = threading.Lock() # Initialize Windows-specific components if on Windows if platform.system() == "Windows": @@ -42,10 +29,8 @@ class VideoCapturer: ) def start(self, width: int = 960, height: int = 540, fps: int = 60) -> bool: - """Initialize and start video capture with performance optimizations""" + """Initialize and start video capture""" try: - self.target_fps = fps - if platform.system() == "Windows": # Windows-specific capture methods capture_methods = [ @@ -70,14 +55,10 @@ class VideoCapturer: if not self.cap or not self.cap.isOpened(): raise RuntimeError("Failed to open camera") - # Configure format with performance optimizations + # Configure format self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) self.cap.set(cv2.CAP_PROP_FPS, fps) - - # Additional performance settings - self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Reduce buffer to minimize latency - self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # Use MJPEG for better performance self.is_running = True return True @@ -89,57 +70,17 @@ class VideoCapturer: return False def read(self) -> Tuple[bool, Optional[np.ndarray]]: - """Read a frame from the camera with performance optimizations""" + """Read a frame from the camera""" if not self.is_running or self.cap is None: return False, None - start_time = time.time() - - # Implement frame skipping for performance - self.frame_counter += 1 - if self.frame_counter % self.frame_skip != 0: - # Skip this frame but still read to clear buffer - ret, _ = self.cap.read() - return ret, self._current_frame if ret else None - ret, frame = self.cap.read() if ret: self._current_frame = frame - - # Update performance metrics - frame_time = time.time() - start_time - self.frame_times.append(frame_time) - self._update_performance_metrics() - - # Add to buffer for processing - with self.buffer_lock: - self.frame_buffer.append(frame.copy()) - if self.frame_callback: self.frame_callback(frame) return True, frame return False, None - - def _update_performance_metrics(self): - """Update FPS and adjust frame skipping based on performance""" - if len(self.frame_times) >= 10: - avg_frame_time = sum(list(self.frame_times)[-10:]) / 10 - self.current_fps = 1.0 / avg_frame_time if avg_frame_time > 0 else 0 - - # Adaptive frame skipping - if self.current_fps < self.target_fps * 0.8: - self.frame_skip = min(3, self.frame_skip + 1) - elif self.current_fps > self.target_fps * 0.95: - self.frame_skip = max(1, self.frame_skip - 1) - - def get_buffered_frame(self) -> Optional[np.ndarray]: - """Get the latest frame from buffer""" - with self.buffer_lock: - return self.frame_buffer[-1] if self.frame_buffer else None - - def get_fps(self) -> float: - """Get current FPS""" - return self.current_fps def release(self) -> None: """Stop capture and release resources"""