#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 屏幕录制工具 支持录制当前屏幕并保存为视频文件 """ import cv2 import numpy as np import pyautogui import threading import time from datetime import datetime import os class ScreenRecorder: def __init__(self, output_dir="recordings", fps=20, quality=80, region=None): """ 初始化屏幕录制器 Args: output_dir (str): 输出目录 fps (int): 帧率 quality (int): 视频质量 (1-100) region (tuple): 录制区域 (x, y, width, height),None表示全屏录制 """ self.output_dir = output_dir self.fps = fps self.quality = quality self.recording = False self.paused = False self.video_writer = None self.thread = None self.region = region # 创建输出目录 if not os.path.exists(output_dir): os.makedirs(output_dir) # 获取屏幕尺寸 self.screen_size = pyautogui.size() print(f"屏幕尺寸: {self.screen_size}") # 设置录制区域 if self.region: x, y, width, height = self.region # 确保区域在屏幕范围内 x = max(0, min(x, self.screen_size[0] - 1)) y = max(0, min(y, self.screen_size[1] - 1)) width = min(width, self.screen_size[0] - x) height = min(height, self.screen_size[1] - y) self.region = (x, y, width, height) self.record_size = (width, height) print(f"录制区域: {self.region}") else: self.record_size = self.screen_size print("录制模式: 全屏录制") def start_recording(self, filename=None): """ 开始录制 Args: filename (str): 输出文件名,如果为None则自动生成 """ if self.recording: print("录制已在进行中") return if filename is None: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"screen_record_{timestamp}.mp4" self.output_path = os.path.join(self.output_dir, filename) # 设置视频编码器 fourcc = cv2.VideoWriter_fourcc(*'mp4v') self.video_writer = cv2.VideoWriter( self.output_path, fourcc, self.fps, self.record_size ) self.recording = True self.paused = False # 在新线程中开始录制 self.thread = threading.Thread(target=self._record_loop) self.thread.daemon = True self.thread.start() print(f"开始录制: {self.output_path}") def _record_loop(self): """ 录制循环 """ while self.recording: if not self.paused: # 截取屏幕 if self.region: # 区域录制 x, y, width, height = self.region screenshot = pyautogui.screenshot(region=(x, y, width, height)) else: # 全屏录制 screenshot = pyautogui.screenshot() # 转换为numpy数组 frame = np.array(screenshot) # 转换颜色格式 (RGB -> BGR) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 写入视频文件 self.video_writer.write(frame) # 控制帧率 time.sleep(1.0 / self.fps) def pause_recording(self): """ 暂停录制 """ if not self.recording: print("当前没有在录制") return self.paused = not self.paused status = "暂停" if self.paused else "继续" print(f"录制{status}") def stop_recording(self): """ 停止录制 """ if not self.recording: print("当前没有在录制") return self.recording = False self.paused = False # 等待录制线程结束 if self.thread: self.thread.join() # 释放视频写入器 if self.video_writer: self.video_writer.release() self.video_writer = None print(f"录制完成: {self.output_path}") def set_region(self, region): """ 设置录制区域 Args: region (tuple): 录制区域 (x, y, width, height),None表示全屏录制 """ if self.recording: print("录制进行中,无法更改区域设置") return False self.region = region # 重新计算录制区域 if self.region: x, y, width, height = self.region # 确保区域在屏幕范围内 x = max(0, min(x, self.screen_size[0] - 1)) y = max(0, min(y, self.screen_size[1] - 1)) width = min(width, self.screen_size[0] - x) height = min(height, self.screen_size[1] - y) self.region = (x, y, width, height) self.record_size = (width, height) print(f"录制区域已设置: {self.region}") else: self.record_size = self.screen_size print("录制模式已设置: 全屏录制") return True def get_status(self): """ 获取录制状态 Returns: dict: 包含录制状态信息的字典 """ return { 'recording': self.recording, 'paused': self.paused, 'output_path': getattr(self, 'output_path', None), 'screen_size': self.screen_size, 'record_size': self.record_size, 'region': self.region, 'fps': self.fps } def main(): """ 主函数 - 命令行界面 """ recorder = ScreenRecorder() print("\n=== 屏幕录制工具 ===") print("命令:") print(" start [filename] - 开始录制") print(" pause - 暂停/恢复录制") print(" stop - 停止录制") print(" status - 查看状态") print(" region x y w h - 设置录制区域 (x, y, 宽度, 高度)") print(" fullscreen - 设置全屏录制") print(" center w h - 设置居中区域录制 (宽度, 高度)") print(" quit - 退出程序") print("\n输入命令:") while True: try: command = input("> ").strip().split() if not command: continue cmd = command[0].lower() if cmd == "start": filename = command[1] if len(command) > 1 else None recorder.start_recording(filename) elif cmd == "pause": recorder.pause_recording() elif cmd == "stop": recorder.stop_recording() elif cmd == "status": status = recorder.get_status() print(f"录制状态: {'进行中' if status['recording'] else '已停止'}") print(f"暂停状态: {'是' if status['paused'] else '否'}") print(f"输出文件: {status['output_path']}") print(f"屏幕尺寸: {status['screen_size']}") print(f"录制尺寸: {status['record_size']}") print(f"录制区域: {status['region'] if status['region'] else '全屏'}") print(f"帧率: {status['fps']} FPS") elif cmd == "region": if len(command) != 5: print("用法: region x y width height") continue try: x, y, w, h = map(int, command[1:5]) if recorder.set_region((x, y, w, h)): print(f"录制区域已设置: ({x}, {y}, {w}, {h})") except ValueError: print("请输入有效的数字") elif cmd == "fullscreen": if recorder.set_region(None): print("已设置为全屏录制") elif cmd == "center": if len(command) != 3: print("用法: center width height") continue try: w, h = map(int, command[1:3]) screen_w, screen_h = recorder.screen_size x = (screen_w - w) // 2 y = (screen_h - h) // 2 if recorder.set_region((x, y, w, h)): print(f"居中录制区域已设置: ({x}, {y}, {w}, {h})") except ValueError: print("请输入有效的数字") elif cmd == "quit": if recorder.recording: recorder.stop_recording() print("程序退出") break else: print("未知命令") except KeyboardInterrupt: if recorder.recording: recorder.stop_recording() print("\n程序退出") break except Exception as e: print(f"错误: {e}") if __name__ == "__main__": main()