当前位置: 首页 > news >正文

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.mrgr.cn/news/55010.html

相关文章:

  • 程序崩溃的形式:为什么C++是coredump,而Golang是panic
  • 【JavaEE】——TCP应答报文机制,超时重传机制
  • AI驱动的支持截图或线框图快速生成网页应用的开源项目
  • 【Android】Jetpack入门知识总结(LifeCycle,ViewModel,LiveData,DataBinding等)
  • 【BUG】解决已安装anaconda的pycharm中jupyter服务器中出现的import jieba失败问题
  • 高等数学 5.5 反常积分的审敛法 Γ函数
  • 集创赛比赛细则了解
  • 【数据结构与算法】之单链表反转
  • 【每日一题】24.10.14 - 24.10.20
  • 单链表的经典算法OJ
  • 华为杯”第十三届中国研究生数学建模竞赛-C题:基于无线通信基站的室内三维定位问题
  • SpringCloud
  • process.platform 作用
  • C#基于SkiaSharp实现印章管理(11)
  • 智简魔方业务管理系统v10 好用的IDC业务管理软件
  • 嵌入式元件面试题及参考答案
  • MYSQL的SQL优化
  • PCL 点云配准 GICP算法(精配准)
  • ESP32-IDF 非易失存储 NVS
  • 《深度学习》dlib 人脸应用实例 仿射变换 换脸术
  • 时间复杂度知识点详解重点知识总结
  • 计算机网络—ACL技术和NAT转换
  • Java Exercise
  • 如何进行变基并更新拉取请求
  • 【文献及模型、制图分享】长江中游经济区“水—能源—粮食”系统与城市绿色转型适配性研究
  • 6.2 URDF集成Rviz基本流程