python+ffmpeg 屏幕录制程序

python+ffmpeg 屏幕录制程序

不同平台使用对应的ffmpeg

例如 windows on arm 平台使用这个:
https://github.com/wmx-github/ffmpeg-wos-arm64-build/releases

ScreenRecorder.py :

import sys
import subprocess
import tkinter as tk
from tkinter import filedialog, messagebox, ttkclass ScreenRecorder:def __init__(self, root):self.root = rootself.root.title("Screen Recorder")self.root.geometry("350x200")self.create_widgets()self.load_config()def create_widgets(self):# 创建一个Notebook(标签控件)self.notebook = ttk.Notebook(self.root)# 主界面self.main_frame = ttk.Frame(self.notebook)self.notebook.add(self.main_frame, text='Main')# 配置界面self.config_frame = ttk.Frame(self.notebook)self.notebook.add(self.config_frame, text='Config')# 按钮列表布局button_frame = ttk.Frame(self.main_frame)button_frame.pack(pady=10, fill='x')self.record_button = tk.Button(button_frame, text="Start Recording", command=self.start_recording, width=20)self.record_button.pack(pady=5, fill='x')self.play_button = tk.Button(button_frame, text="Play Video", command=self.play_video, width=20)self.play_button.pack(pady=5, fill='x')# 配置界面组件config_label_frame = ttk.LabelFrame(self.config_frame, text="Configuration")config_label_frame.pack(fill="both", expand="yes", padx=10, pady=10)# FFmpeg路径self.ffmpeg_path_var = tk.StringVar()ffmpeg_label = ttk.Label(config_label_frame, text="FFmpeg Path:")ffmpeg_label.grid(row=0, column=0, padx=5, pady=5, sticky='w')ffmpeg_entry = ttk.Entry(config_label_frame, textvariable=self.ffmpeg_path_var, width=30)ffmpeg_entry.grid(row=0, column=1, padx=5, pady=5)ffmpeg_browse_button = ttk.Button(config_label_frame, text="Browse", command=self.browse_ffmpeg)ffmpeg_browse_button.grid(row=0, column=2, padx=5, pady=5)# 文件保存路径self.save_path_var = tk.StringVar()save_path_label = ttk.Label(config_label_frame, text="Save Path:")save_path_label.grid(row=1, column=0, padx=5, pady=5, sticky='w')save_path_entry = ttk.Entry(config_label_frame, textvariable=self.save_path_var, width=30)save_path_entry.grid(row=1, column=1, padx=5, pady=5)save_path_browse_button = ttk.Button(config_label_frame, text="Browse", command=self.browse_save_path)save_path_browse_button.grid(row=1, column=2, padx=5, pady=5)self.notebook.pack(expand=1, fill='both')# 快捷键self.root.bind('<Control-r>', lambda event: self.start_recording())self.root.bind('<Control-p>', lambda event: self.play_video())self.is_recording = Falseself.record_process = Noneself.file_path = Noneself.play_process = Nonedef load_config(self):# 这里可以加载配置文件或使用默认值self.ffmpeg_path_var.set("ffmpeg")self.save_path_var.set(".")def browse_ffmpeg(self):path = filedialog.askopenfilename(filetypes=[("Executable files", "*.exe")])if path:self.ffmpeg_path_var.set(path)def browse_save_path(self):path = filedialog.askdirectory()if path:self.save_path_var.set(path)def start_recording(self):if not self.is_recording:file_path = filedialog.asksaveasfilename(initialdir=self.save_path_var.get(), defaultextension=".mp4", filetypes=[("MP4 Files", "*.mp4")])if file_path:self.file_path = file_pathffmpeg_path = self.ffmpeg_path_var.get()self.record_process = subprocess.Popen([ffmpeg_path,"-f", "gdigrab","-framerate", "25","-i", "desktop","-c:v", "libx264","-preset", "ultrafast","-crf", "0",file_path],stdin=subprocess.PIPE  # Create a pipe for stdin)self.is_recording = Trueself.record_button.config(text="Stop Recording")else:self.stop_recording()def stop_recording(self):if self.record_process and self.is_recording:try:self.record_process.stdin.write(b'q')  # Send 'q' to ffmpeg to request a graceful shutdownself.record_process.stdin.flush()  # Ensure the command is sent immediatelyself.record_process.wait()  # Wait for the process to finishexcept BrokenPipeError:pass  # If the pipe is broken, the process has already terminatedfinally:self.record_process = Noneself.is_recording = Falseself.record_button.config(text="Start Recording")def play_video(self):file_path = filedialog.askopenfilename(initialdir=self.save_path_var.get(), defaultextension=".mp4", filetypes=[("MP4 Files", "*.mp4"), ("All Files", "*.*")])if file_path:ffmpeg_path = self.ffmpeg_path_var.get()self.play_process = subprocess.Popen([ffmpeg_path.replace('ffmpeg', 'ffplay'),"-autoexit",  # Automatically exit when the video ends"-x", "800",  # Set initial window width"-y", "600",  # Set initial window height"-window_title", "Video Player",  # Set window titlefile_path])def on_closing(self):if self.record_process and self.is_recording:if messagebox.askokcancel("Quit", "Recording is in progress. Do you want to stop recording and quit?"):self.stop_recording()self.root.destroy()elif self.play_process and self.play_process.poll() is None:if messagebox.askokcancel("Quit", "Video is playing. Do you want to stop playback and quit?"):self.play_process.terminate()self.play_process.wait()self.root.destroy()else:self.root.destroy()if __name__ == "__main__":root = tk.Tk()app = ScreenRecorder(root)root.protocol("WM_DELETE_WINDOW", app.on_closing)root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/453607.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库系统概论】第3章 关系数据库标准语言SQL(一)数据定义(超详细)

