[Python] 纯文本查看 复制代码
import os
import math
from tkinter import *
from tkinter import filedialog, messagebox
from moviepy.editor import VideoFileClip
from threading import Thread
class VideoSplitter:
def __init__(self, root):
self.root = root
self.root.title("视频无损批量分割器 v1.0")
self.root.geometry("500x400")
# 界面组件
self.create_widgets()
self.running = False # 任务状态标志
def create_widgets(self):
"""创建GUI界面组件"""
# 文件选择区域
Label(self.root, text="目标文件/文件夹:").pack(pady=5)
self.path_entry = Entry(self.root, width=50)
self.path_entry.pack(pady=5)
Button(self.root, text="选择文件", command=self.select_file).pack(side=LEFT, padx=20)
Button(self.root, text="选择文件夹", command=self.select_folder).pack(side=LEFT)
# 参数设置区域
Label(self.root, text="分割份数:").pack(pady=10)
self.num_entry = Entry(self.root, width=10)
self.num_entry.pack()
# 进度显示
self.status = Label(self.root, text="就绪", relief=SUNKEN, anchor=W)
self.status.pack(side=BOTTOM, fill=X)
# 控制按钮
self.start_btn = Button(self.root, text="开始分割", command=self.start_process)
self.start_btn.pack(pady=20)
def select_file(self):
"""选择单个视频文件"""
path = filedialog.askopenfilename(filetypes=[("视频文件", "*.mp4 *.avi *.mov *.mkv")])
self.path_entry.delete(0, END)
self.path_entry.insert(0, path)
def select_folder(self):
"""选择包含视频的文件夹"""
path = filedialog.askdirectory()
self.path_entry.delete(0, END)
self.path_entry.insert(0, path)
def split_video(self, input_path, output_dir, num_segments):
"""执行视频分割的核心函数"""
try:
clip = VideoFileClip(input_path)
total_duration = clip.duration
segment_duration = total_duration / num_segments
# 创建输出目录
base_name = os.path.splitext(os.path.basename(input_path))[0]
video_output_dir = os.path.join(output_dir, base_name)
os.makedirs(video_output_dir, exist_ok=True)
# 无损分割处理
for i in range(num_segments):
start_time = i * segment_duration
end_time = min((i+1)*segment_duration, total_duration)
subclip = clip.subclip(start_time, end_time)
output_path = os.path.join(video_output_dir,
f"{base_name}_part{i+1}.mp4")
# 使用默认编码参数,不再指定codec
subclip.write_videofile(output_path, threads=4)
self.update_status(f"处理中: {os.path.basename(input_path)} - 第{i+1}/{num_segments}段")
clip.close()
return True
except Exception as e:
messagebox.showerror("错误", f"处理失败: {str(e)}")
return False
def process_files(self):
"""批量处理主逻辑"""
input_path = self.path_entry.get()
num_segments = int(self.num_entry.get())
output_dir = os.path.join(os.path.dirname(input_path), "Split_Output")
if os.path.isfile(input_path):
files = [input_path]
elif os.path.isdir(input_path):
files = [os.path.join(input_path, f) for f in os.listdir(input_path)
if f.lower().endswith(('.mp4', '.avi', '.mov', '.mkv'))]
os.makedirs(output_dir, exist_ok=True)
for idx, file_path in enumerate(files):
if not self.running: break
self.update_status(f"正在处理第 {idx+1}/{len(files)} 个文件")
self.split_video(file_path, output_dir, num_segments)
self.running = False
self.update_status("任务完成")
messagebox.showinfo("完成", f"所有视频已分割完成!\n输出目录: {output_dir}")
def start_process(self):
"""启动处理线程"""
if not self.running:
if not self.validate_input():
return
self.running = True
self.start_btn.config(text="停止分割")
Thread(target=self.process_files).start()
else:
self.running = False
self.start_btn.config(text="开始分割")
def validate_input(self):
"""验证输入参数有效性"""
try:
int(self.num_entry.get())
except:
messagebox.showerror("错误", "分割份数必须是整数")
return False
return True
def update_status(self, message):
"""更新状态栏"""
self.status.config(text=message)
self.root.update()
if __name__ == "__main__":
root = Tk()
app = VideoSplitter(root)
root.mainloop()