Build a Screen Recorder in Python (pyautogui + OpenCV+win32api)

Driven Data Science and Machine Learning enthusiast with hands-on experience in data analysis, predictive modeling, and Power BI visualization. Completed a Data Science internship at Codesoft, building strong technical foundations. With 2.5 years as a Shopify Executive and a background in system administration and malware analysis, I bring a broad IT skill set. Passionate about transforming complex data into actionable insights and contributing to innovative, fast-paced teams.
Recording your screen can be extremely useful for quick demos, bug reports, tutorials, or usability tests. In this short guide, you'll build a simple screen recorder in Python that:
captures screenshots,
writes them into a video file (MP4/AVI),
This is meant to be beginner-friendly and easy to adapt.
What you'll build
A small script (ScreenSnapper.py) that:
captures the primary display,
converts screenshots to frames for OpenCV,
saves the recording to a video file,
can be run from the command line with options.
Prerequisites
Windows (uses
GetSystemMetricsfrompywin32in the example; you can adapt for other OSes).Python 3.7+
Pip
Install the required packages (PowerShell):
python -m pip install --upgrade pip
python -m pip install opencv-python numpy pyautogui pywin32
The script (complete)
Save the following as ScreenSnapper.py. It contains a record_screen() function :
#!/usr/bin/env python3
"""
ScreenSnapper.py
Simple screen recorder with a small CLI.
"""
# Imports: libraries used in the script
import cv2 # OpenCV: for video writing and color conversion
import numpy as np # NumPy: for array handling
import pyautogui # pyautogui: to grab screenshots (returns a PIL Image)
import time # time: to control duration and timestamps
from win32api import GetSystemMetrics # Windows API: to get screen resolution
# Screen size
# Get the width and height of the primary display (pixels)
# GetSystemMetrics(0) -> screen width, GetSystemMetrics(1) -> screen height
width = GetSystemMetrics(0)
height = GetSystemMetrics(1)
# Frame size for the video writer (width, height)
dimen = (width, height)
# Video writer setup
# FourCC is a 4-byte code that tells OpenCV which codec to use to compress video.
# 'XVID' is commonly used and works on many systems. Other options: 'MJPG', 'H264' (system dependent).
frmt = cv2.VideoWriter_fourcc(*"XVID")
# Create a VideoWriter object to save the video file.
# Parameters:
# - filename: where to save the video (relative to current working directory or absolute path)
# - fourcc: compression codec
# - fps: frames per second (how many frames we want recorded each second)
# - frameSize: the size (width, height) of each frame in pixels
# Note: We choose 20.0 fps here. The script currently captures screenshots as fast as possible and writes
# them; if you want an exact frame rate, see the comment below on sleeping to match fps.
output = cv2.VideoWriter("output.mp4", frmt, 20.0, dimen)
# Timing / duration
# Record for a fixed number of seconds. Change `dur` to make the recording longer or shorter.
start_time = time.time()
# duration in seconds
dur = 10 # change this to record longer/shorter
end_time = start_time + dur
# Capture loop
# Keep taking screenshots and writing them to the video until time runs out.
while True:
# Take a screenshot using pyautogui. This returns a PIL Image in RGB format.
image = pyautogui.screenshot()
# Convert the PIL Image to a NumPy array (height, width, channels) in RGB order.
frame_1 = np.array(image)
# OpenCV expects images in BGR color order. Convert from RGB -> BGR so colors look correct in the saved video.
# Use cv2.COLOR_RGB2BGR because pyautogui/PIL provide RGB arrays.
frame = cv2.cvtColor(frame_1, cv2.COLOR_RGB2BGR)
# Write the converted frame to the video file.
output.write(frame)
# If you want a stable frame rate (for example exactly 20 fps), you can add a small sleep here:
# time.sleep(1 / 20.0) # sleep for one frame at 20 fps
# Note: adding sleep will limit CPU usage and stabilize the fps, but it also reduces the number of frames captured
# when the system is fast enough to capture more. Choose based on your needs.
# Check current time and stop when the duration has elapsed
cr_time = time.time()
if cr_time > end_time:
break
# Finish
# Release the VideoWriter to flush and close the output file properly
output.release()
print("Recording Completed Successfully")
# Tips and notes
# - If colors look inverted or wrong in the saved video, try swapping the conversion (RGB/BGR) or inspect frame_1's channel order.
# - If the video file does not play, try changing the codec/fourcc and file extension (e.g., use 'MJPG' and 'output.avi').
# - For a CLI or configurable duration/output filename, we can add argparse to accept parameters from the command line.
# - For long recordings, consider writing to disk in smaller chunks or using compression that your system supports well.
How the script works (brief)
We use
pyautogui.screenshot()to grab the current screen. It returns a PIL image in RGB color order.Convert that image to a NumPy array, then convert RGB โ BGR for OpenCV.
cv2.VideoWriterwrites frames to a video file. We choose a codec withcv2.VideoWriter_fourcc.
Run examples (PowerShell)
Default (10 seconds):
python ScreenSnapper.py
Custom:
python ScreenSnapper.py --duration 20 --output my_recording.mp4 --fps 15
Notes:
Try lowering
fpsif your machine is slow.If the saved video plays with odd colors, check the RGB/BGR conversion.
Common improvements and next steps
The basic script is intentionally simple. Here are a few improvements you can add:
Use
argparse(already included) to expose more options (region cropping, backend choice).A CLI for taking imputs in realtime.
Add a progress indicator or countdown in the terminal so you see remaining time.
Use a faster capture backend such as
mssfor higher frame rates and lower CPU overhead.Support capturing a region of the screen instead of the full monitor (
pyautogui.screenshot(region=(x, y, w, h))or use mss).Add an option to split long recordings into chunked files.
Troubleshooting
Missing packages? Install with pip as shown above.
If the video file won't play, try a different codec/extension:
MJPG+.avioften plays on more systems.
pyautogui.screenshot()can be slow on some systems;mssis faster.
Final thoughts
This simple recorder is a great starting point to learn how to capture the screen programmatically and how to combine small Python libraries to build useful tools.
If you'd like, I can:
Add live progress display,
Add region capture,
Update the script to use
mssas an optional backend for better performance,Or create a small GUI wrapper with Tkinter for interactive recording.
Author & links
GitHub: <https://github.com/Abhinavtiwari-doit/Pyhton-Projects>
LinkedIn: <https://www.linkedin.com/in/abhinavtiwari--/>
X (Twitter): <https://x.com/Abhinavt456>