教材&#xff1a; 数据库系统概论&#xff08;第6版&#xff09;王珊,杜小勇,陈红编著 目录 一、SQL概述 1.1 SQL 的产生与发展 1.2 SQL的特点 1.3 SQL的基本概念 二、数据定义 2.1 数据库的定义 2.2 数据表的定义 2.3 模式的定义 一、SQL概述 1974年IBM为关系DBMS设…

Docker 搭建mysql

拉取mysql镜像 docker pull mysql # 拉取镜像 [rooteason ~]# docker pull mysql Using default tag: latest latest: Pulling from library/mysql 72a69066d2fe: Pull complete 93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d…

用HTML构建酷炫的文件上传下载界面

1. 基础HTML结构 首先&#xff0c;我们构建一个基本的HTML结构&#xff0c;包括一个表单用于文件上传&#xff0c;以及一个列表用于展示已上传文件&#xff1a; HTML <!DOCTYPE html> <html> <head><title>酷炫文件上传下载</title><link …

分布式ID生成策略

文章目录 分布式ID必要性1.UUID2.基于DB的自增主键方案3.数据库多主模式4.号段模式5.Redis6.Zookeeper7.ETCD8.雪花算法9.百度(Uidgenerator)10.美团(Leaf)11.滴滴(TinyID) 分布式ID必要性 业务量小于500W的时候单独一个mysql即可提供服务&#xff0c;再大点的时候就进行读写分…

浏览器播放rtsp视频流解决方案

方案一: html5 websocket_rtsp_proxy 实现视频流直播 实现原理 实现步骤 服务器安装streamedian服务器 客户端通过video标签播放 <video id"test_video" controls autoplay></video><script src"free.player.1.8.4.js"></script&g…

openresty通过header_filter_by_lua记录特定的请求头和特定的响应头到日志文件

有时我们希望记录特定的请求头信息和特定的响应头信息,以便能够通过关联请求信息和响应头信息,来实现记录请求和响应的对应关系。这里通过逐步尝试和优化的方式进行尝试。具体包括将需要的请求头和响应头组织到一条日志记录,输出到单独的错误日志文件记录等的配置尝试。 1.…

HAL+M4学习记录_8

一、TIM的HAL库用法 这里记录学习HAL库开发TIM 1.1 定时中断基本结构 这里给出定时中断的基本结构 基本步骤如下 开启时钟选择时基单元时钟源配置时基单元配置输出中断控制&#xff0c;允许更新中断输出到NVIC配置NVIC&#xff0c;打开定时器中断通道运行控制编写中断服务函…

