您当前的位置:首页 > 计算机 > 编程开发 > Python

python --录屏工具开发

时间:08-15来源:作者:点击数:

该文章描述了一个使用Python实现的GUI录屏工具,主要利用Tkinter库构建界面,支持倒计时功能和帧率设置。用户可以通过菜单栏进行开始、暂停和结束录屏操作,录屏视频保存至桌面,倒计时默认为3秒,帧率默认为12fps,可自定义调整。

import os
from datetime import datetime
import time
from threading import Thread, Event
from tkinter import Tk, Menu, Frame, Label, IntVar, Toplevel, Entry, Scale, HORIZONTAL, messagebox
import numpy as np
import cv2
import pyautogui


class Window(Tk):
    def __init__(self):
        super().__init__()

        # 倒计时标签对象
        self.lb = None
        # 倒计时标签数值
        self.lbNum = IntVar()
        self.lbNum.set(3)
        # 倒计时数值备份
        self.lbNumBack = 3

        # 帧率
        self.fps = 12

        # 录屏状态
        self.screencapState = False
        # 暂停状态
        self.screencapWaitState = Event()
        # 取消暂停
        self.screencapWaitState.set()

        # 倒计时状态
        self.countdownState = False

        self.gui()
        self.menu()

    def gui(self):
        """
        主窗体
        :return:
        """
        # 设置窗体背景色
        self["background"] = "Crimson"
        # 设置Crimson色为透明
        self.attributes('-transparentcolor', 'Crimson')
        # 设置窗体透明度为80%
        self.attributes("-alpha", 0.8)
        # 获取主屏幕宽高
        mainWidth = self.winfo_screenwidth()
        mainHeight = self.winfo_screenheight()
        # 窗口宽高
        width = int(mainWidth * 0.4)
        height = int(mainHeight * 0.4)
        # 设置窗口大小与显示位置
        self.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
        # 标题
        self.title("录屏工具")
        # 图标
        self.iconbitmap("logo.ico")
        # 倒计时标签
        f = Frame(self)
        self.lb = Label(
            f,
            textvariable=self.lbNum,
            fg='red',
            bg='Crimson',
            font=('微软雅黑', 66, 'bold')
        )
        self.lb.pack()
        # 水平垂直居中
        f.pack(expand=1)

    def menu(self):
        """
        菜单栏
        :return:
        """
        menubar = Menu(self)
        # 操作
        operate = Menu(menubar, tearoff=0)
        menubar.add_cascade(label="操作", menu=operate)
        operate.add_command(label='开始', command=self.startScreencap)
        operate.add_command(label='暂停', command=self.waitScreencap)
        operate.add_separator()
        operate.add_command(label='结束', command=self.stopScreencap)

        # 操作
        setting = Menu(menubar, tearoff=0)
        menubar.add_cascade(label="设置", menu=setting)
        setting.add_command(label='倒计时', command=self.setCountdown)
        setting.add_separator()
        setting.add_command(label='帧率', command=self.setFps)

        # 关于
        about = Menu(menubar, tearoff=0)
        menubar.add_cascade(label='关于', menu=about)
        about.add_command(label='说明', command=self.instruction)
        about.add_separator()
        about.add_command(label='作者', command=self.author)
        self.config(menu=menubar)

    def setCountdown(self):
        """
        设置倒计时弹窗
        :return:
        """
        # 设置主窗口不可操作
        self.attributes("-disabled", 1)
        # 弹窗
        t = Toplevel(self)
        # 弹窗宽高
        width = 250
        height = 120
        # 获取主屏幕宽高
        mainWidth = t.winfo_screenwidth()
        mainHeight = t.winfo_screenheight()
        # 设置窗口大小与显示位置
        t.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
        # 禁止窗口缩放
        t.resizable(0, 0)
        # 标题
        t.title("倒计时设置")
        # 图标
        t.iconbitmap("logo.ico")
        # 输入框
        e = Entry(t,
                  width=2,
                  fg='red',
                  font=('微软雅黑', 30, 'bold')
                  )
        e.pack(pady=30)
        # 设置输入框焦点
        e.focus_set()
        # 设置输入框值
        e.insert(0, self.lbNumBack)
        # 绑定弹窗关闭事件
        t.protocol("WM_DELETE_WINDOW", lambda: self.setCountdownClose(e, t))

    def setCountdownClose(self, e, t):
        """
        设置倒计时弹窗关闭事件
        :param e: 设置倒计时弹窗输入框对象
        :param t: 设置倒计时弹窗对象
        :return:
        """
        try:
            # 获取输入框数据
            num = int(e.get())
            # 更新倒计时标签数值
            self.lbNum.set(num)
            # 备份倒计时设置数值
            self.lbNumBack = num
            # 销毁设置倒计时数值弹窗
            t.destroy()
            # 设置主窗口可操作
            self.attributes("-disabled", 0)
            # 窗口保持在前面
            self.lift()
        except ValueError:
            pass

    def setFps(self):
        """
        设置帧率弹窗
        :return:
        """
        # 设置主窗口不可操作
        self.attributes("-disabled", 1)
        # 弹窗
        t = Toplevel(self)
        # 弹窗宽高
        width = 250
        height = 120
        # 获取主屏幕宽高
        mainWidth = t.winfo_screenwidth()
        mainHeight = t.winfo_screenheight()
        # 设置窗口大小与显示位置
        t.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
        # 禁止窗口缩放
        t.resizable(0, 0)
        # 标题
        t.title("帧率设置")
        # 图标
        t.iconbitmap("logo.ico")
        # 输入框
        e = Scale(t,
                  width=60,
                  from_=6,
                  to=60,
                  orient=HORIZONTAL)
        e.pack()
        e.set(self.fps)
        # 绑定弹窗关闭事件
        t.protocol("WM_DELETE_WINDOW", lambda: self.setFpsClose(e, t))

    def setFpsClose(self, e, t):
        """
        设置倒计时弹窗关闭事件
        :param e: 设置滚动条对象
        :param t: 设置帧率弹窗对象
        :return:
        """
        try:
            # 获取滚动条数据
            num = int(e.get())
            self.fps = num
            # 销毁设置帧率弹窗
            t.destroy()
            # 设置主窗口可操作
            self.attributes("-disabled", 0)
            # 窗口保持在前面
            self.lift()
        except ValueError:
            pass

    @staticmethod
    def instruction():
        messagebox.showinfo('说明',
                            '1、录屏区域为本软件窗口区域\n\n'
                            '2、菜单栏进行录屏操作\n\n'
                            '3、录屏视频位于桌面\n\n'
                            '4、倒计时设置秒值-默认:3\n\n'
                            '5、帧率常为12~24-默认:12')

    @staticmethod
    def author():
        messagebox.showinfo('作者', '小丫')

    def screencap(self):
        """
        录屏
        :return:
        """
        # 倒计时
        self.countdown()
        # 编码格式
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        video = cv2.VideoWriter(os.path.join(os.path.join(os.path.expanduser("~"), 'Desktop'), datetime.now().strftime('%Y-%m-%d %H-%M-%S') + '.mp4'),
                                fourcc,
                                self.fps,
                                pyautogui.screenshot(region=(
                                    self.winfo_x() + 4, self.winfo_y(), self.winfo_width(),
                                    self.winfo_height())).size
                                )
        while self.screencapState:
            # 暂停
            self.screencapWaitState.wait()
            # 转为opencv的BGR格式
            imm = cv2.cvtColor(
                np.array(pyautogui.screenshot(
                    region=(self.winfo_x() + 4, self.winfo_y(), self.winfo_width(), self.winfo_height()))),
                cv2.COLOR_RGB2BGR
            )
            # 写入视频
            video.write(imm)
        # 保存视频
        video.release()

    def startScreencap(self):
        """
        开始录屏
        :return:
        """
        # 判断暂停状态
        if self.screencapWaitState.isSet():
            # 判断录屏状态
            if not self.screencapState:
                # 录制状态开启
                self.screencapState = True
                # 取消缩放
                self.resizable(0, 0)
                # 录屏
                ts = Thread(target=self.screencap)
                ts.daemon = True
                ts.start()
        else:
            # 判断倒计时状态
            if not self.countdownState:
                # 倒计时初始化
                self.lbNum.set(self.lbNumBack)
                # 显示标签
                self.lb.configure(fg="red")
                # 继续录屏
                tc = Thread(target=self.continueScreencap)
                tc.daemon = True
                tc.start()

    def continueScreencap(self):
        """
        继续录屏
        :return:
        """
        # 倒计时
        self.countdown()
        # 取消暂停
        self.screencapWaitState.set()

    def waitScreencap(self):
        """
        暂停录屏
        :return:
        """
        # 判断录屏状态与倒计时状态
        if self.screencapState and not self.countdownState:
            self.screencapWaitState.clear()
            # 暂停指示
            self.lbNum.set(0)
            # 显示标签
            self.lb.configure(fg="red")

    def stopScreencap(self):
        """
        停止录屏
        :return:
        """
        # 判断录屏状态与倒计时状态
        if self.screencapState and not self.countdownState:
            # 取消暂停
            self.screencapWaitState.set()
            # 录屏状态关闭
            self.screencapState = False
            # 倒计时初始化
            self.lbNum.set(self.lbNumBack)
            # 显示标签
            self.lb.configure(fg="red")
            # 开启缩放
            self.resizable(1, 1)

    def countdown(self):
        """
        倒计时
        :return:
        """
        # 倒计时状态开
        self.countdownState = True
        time.sleep(1)
        while self.lbNum.get() > 1:
            self.lbNum.set(self.lbNum.get() - 1)
            time.sleep(1)
        # 隐藏标签
        self.lb.configure(fg="Crimson")
        # 倒计时状态关
        self.countdownState = False


if __name__ == '__main__':
    root = Window()
    root.mainloop()
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