import tkinter as tk
from tkinter import filedialog, messagebox, Label, Entry, Button
import os
import hashlib
import random
import shutil
import boto3
import cv2
from moviepy.editor import VideoFileClip
win7_window = None # 用于保存 Win7 窗口的引用
win10_window = None
win11_window = None
win12_window = None
win01_window = None
def show_selected_key():
text_box.delete(1.0, tk.END)
text_box.insert(tk.END, 'win7 key: 123456')
############ login ############
def check_password():
password = password_entry.get()
if password == "18503":
menubar.entryconfig("Open", state="normal")
menubar.entryconfig("Other", state="normal")
menubar.entryconfig("Close", state="normal")
password_entry.delete(0, tk.END) # 清空密码输入框
password_label.config(state=tk.DISABLED) # 禁用密码标签
password_entry.config(state=tk.DISABLED) # 禁用密码输入框
confirm_button.config(state=tk.DISABLED) # 禁用确认按钮
messagebox.showinfo("完成!", "已经解锁所有功能!")
else:
messagebox.showerror("密码错误", "请输入正确密码!")
############ text to speech ############
aws_access_key_id = 'AKIA47CRUYAIT5KL3DXG'
aws_secret_access_key = '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'
region_name = 'eu-west-1'
available_voices = {
"Zhiyu-普通话(女)": "Zhiyu",
"Hiujin-广东话(女)": "Hiujin",
"Joanna-英文-(女)": "Joanna"
}
def save_completed_dialog(save_path):
messagebox.showinfo("完成!", f"储存路径:\n{save_path}")
def generate_mp3():
text = entry.get()
polly_client = boto3.client('polly', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, region_name=region_name)
response = polly_client.synthesize_speech(
Text=text,
OutputFormat='mp3',
VoiceId=selected_voice.get(),
Engine='neural'
)
save_path = filedialog.asksaveasfilename(defaultextension=".mp3", filetypes=[("MP3 files", "*.mp3")])
if save_path:
with open(save_path, 'wb') as file:
file.write(response['AudioStream'].read())
print("Speech saved as", save_path)
save_completed_dialog(save_path)
############ text to speech ############
############ MP4视频帧提取及分割工具 ############
def open_file():
file_path = filedialog.askopenfilename(filetypes=[("Video Files", "*.mp4")])
if file_path:
entry_file_path.delete(0, tk.END)
entry_file_path.insert(tk.END, file_path)
def is_file_path_valid(file_path):
if not file_path.strip():
messagebox.showerror("错误", "请输入正确的文件路径!")
return False
return True
def split_video():
file_path = entry_file_path.get()
start_time = entry_start_time.get()
end_time = entry_end_time.get()
output_folder = "output"
if not is_file_path_valid(file_path):
return
if not os.path.exists(output_folder):
os.makedirs(output_folder)
if file_path and start_time and end_time:
try:
clip = VideoFileClip(file_path).subclip(start_time, end_time)
output_path = f"{output_folder}/output.mp4" # 设置输出文件路径
clip.write_videofile(output_path)
#lbl_status.config(text="分割完成!")
messagebox.showinfo("Info", "分割完成!")
except Exception as e:
#lbl_status.config(text=str(e))
messagebox.showerror("错误", text=str(e))
else:
#lbl_status.config(text="请填写影片的路径,剪辑开始及结束时间!")
messagebox.showerror("错误", "请输入正确的影片路径,剪辑开始及结束时间!")
def extract_frames():
file_path = entry_file_path.get()
start_time_str = entry_start_time.get()
end_time_str = entry_end_time.get()
if not is_file_path_valid(file_path):
return
if file_path and start_time_str and end_time_str:
start_time = sum(int(x) * 60 ** i for i, x in enumerate(reversed(start_time_str.split(":"))))
end_time = sum(int(x) * 60 ** i for i, x in enumerate(reversed(end_time_str.split(":"))))
video_capture = cv2.VideoCapture(file_path)
video_capture.set(cv2.CAP_PROP_FPS, 30)
output_folder = "output"
if not os.path.exists(output_folder):
os.makedirs(output_folder)
saved_frame_name = 0
while video_capture.isOpened():
frame_is_read, frame = video_capture.read()
if frame_is_read:
# 保存指定时间范围内的帧
current_time = video_capture.get(cv2.CAP_PROP_POS_MSEC) / 1000
if start_time <= current_time <= end_time:
cv2.imwrite(f"{output_folder}/frame{str(saved_frame_name)}.jpg", frame)
saved_frame_name += 1
elif current_time > end_time:
break
else:
print("Couldn't read the frame anymore!")
break
video_capture.release()
messagebox.showinfo("Info", "提取帧成功! 已经保存到output文件夹。")
else:
messagebox.showerror("错误", "请输入正确的影片路径,剪辑开始及结束时间!")
def start_execution():
if choice.get() == 1:
split_video()
elif choice.get() == 2:
extract_frames()
else:
messagebox.showerror("错误", "请输入需要打开的文件路径,开始及结束时间,选择对应的操作!")
############ MP4视频帧提取及分割工具 ############
############ MD5 Modifier ############
def calculate_md5(file_path):
hash_md5 = hashlib.md5()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def modify_mp4(file_path):
with open(file_path, "ab") as f:
f.write(os.urandom(random.randint(100, 1000)))
def process_files(input_folder, output_folder, text_output):
if not input_folder or not output_folder:
messagebox.showerror("错误", "请选择输入及输出文件夹的路径!")
return
if input_folder == output_folder:
messagebox.showerror("错误", "输入的文件夹路径不能与来源相同!")
return
if not output_folder:
messagebox.showerror("错误", "请选择输出视频的文件夹路径!")
return
mp4_files = [f for f in os.listdir(input_folder) if f.endswith(".mp4")]
if not mp4_files:
messagebox.showinfo("提示", "输入文件夹中没有找到 *.mp4 档案可以处理!")
return
if not os.path.exists(output_folder):
os.makedirs(output_folder)
text_output.delete('1.0', tk.END)
for file_name in os.listdir(input_folder):
if file_name.endswith(".mp4"):
input_file_path = os.path.join(input_folder, file_name)
output_file_path = os.path.join(output_folder, file_name)
original_md5 = calculate_md5(input_file_path)
modify_mp4(input_file_path)
modified_md5 = calculate_md5(input_file_path)
shutil.copyfile(input_file_path, output_file_path)
text_output.insert(tk.END, f"文件名称: {file_name}\n")
text_output.insert(tk.END, f"原本的MD5: {original_md5}\n")
text_output.insert(tk.END, f"修改后的MD5: {modified_md5}\n")
text_output.insert(tk.END, f"储存路径: {output_file_path}\n\n")
messagebox.showinfo("操作完成", "所有视频文件的MD5已被修改完毕!")
input_folder = ""
output_folder = ""
def open_folder():
global input_folder
input_folder = filedialog.askdirectory(parent=root, title="选择放有视频的文件夹")
input_folder_label.config(text=input_folder)
def select_output_folder():
global output_folder
output_folder = filedialog.askdirectory(parent=root, title="选择输出视频的文件夹")
output_folder_label.config(text=output_folder)
############ MD5 Modifier ############
def close_win7_window():
global win7_window
win7_window.destroy()
win7_window = None # 当 Win7 窗口关闭时,重置窗口变量
def close_win10_window():
global win10_window
win10_window.destroy()
win10_window = None
def close_win11_window():
global win11_window
win11_window.destroy()
win11_window = None
def close_win12_window():
global win12_window
win12_window.destroy()
win12_window = None
def close_win01_window():
global win01_window
win01_window.destroy()
win01_window = None
def show_win7_window():
global win7_window
if win7_window is None: # 如果 Win7 窗口尚未打开
win7_window = tk.Toplevel(root)
win7_window.geometry("720x180")
win7_window.title("Keygen")
win7_window.resizable(False, False)
global text_box # 在函数内部使用全局的 text_box 变量
text_box = tk.Text(win7_window, height=10, width=50)
text_box.place(relx=0.5, rely=0.5, anchor="center")
button = tk.Button(win7_window, text="Show Key", command=show_selected_key)
button.place(relx=0.175, rely=0.5, anchor="center")
win7_window.protocol("WM_DELETE_WINDOW", close_win7_window) # 监听窗口关闭事件
def show_win10_window():
global win10_window
if win10_window is None:
win10_window = tk.Toplevel(root)
win10_window.geometry("600x460")
win10_window.title("张燕的MP4视频MD5修改器")
win10_window.resizable(False, False)
input_folder_btn = tk.Button(win10_window, text="打开放有视频的文件夹", command=open_folder)
input_folder_btn.pack()
global input_folder_label
input_folder_label = tk.Label(win10_window, text="Input Folder: ")
input_folder_label.pack()
output_folder_btn = tk.Button(win10_window, text="选择输出视频的文件夹", command=select_output_folder)
output_folder_btn.pack()
global output_folder_label
output_folder_label = tk.Label(win10_window, text="Output Folder: ")
output_folder_label.pack()
text_output = tk.Text(win10_window)
text_output.pack()
process_btn = tk.Button(win10_window, text="更改MP4视频文件MD5",
command=lambda: process_files(input_folder, output_folder, text_output))
process_btn.pack()
win10_window.protocol("WM_DELETE_WINDOW", close_win10_window)
win10_window.mainloop()
def show_win11_window():
global win11_window
if win11_window is None:
win11_window = tk.Toplevel(root)
win11_window.geometry("500x150")
win11_window.title("《张燕的AI自然朗读机》")
win11_window.resizable(False, False)
label = tk.Label(win11_window, text="请输入需要朗读的文本")
label.pack()
global entry
entry = tk.Entry(win11_window, width=50)
entry.pack()
global selected_voice
selected_voice = tk.StringVar(value="Zhiyu")
for voice_name in available_voices:
tk.Radiobutton(win11_window, text=voice_name, variable=selected_voice, value=available_voices[voice_name]).pack()
button = tk.Button(win11_window, text="生成 *.MP3", command=generate_mp3)
button.pack()
win11_window.protocol("WM_DELETE_WINDOW", close_win11_window)
win11_window.mainloop()
def show_win12_window():
global win12_window
if win12_window is None:
win12_window = tk.Toplevel(root)
win12_window.geometry("350x200")
win12_window.title("《张燕的MP4视频帧提取及分割工具》")
win12_window.resizable(False, False)
# 打开文件按钮
btn_open_file = tk.Button(win12_window, text="打开MP4文件", command=open_file)
btn_open_file.pack()
# 文件路径输入框
global entry_file_path
entry_file_path = tk.Entry(win12_window)
entry_file_path.pack()
# 开始时间输入框
Label(win12_window, text="开始时间(秒)").pack()
global entry_start_time
entry_start_time = Entry(win12_window)
entry_start_time.pack()
# 结束时间输入框
Label(win12_window, text="结束时间(秒)").pack()
global entry_end_time
entry_end_time = Entry(win12_window)
entry_end_time.pack()
# 创建Radio Button的变量
global choice
choice = tk.IntVar()
# 创建一个 Frame 来放置 radio_button1 和 radio_button2
radio_frame = tk.Frame(win12_window)
radio_frame.pack()
radio_button1 = tk.Radiobutton(radio_frame, text="分割MP4视频", variable=choice, value=1)
radio_button1.pack(side="left")
radio_button2 = tk.Radiobutton(radio_frame, text="提取MP4视频图片", variable=choice, value=2)
radio_button2.pack(side="left")
start_button = tk.Button(win12_window, text="开始执行", command=start_execution)
start_button.pack()
# 状态标签
lbl_status = tk.Label(win12_window)
lbl_status.pack()
win12_window.protocol("WM_DELETE_WINDOW", close_win12_window)
win12_window.mainloop()
def show_win01_window():
global win01_window
if win01_window is None:
win01_window = tk.Toplevel(root)
key_label = tk.Label(win01_window, text="Win01 Key: ttttyyyy678910")
key_label.pack()
win01_window.protocol("WM_DELETE_WINDOW", close_win01_window)
win01_window.mainloop()
############ Main Window ############
root = tk.Tk()
root.geometry("545x265")
root.title("《张燕的视频工具库》")
root.resizable(False, False)
background_image = tk.PhotoImage(file="m.png")
background_label = tk.Label(root, image=background_image)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
password_label = tk.Label(root, text="请输入密码以解锁功能菜单:", fg="red", bg="yellow", font=("Arial", 12, "bold")) # 设置背景色为黄色,字体为12号粗体
password_label.pack()
password_entry = tk.Entry(root, show="$", width=20)
password_entry.pack()
confirm_button = tk.Button(root, text="确认", command=check_password, width=20, fg="purple", bg="light green", font=("Arial", 10, "bold"))
confirm_button.pack()
password_entry.bind("<Return>", lambda event: check_password())
confirm_button.bind("<Return>", lambda event: check_password())
# 将 password_label,password_entry 和 confirm_button 放到视窗 y 的中央
root.update_idletasks()
win_height = root.winfo_height()
y_position = (win_height - (password_label.winfo_height() + password_entry.winfo_height() + confirm_button.winfo_height())) // 2
password_label.place(relx=0.5, rely=0.4, anchor="center")
password_entry.place(relx=0.5, rely=0.5, anchor="center")
confirm_button.place(relx=0.5, rely=0.62, anchor="center")
menubar = tk.Menu(root)
filemenu = tk.Menu(menubar, tearoff=0, activebackground='red', activeforeground='yellow',bg='light green')
filemenu.add_command(label="Keygen", command=show_win7_window)
filemenu.add_command(label="批量修改MP4视频的MD5", command=show_win10_window)
othermenu = tk.Menu(menubar, tearoff=0, activebackground='red', activeforeground='yellow',bg='light green')
othermenu.add_command(label="文字转自然朗读工具", command=show_win11_window)
othermenu.add_command(label="MP4视频帧提取及分割工具", command=show_win12_window)
othermenu.add_command(label="Win01", command=show_win01_window)
menubar.add_cascade(label="Open", menu=filemenu)
menubar.add_cascade(label="Other", menu=othermenu)
menubar.add_command(label="Close", command=root.destroy)
# 禁用所有菜单项,需要密码验证后才启用
menubar.entryconfig("Open", state="disabled")
menubar.entryconfig("Other", state="disabled")
menubar.entryconfig("Close", state="disabled")
root.config(menu=menubar)
root.mainloop()