为什么九齐单片机中不能使用bit?

如果开发环境不支持bit 定义static unsigned char task_720ms_flag 0;还可以用什么方式替代bit定义标志&#xff0c;使其占用内存空间小。 如果开发环境不支持位定义&#xff0c;可以使用 unsigned char 的多个状态位来替代。可以将多个标志合并到一个 unsigned char 中&…

Vue - Element 选择器 el-select 既可以选择下拉又可以手动输入文本功能(手动输入的值只能是数字 并且支持4位小数)

Vue - Element 选择器 el-select 既可以选择下拉又可以手动输入文本功能&#xff08;手动输入的值只能是数字 并且支持4位小数&#xff09; 备注 filterable 下拉框开启快速搜索功能 no-match-text 当输入的内容在下拉框中找不到时&#xff1b;下拉框提示的文字 handFocus 触发…

软件测试快速入门:测试对象、过程模型、生命周期与测试用例

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

redis集群介绍

Redis集群是一种分布式存储系统&#xff0c;它通过将数据分散存储在多个Redis节点上来实现可扩展性和高可用性。每个节点都是一个独立的Redis服务器实例&#xff0c;它们通过网络相互连接&#xff0c;共同协作以提供数据服务。 在Redis集群中&#xff0c;数据被划分为多个槽&am…

【Vercel】Vercel静态部署踩坑

背景 在现代的软件开发中&#xff0c;自动化部署是一个不可或缺的环节。Vercel作为一个流行的前端部署平台&#xff0c;提供了与GitHub的无缝集成&#xff0c;使得开发者能够在每次提交代码后自动触发部署流程。然而&#xff0c;自动化部署过程中可能会遇到一些挑战&#xff0…

自动化工具:Ansible

目录 一、运维自动化工具有哪些 二、Ansible 概述 1、Ansible 概念 2、Ansible 特点 3、Ansible 工作流程 三、安装部署Ansible 1、环境部署 2、管理节点安装 Ansible 3、查看Ansible相关文件 4、配置主机清单 5、免密管理 ssh-keygen 5.1、测试连通性 5.2、简洁输…

IPC通信-消息队列

使用消息队列实现两个进程的相互通信 #include<myhead.h>//定义结构体存储信息种类和信息正文 typedef struct {long mtype; //信息类型char mtext[128]; //信息正文 }msgbuf;//宏定义信息正文的大小 #define MESIZE sizeof(msgbuf)-sizeof(long)typedef struct sockad…

vscode:创建fastapi项目

1.选择py解释器 或者 uvicorn main:app --reload

java游戏网站源码

题目&#xff1a;java游戏网站源码 编号B22A390 主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Mysql|大数据|SSM|SpringBoot|Vue|Jsp|MYSQL等)、学习资料、JAVA源码、技术咨询 文末联系获取 感兴趣可以先收藏起来&#xff0c;以防走丢&#xff0c;有任何选题、文档编…

雷池WAF自动化实现安全运营实操案例终极篇

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Unity DOTS中的Archetype与Chunk

Unity DOTS中的Archetype与Chunk 在Unity中&#xff0c;archetype&#xff08;原型&#xff09;用来表示一个world里具有相同component类型组合的entity。也就是说&#xff0c;相同component类型的entity在Unity内部会存储到一起&#xff0c;共享同一个archetype。 使用这样的设…

React是如何工作的?

从编写组件到最后屏幕生成界面&#xff0c;如上图所示&#xff0c;我们现在需要知道的就是后面几步是如何运行的。 概述 这张图解释了 React 渲染过程的几个阶段&#xff1a; 渲染触发&#xff1a;通过更新某处的状态来触发渲染。渲染阶段&#xff1a;React 调用组件函数&…

智能优化算法-生物地理学算法(BBO)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 生物地理学优化算法 (Biogeography-Based Optimization, BBO) 是一种基于生物地理学原理的元启发式优化算法&#xff0c;由Dan Simon于2008年提出。BBO通过模拟物种在不同栖息地之间的迁移过程来搜索最优解&…