如何使用Python实现高帧率屏幕录制
Hey there! Let's fix your screen recording frame rate issue and get that GPU working for you. Your current setup is bottlenecked by slow screen capture and CPU-only processing—here's how to address both:
Your code has a few key bottlenecks:
ImageGrab.grab()is slow: It's a CPU-bound, older method that adds overhead converting between PIL images and numpy arrays.- CPU-only color conversion:
cv2.cvtColorruns on the CPU, which adds more processing time per frame. - CPU video encoding: The XVID codec you're using is CPU-based, so encoding frames eats up cycles that could be used for capture.
We'll replace slow components with faster alternatives and leverage GPU acceleration where possible.
1. Switch to a Faster Screen Capture Library
Use mss—it's optimized for screen capture, returns numpy arrays directly, and is way faster than ImageGrab. Install it first:
pip install mss
2. Use GPU-Accelerated Encoding & Processing
To use your GPU, you need an OpenCV build with CUDA support. Check if your setup has it with:
import cv2 print(cv2.cuda.getCudaEnabledDeviceCount()) # Returns >0 if CUDA is enabled
If it returns 0, install a CUDA-enabled OpenCV version (e.g., via conda: conda install -c conda-forge opencv-cuda).
Full Optimized Code
This code uses mss for fast capture, GPU color conversion, and NVENC (GPU-based H.264 encoding):
import cv2 import mss import numpy as np # Initialize mss for high-speed screen capture sct = mss.mss() monitor = sct.monitors[1] # 1 = primary monitor; adjust if you have multiple # Use GPU-accelerated codec (NVENC H.264) - check support with cv2.getBuildInformation() fourcc = cv2.VideoWriter_fourcc(*'H264') # Set output to 60 FPS, match your monitor resolution video_writer = cv2.VideoWriter( "output_gpu.mp4", fourcc, 60, (monitor["width"], monitor["height"]) ) # Check if GPU acceleration is available use_gpu = cv2.cuda.getCudaEnabledDeviceCount() > 0 if use_gpu: print("GPU acceleration activated!") cuda_stream = cv2.cuda.Stream() try: while True: # Capture screen directly as a numpy array (no PIL conversion overhead) raw_frame = np.array(sct.grab(monitor)) # Convert BGRA (mss output) to BGR for OpenCV if use_gpu: # Offload conversion to GPU gpu_frame = cv2.cuda_GpuMat() gpu_frame.upload(raw_frame, cuda_stream) gpu_bgr_frame = cv2.cuda.cvtColor(gpu_frame, cv2.COLOR_BGRA2BGR, stream=cuda_stream) bgr_frame = gpu_bgr_frame.download(cuda_stream) cuda_stream.waitForCompletion() else: # Fallback to CPU conversion (still faster with mss) bgr_frame = cv2.cvtColor(raw_frame, cv2.COLOR_BGRA2BGR) # Write frame to video (uses GPU encoding if H264 NVENC is enabled) video_writer.write(bgr_frame) # Optional preview window (disable if you need maximum FPS) cv2.imshow("Screen Capture", bgr_frame) if cv2.waitKey(1) == 27: # Press ESC to stop recording break finally: # Cleanup resources sct.close() video_writer.release() cv2.destroyAllWindows()
Key Improvements Breakdown
- Faster capture:
msscuts out the PIL-to-numpy conversion step, capturing frames in milliseconds instead of tens of milliseconds. - GPU color conversion: Moving
cvtColorto the GPU frees up CPU cycles for capture and other tasks. - GPU encoding: The H264 codec (when paired with CUDA-enabled OpenCV) uses NVIDIA's NVENC to encode frames on the GPU, eliminating the CPU encoding bottleneck.
Extra Tips for Maximum FPS
- Disable the preview window:
cv2.imshowadds overhead—comment that out if you don't need to see the live feed. - Capture only what you need: If you don't need the entire screen, define a smaller region in
mss(e.g.,monitor = {"top": 0, "left": 0, "width": 1280, "height": 720}). - Update GPU drivers: Newer drivers optimize NVENC performance, so make sure yours are up to date.
内容的提问来源于stack exchange,提问作者shobhit99

