如何用Python案例实现屏幕录制?

wen python案例 1

如何用Python案例实现屏幕录制?完整代码与实战详解

目录导读


为什么选择Python实现屏幕录制?

在视频录制领域,多数用户第一反应是OBS或Bandicam等专业工具,但如果你是开发者,需要在自动化脚本、教学课件生成或远程监控中嵌入录屏功能,Python的跨平台特性与丰富的第三方库能让定制化录制变得极其简单。用Python做屏幕录制没有GUI臃肿的负担,你可以将录制逻辑整合进爬虫、测试框架或数据采集系统

如何用Python案例实现屏幕录制?

Q:Python录屏比专业软件慢吗?
A:是的,原生方式下帧率通常只有15-30 FPS(专业软件可达60+),但通过多线程+硬件加速(如DXcam库)可大幅提升,若仅需采集桌面变化(非游戏),Python完全够用。


核心依赖库对比与安装指南

库名称 特点 适用场景 安装指令
PIL(Pillow) 截图功能稳定,返回RGB图像 作为底层截图工具 pip install Pillow
OpenCV 视频编解码强大,支持多种格式 合成视频流 pip install opencv-python
PyAutoGUI 跨平台截图简单,自带坐标获取 快速原型开发 pip install pyautogui
mss 高性能截图,支持多显示器 高帧率需求 pip install mss

推荐组合PIL/mss(截图) + OpenCV(写入视频) + numpy(图像处理)。
安装指令:

pip install pillow opencv-python numpy mss

实战案例一:基于PIL+OpenCV的基础录屏

核心逻辑:循环截取屏幕 → 转为BGR格式 → 写入MP4文件。

import numpy as np
from PIL import ImageGrab
import cv2
import time
def record_screen_basic(output_path="output_basic.mp4", fps=20.0):
    # 1. 获取屏幕尺寸并设定编码器
    screen = ImageGrab.grab()
    width, height = screen.size
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    # 2. 录制10秒示例(实际使用时改为while循环+终止条件)
    start_time = time.time()
    duration = 10  # 秒
    while time.time() - start_time < duration:
        # 截屏 → 转为numpy数组 → RGB转BGR
        img = ImageGrab.grab()
        frame = np.array(img)
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        out.write(frame)
        # 可添加延时控制帧率(实际已由fps控制)
        time.sleep(1/fps)
    out.release()
    cv2.destroyAllWindows()
    print(f"录制完成,视频保存至 {output_path}")

Q:为什么我的视频是黑屏?
A:检查是否在虚拟环境或远程桌面下运行,部分环境截图函数可能失效,可尝试改用mss.grab()替代ImageGrab。


实战案例二:使用PyAutoGUI+OpenCV的轻量方案

PyAutoGUI的region参数可指定录制区域,适合只录制部分屏幕。

import pyautogui
import cv2
import numpy as np
def record_region(left=100, top=100, width=800, height=600, output="region.mp4"):
    # 获取指定区域截图
    screenshot = pyautogui.screenshot(region=(left, top, width, height))
    frame = np.array(screenshot)
    height, width, _ = frame.shape
    fourcc = cv2.VideoWriter_fourcc(*'XVID')  # 或使用'mp4v'
    out = cv2.VideoWriter(output, fourcc, 15.0, (width, height))
    for i in range(150):  # 录制150帧(约10秒)
        img = pyautogui.screenshot(region=(left, top, width, height))
        frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        out.write(frame)
    out.release()
    print("区域录制完成")

优点:代码极简,适合集成到自动化脚本中。
缺点:PyAutoGUI截图性能一般,高分辨率下帧率可能降到10以下。


实战案例三:带鼠标轨迹与实时水印的高阶录制

录制时叠加鼠标位置、时间戳或自定义水印,常用于教学视频制作。

import numpy as np
import cv2
import pyautogui
from datetime import datetime
def record_with_marker(output="demo_with_marker.mp4", record_seconds=10):
    # 获取主屏幕尺寸
    screen_size = pyautogui.size()
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output, fourcc, 20.0, screen_size)
    start_time = datetime.now()
    while (datetime.now() - start_time).seconds < record_seconds:
        # 截图并转为OpenCV格式
        img = pyautogui.screenshot()
        frame = np.array(img)
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        # 1. 添加鼠标光标圆圈
        mouse_x, mouse_y = pyautogui.position()
        cv2.circle(frame, (mouse_x, mouse_y), 10, (0, 255, 0), 2)  # 绿色圆圈
        # 2. 添加时间水印
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cv2.putText(frame, timestamp, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 
                    0.7, (255, 255, 255), 2, cv2.LINE_AA)
        # 3. 可添加自定义水印(如"演示版")
        cv2.putText(frame, "WATERMARK", (screen_size[0]-200, screen_size[1]-30), 
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
        out.write(frame)
    out.release()
    print("带标记的录制完成")

扩展思路

  • 使用pynput库监听键盘事件,通过按下特定键开始/停止录制。
  • 结合pygetwindow库仅录制特定应用程序窗口。

常见问题FAQ

Q1:录制的视频没有声音怎么办?
A:Python原生方案通常只录制视频流,要同步录音,需使用pyaudiosounddevice库额外开启音频采集线程,并利用moviepy合并音频和视频,此部分代码较复杂,建议单独封装为AudioRecorder类。

Q2:如何实现录制过程中实时预览?
A:在循环中插入cv2.imshow('Screen Recorder', frame),并监听cv2.waitKey(1) & 0xFF == ord('q')来退出预览。

Q3:录制游戏或全屏应用卡顿严重?
A:建议改用mss库替代PIL/PyAutoGUI,mss通过底层API(Windows为DXGI)获取帧,速度提升3-5倍,代码示例如下:

import mss
sct = mss.mss()
monitor = sct.monitors[1]  # 主显示器
img = sct.grab(monitor)     # 直接返回PIL Image
frame = np.array(img)

性能优化与多线程录制

瓶颈分析:单线程中截图 → 转格式 → 写入磁盘是串行操作,造成帧率下降。

优化方案:生产者-消费者模型

  • 生产者线程:高速截图,将原始帧放入队列
  • 消费者线程:从队列取出帧,写入视频文件
  • 缓冲区大小:设置最大队列长度防止内存溢出(如queue.Queue(maxsize=30)

参考代码架构:

import threading
import queue
def capture_thread(q, stop_flag):
    """持续截图,放入队列"""
    while not stop_flag.is_set():
        img = ImageGrab.grab()  # 或使用mss
        q.put(np.array(img))
def write_thread(q, stop_flag, out):
    """从队列取帧并写入"""
    while not (stop_flag.is_set() and q.empty()):
        try:
            frame = q.get(timeout=0.5)
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
            out.write(frame)
        except queue.Empty:
            continue
# 使用时创建线程,通过stop_flag控制结束

实战效果:在1080p分辨率下,单线程约20 FPS,多线程可提升至35-40 FPS(使用mss可达50+)。


文章结语
通过以上四个层次递进的Python案例,你可以根据需求选择最合适的屏幕录制方案,从基础的全屏录制到带交互元素的高阶录制,再到多线程性能优化,整个技术栈完全可控,如果你需要在生产环境中长期运行,建议加上异常处理(如磁盘空间不足)、SIGINT信号捕获和日志记录,下一步可以尝试将录制模块打包成pip包,或整合进FastAPI提供RESTful录屏服务。

代码的重点不在于长度,而在于清晰地理解每个环节的瓶颈——截图速度、编解码性能、I/O写入,有了本文的框架,你可以自由探索更高效的实现路径。

抱歉,评论功能暂时关闭!