python+ffmpeg 屏幕录制程序

时间:2024-10-21 10:04:59
import sys import subprocess import tkinter as tk from tkinter import filedialog, messagebox, ttk class ScreenRecorder: def __init__(self, root): self.root = root self.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 = False self.record_process = None self.file_path = None self.play_process = None def 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_path ffmpeg_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 = True self.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 shutdown self.record_process.stdin.flush() # Ensure the command is sent immediately self.record_process.wait() # Wait for the process to finish except BrokenPipeError: pass # If the pipe is broken, the process has already terminated finally: self.record_process = None self.is_recording = False self.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 title file_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()