25
2024
01

Movies GUI Tools

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()


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。