视频万能转换器(源码)
import os import sys import tkinter as tk from tkinter import filedialog, ttk import subprocess import threading import datetime class VideoConverterApp: def __init__(self, root): self.root = root self.root.title("万能高清转换器-三松礼品-强哥出品必属精品") # 转换参数预设 self.presets = { '高清1080p': '-c:v libx264 -crf 23 -preset medium -vf scale=1920:1080 -c:a aac -b:a 192k', '高清720p': '-c:v libx264 -crf 23 -preset fast -vf scale=1280:720 -c:a aac -b:a 128k', '原画质': '-c:v libx264 -crf 18 -preset slow -c:a aac -b:a 256k' } # 获取 `ffmpeg` 相关文件的路径 self.ffmpeg_path = self.get_ffmpeg_path() self.ffplay_path = self.get_ffplay_path() self.ffprobe_path = self.get_ffprobe_path() # 创建 GUI 界面 self.create_widgets() # 当前转换进程 self.current_process = None def get_ffmpeg_path(self): """ 获取 ffmpeg.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffmpeg.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffmpeg.exe") def get_ffplay_path(self): """ 获取 ffplay.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffplay.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffplay.exe") def get_ffprobe_path(self): """ 获取 ffprobe.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffprobe.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffprobe.exe") def create_widgets(self): # 文件选择 tk.Label(self.root, text="选择文件或文件夹:").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.input_entry = tk.Entry(self.root, width=50) self.input_entry.grid(row=0, column=1, padx=5, pady=5) tk.Button(self.root, text="浏览", command=self.select_input_file_or_folder).grid(row=0, column=2, padx=5, pady=5) # 输出目录 tk.Label(self.root, text="输出目录:").grid(row=1, column=0, padx=5, pady=5, sticky="w") self.output_entry = tk.Entry(self.root, width=50) self.output_entry.grid(row=1, column=1, padx=5, pady=5) self.output_entry.insert(0, os.getcwd()) # 默认当前目录 tk.Button(self.root, text="浏览", command=self.select_output_dir).grid(row=1, column=2, padx=5, pady=5) # 预设选择 tk.Label(self.root, text="转换预设:").grid(row=2, column=0, padx=5, pady=5, sticky="w") self.preset_var = tk.StringVar() self.preset_combobox = ttk.Combobox(self.root, textvariable=self.preset_var, values=list(self.presets.keys())) self.preset_combobox.current(0) self.preset_combobox.grid(row=2, column=1, padx=5, pady=5, sticky="w") # 输出格式选择 tk.Label(self.root, text="选择输出格式:").grid(row=3, column=0, padx=5, pady=5, sticky="w") self.format_var = tk.StringVar() self.format_combobox = ttk.Combobox(self.root, textvariable=self.format_var, values=[".mp4", ".avi", ".mkv", ".mov", ".flv"]) self.format_combobox.current(0) self.format_combobox.grid(row=3, column=1, padx=5, pady=5, sticky="w") # 进度条 self.progress = ttk.Progressbar(self.root, orient="horizontal", length=400, mode="determinate") self.progress.grid(row=4, column=0, columnspan=3, padx=5, pady=5) # 日志框 self.log_text = tk.Text(self.root, height=10, width=60) self.log_text.grid(row=5, column=0, columnspan=3, padx=5, pady=5) # 转换按钮 self.start_conversion_button = tk.Button(self.root, text="开始转换", command=self.start_conversion) self.start_conversion_button.grid(row=6, column=2, padx=5, pady=10) # 取消按钮 tk.Button(self.root, text="取消转换", command=self.cancel_conversion).grid(row=6, column=0, padx=5, pady=5) def select_input_file_or_folder(self): input_path = filedialog.askopenfilename(filetypes=[("视频文件", "*.ts;*.mp4;*.avi;*.mkv;*.mov;*.flv")]) if not input_path: input_path = filedialog.askdirectory() self.input_entry.delete(0, tk.END) self.input_entry.insert(0, input_path) def select_output_dir(self): dir_path = filedialog.askdirectory() self.output_entry.delete(0, tk.END) self.output_entry.insert(0, dir_path) def log_message(self, message): self.log_text.insert(tk.END, message + "\n") self.log_text.see(tk.END) def start_conversion(self): """ 开始转换时禁用按钮,防止重复点击 """ self.start_conversion_button.config(state=tk.DISABLED) input_file = self.input_entry.get() output_dir = self.output_entry.get() output_format = self.format_var.get() preset = self.presets[self.preset_var.get()] output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(input_file))[0] + "_converted" + output_format) ffmpeg_cmd = [self.ffmpeg_path, "-i", input_file, "-y"] + preset.split() + [output_file] self.log_message(f"执行命令: {' '.join(ffmpeg_cmd)}") threading.Thread(target=self.run_ffmpeg_silently, args=(ffmpeg_cmd, output_file)).start() def run_ffmpeg_silently(self, cmd, output_file): """ 运行 ffmpeg 并隐藏窗口,同时在转换结束后恢复按钮 """ startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo) out, err = process.communicate() # 获取输出和错误信息 process.wait() if process.returncode == 0: self.log_message(f"转换完成,文件保存在: {output_file}") else: self.log_message(f"错误: {err.decode()}") # 转换完成后恢复按钮 self.start_conversion_button.config(state=tk.NORMAL) def cancel_conversion(self): if self.current_process: self.current_process.terminate() self.log_message("转换已取消") self.start_conversion_button.config(state=tk.NORMAL) # 恢复按钮状态 if __name__ == "__main__": root = tk.Tk() app = VideoConverterApp(root) root.mainloop() """ pyinstaller --onefile --add-data "ffmpeg.exe;." --add-data "ffplay.exe;." --add-data "ffprobe.exe;." --noconsole 222.py """
带日期限制的代码:
import os import sys import tkinter as tk from tkinter import filedialog, ttk import subprocess import threading import datetime import requests class VideoConverterApp: def __init__(self, root): self.root = root self.root.title("万能高清转换器-三松礼品-强哥出品必属精品") # 设置程序的时间限制(比如:2025年2月12日 18:00) self.restricted_time = datetime.datetime(2025, 12, 30, 18, 0, 0) # 获取当前互联网时间并比较 if not self.check_time_allowed(): self.show_restricted_message() return # 转换参数预设 self.presets = { '高清1080p': '-c:v libx264 -crf 23 -preset medium -vf scale=1920:1080 -c:a aac -b:a 192k', '高清720p': '-c:v libx264 -crf 23 -preset fast -vf scale=1280:720 -c:a aac -b:a 128k', '原画质': '-c:v libx264 -crf 18 -preset slow -c:a aac -b:a 256k' } # 获取 `ffmpeg` 相关文件的路径 self.ffmpeg_path = self.get_ffmpeg_path() self.ffplay_path = self.get_ffplay_path() self.ffprobe_path = self.get_ffprobe_path() # 创建 GUI 界面 self.create_widgets() # 当前转换进程 self.current_process = None def get_ffmpeg_path(self): """ 获取 ffmpeg.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffmpeg.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffmpeg.exe") def get_ffplay_path(self): """ 获取 ffplay.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffplay.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffplay.exe") def get_ffprobe_path(self): """ 获取 ffprobe.exe 的路径 """ if getattr(sys, 'frozen', False): return os.path.join(sys._MEIPASS, "ffprobe.exe") return os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffprobe.exe") def check_time_allowed(self): """ 获取当前互联网时间,并与限制时间进行比较 """ try: response = requests.get('http://worldtimeapi.org/api/timezone/Etc/UTC') data = response.json() current_time = datetime.datetime.fromisoformat(data['datetime'].replace('Z', '+00:00')) if current_time > self.restricted_time: return False # 超过限制时间,禁止使用 return True except requests.RequestException: # 如果无法获取互联网时间,默认允许使用 return True def show_restricted_message(self): """ 显示程序禁止使用的消息 """ tk.Label(self.root, text="程序禁止使用:超过限制时间", font=("Arial", 16)).pack(padx=5, pady=5) self.root.after(5000, self.root.quit) # 5秒后自动关闭程序 def create_widgets(self): # 文件选择 tk.Label(self.root, text="选择文件或文件夹:").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.input_entry = tk.Entry(self.root, width=50) self.input_entry.grid(row=0, column=1, padx=5, pady=5) tk.Button(self.root, text="浏览", command=self.select_input_file_or_folder).grid(row=0, column=2, padx=5, pady=5) # 输出目录 tk.Label(self.root, text="输出目录:").grid(row=1, column=0, padx=5, pady=5, sticky="w") self.output_entry = tk.Entry(self.root, width=50) self.output_entry.grid(row=1, column=1, padx=5, pady=5) self.output_entry.insert(0, os.getcwd()) # 默认当前目录 tk.Button(self.root, text="浏览", command=self.select_output_dir).grid(row=1, column=2, padx=5, pady=5) # 预设选择 tk.Label(self.root, text="转换预设:").grid(row=2, column=0, padx=5, pady=5, sticky="w") self.preset_var = tk.StringVar() self.preset_combobox = ttk.Combobox(self.root, textvariable=self.preset_var, values=list(self.presets.keys())) self.preset_combobox.current(0) self.preset_combobox.grid(row=2, column=1, padx=5, pady=5, sticky="w") # 输出格式选择 tk.Label(self.root, text="选择输出格式:").grid(row=3, column=0, padx=5, pady=5, sticky="w") self.format_var = tk.StringVar() self.format_combobox = ttk.Combobox(self.root, textvariable=self.format_var, values=[".mp4", ".avi", ".mkv", ".mov", ".flv"]) self.format_combobox.current(0) self.format_combobox.grid(row=3, column=1, padx=5, pady=5, sticky="w") # 进度条 self.progress = ttk.Progressbar(self.root, orient="horizontal", length=400, mode="determinate") self.progress.grid(row=4, column=0, columnspan=3, padx=5, pady=5) # 日志框 self.log_text = tk.Text(self.root, height=10, width=60) self.log_text.grid(row=5, column=0, columnspan=3, padx=5, pady=5) # 转换按钮 self.start_conversion_button = tk.Button(self.root, text="开始转换", command=self.start_conversion) self.start_conversion_button.grid(row=6, column=2, padx=5, pady=10) # 取消按钮 tk.Button(self.root, text="取消转换", command=self.cancel_conversion).grid(row=6, column=0, padx=5, pady=5) def select_input_file_or_folder(self): input_path = filedialog.askopenfilename(filetypes=[("视频文件", "*.ts;*.mp4;*.avi;*.mkv;*.mov;*.flv")]) if not input_path: input_path = filedialog.askdirectory() self.input_entry.delete(0, tk.END) self.input_entry.insert(0, input_path) def select_output_dir(self): dir_path = filedialog.askdirectory() self.output_entry.delete(0, tk.END) self.output_entry.insert(0, dir_path) def log_message(self, message): self.log_text.insert(tk.END, message + "\n") self.log_text.see(tk.END) def start_conversion(self): """ 开始转换时禁用按钮,防止重复点击 """ self.start_conversion_button.config(state=tk.DISABLED) input_file = self.input_entry.get() output_dir = self.output_entry.get() output_format = self.format_var.get() preset = self.presets[self.preset_var.get()] output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(input_file))[0] + "_converted" + output_format) ffmpeg_cmd = [self.ffmpeg_path, "-i", input_file, "-y"] + preset.split() + [output_file] self.log_message(f"执行命令: {' '.join(ffmpeg_cmd)}") threading.Thread(target=self.run_ffmpeg_silently, args=(ffmpeg_cmd, output_file)).start() def run_ffmpeg_silently(self, cmd, output_file): """ 运行 ffmpeg 并隐藏窗口,同时在转换结束后恢复按钮 """ startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo) out, err = process.communicate() # 获取输出和错误信息 process.wait() if process.returncode == 0: self.log_message(f"转换完成,文件保存在: {output_file}") else: self.log_message(f"错误: {err.decode()}") # 转换完成后恢复按钮 self.start_conversion_button.config(state=tk.NORMAL) def cancel_conversion(self): if self.current_process: self.current_process.terminate() self.log_message("转换已取消") self.start_conversion_button.config(state=tk.NORMAL) # 恢复按钮状态 if __name__ == "__main__": root = tk.Tk() app = VideoConverterApp(root) root.mainloop() """ pyinstaller --onefile --add-data "ffmpeg.exe;." --add-data "ffplay.exe;." --add-data "ffprobe.exe;." --noconsole 222.py """

浙公网安备 33010602011771号