import tkinter as tk from tkinter import filedialog, ttk import configparser import os try: with open('installed.txt', 'r') as file: version = file.read() except FileNotFoundError: print("SyncKing-Kong does not appear to have installed correctly.") print("Please try to install it again.") print("https://github.com/anothermartz/Easy-Wav2Lip/issues") input() exit() print("opening GUI") runfile = 'run.txt' if os.path.exists(runfile): os.remove(runfile) import webbrowser def open_github_link(event): webbrowser.open("https://github.com/anothermartz/Easy-Wav2Lip?tab=readme-ov-file#advanced-tweaking") def read_config(): # Read the config.ini file config = configparser.ConfigParser() config.read("config.ini") return config def save_config(config): # Save the updated config back to config.ini with open("config.ini", "w") as config_file: config.write(config_file) def open_video_file(): file_path = filedialog.askopenfilename(title="Select a video file", filetypes=[("All files", "*.*")]) if file_path: video_file_var.set(file_path) def open_vocal_file(): file_path = filedialog.askopenfilename(title="Select a vocal file", filetypes=[("All files", "*.*")]) if file_path: vocal_file_var.set(file_path) # feathering def validate_frame_preview(P): if P == "": return True # Allow empty input try: num = float(P) if (num.is_integer()): return True except ValueError: pass return False def start_syncking_kong(): print("Saving config") config["OPTIONS"]["video_file"] = str(video_file_var.get()) config["OPTIONS"]["vocal_file"] = str(vocal_file_var.get()) config["OPTIONS"]["quality"] = str(quality_var.get()) config["OPTIONS"]["output_height"] = str(output_height_combobox.get()) config["OPTIONS"]["wav2lip_version"] = str(wav2lip_version_var.get()) config["OPTIONS"]["use_previous_tracking_data"] = str(use_previous_tracking_data_var.get()) config["OPTIONS"]["nosmooth"] = str(nosmooth_var.get()) config["OPTIONS"]["preview_window"] = str(preview_window_var.get()) config["PADDING"]["u"] = str(padding_vars["u"].get()) config["PADDING"]["d"] = str(padding_vars["d"].get()) config["PADDING"]["l"] = str(padding_vars["l"].get()) config["PADDING"]["r"] = str(padding_vars["r"].get()) config["MASK"]["size"] = str(size_var.get()) config["MASK"]["feathering"] = str(feathering_var.get()) config["MASK"]["mouth_tracking"] = str(mouth_tracking_var.get()) config["MASK"]["debug_mask"] = str(debug_mask_var.get()) config["OTHER"]["batch_process"] = str(batch_process_var.get()) config["OTHER"]["output_suffix"] = str(output_suffix_var.get()) config["OTHER"]["include_settings_in_suffix"] = str(include_settings_in_suffix_var.get()) config["OTHER"]["preview_settings"] = str(preview_settings_var.get()) config["OTHER"]["frame_to_preview"] = str(frame_to_preview_var.get()) save_config(config) # Save the updated config with open("run.txt", "w") as f: f.write("run") exit() # Add your logic here root = tk.Tk() root.title("SyncKing-Kong GUI") root.geometry("800x720") root.configure(bg="lightblue") # Read the existing config.ini config = read_config() row=0 tk.Label(root, text=version, bg="lightblue").grid(row=row, column=0, sticky="w") # Create a label for video file row+=1 video_label = tk.Label(root, text="Video File Path:", bg="lightblue") video_label.grid(row=row, column=0, sticky="e") # Entry widget for video file path video_file_var = tk.StringVar() video_entry = tk.Entry(root, textvariable=video_file_var, width=80) video_entry.grid(row=row, column=1, sticky="w") # Create a button to open the file dialog select_button = tk.Button(root, text="...", command=open_video_file) select_button.grid(row=row, column=1, sticky="w", padx=490) # Set the default value based on the existing config video_file_var.set(config["OPTIONS"].get("video_file", "")) row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # String input for vocal_file row+=1 # Create a label for the input box vocal_file_label = tk.Label(root, text="Vocal File Path:", bg="lightblue") vocal_file_label.grid(row=row, column=0, sticky="e") # Create an input box for the vocal file path vocal_file_var = tk.StringVar() vocal_file_entry = tk.Entry(root, textvariable=vocal_file_var, width=80) vocal_file_entry.grid(row=row, column=1, sticky="w") # Create a button to open the file dialog select_button = tk.Button(root, text="...", command=open_vocal_file) select_button.grid(row=row, column=1, sticky="w", padx=490) # Set the initial value from the 'config' dictionary (if available) vocal_file_var.set(config["OPTIONS"].get("vocal_file", "")) row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # Dropdown box for quality options row+=1 quality_label = tk.Label(root, text="Select Quality:", bg="lightblue") quality_label.grid(row=row, column=0, sticky="e") quality_options = ["Fast", "Improved", "Enhanced"] quality_var = tk.StringVar() quality_var.set(config["OPTIONS"].get("quality", "Improved")) quality_dropdown = tk.OptionMenu(root, quality_var, *quality_options) quality_dropdown.grid(row=row, column=1, sticky="w") row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # Output height row+=1 output_height_label = tk.Label(root, text="Output height:", bg="lightblue") output_height_label.grid(row=row, column=0, sticky="e") output_height_options = ["half resolution", "full resolution"] output_height_combobox = ttk.Combobox(root, values=output_height_options) output_height_combobox.set(config["OPTIONS"].get("output_height", "full resolution")) # Set default value output_height_combobox.grid(row=row, column=1, sticky="w") row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # Dropdown box for wav2lip version options row+=1 wav2lip_version_label = tk.Label(root, text="Select Wav2Lip version:", bg="lightblue") wav2lip_version_label.grid(row=row, column=0, sticky="e") wav2lip_version_options = ["Wav2Lip", "Wav2Lip_GAN"] wav2lip_version_var = tk.StringVar() wav2lip_version_var.set(config["OPTIONS"].get("wav2lip_version", "Wav2Lip")) wav2lip_version_dropdown = tk.OptionMenu(root, wav2lip_version_var, *wav2lip_version_options) wav2lip_version_dropdown.grid(row=row, column=1, sticky="w") row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # output_suffix row+=1 output_suffix_label = tk.Label(root, text="Output File Suffix:", bg="lightblue") output_suffix_label.grid(row=row, column=0, sticky="e") output_suffix_var = tk.StringVar() output_suffix_var.set(config["OTHER"].get("output_suffix", "_SyncKing-Kong")) output_suffix_entry = output_suffix_entry = tk.Entry(root, textvariable=output_suffix_var, width=20) output_suffix_entry.grid(row=row, column=1, sticky="w") include_settings_in_suffix_var = tk.BooleanVar() include_settings_in_suffix_var.set(config["OTHER"].get("include_settings_in_suffix", True)) # Set default value include_settings_in_suffix_checkbox = tk.Checkbutton(root, text="Add Settings to Suffix", variable=include_settings_in_suffix_var, bg="lightblue") include_settings_in_suffix_checkbox.grid(row=row, column=1, sticky="w", padx=130) # batch_process row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") row+=1 batch_process_label = tk.Label(root, text="Batch Process:", bg="lightblue") batch_process_label.grid(row=row, column=0, sticky="e") batch_process_var = tk.BooleanVar() batch_process_var.set(config["OTHER"].get("batch_process", True)) # Set default value batch_process_checkbox = tk.Checkbutton(root, text="", variable=batch_process_var, bg="lightblue") batch_process_checkbox.grid(row=row, column=1, sticky="w") # Dropdown box for preview window options row+=1 preview_window_label = tk.Label(root, text="Preview Window:", bg="lightblue") preview_window_label.grid(row=row, column=0, sticky="e") preview_window_options = ["Face", "Full", "Both", "None"] preview_window_var = tk.StringVar() preview_window_var.set(config["OPTIONS"].get("preview_window", "Face")) preview_window_dropdown = tk.OptionMenu(root, preview_window_var, *preview_window_options) preview_window_dropdown.grid(row=row, column=1, sticky="w") row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") # Button to start SyncKing-Kong row+=1 start_button = tk.Button(root, text="Start SyncKing-Kong", command=start_syncking_kong, bg="#5af269", font=("Arial", 16)) start_button.grid(row=row, column=0, sticky="w", padx=290, columnspan=2) row+=1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") row+=1 tk.Label(root, text="Advanced Tweaking:", bg="lightblue", font=("Arial", 16)).grid(row=row, column=0, sticky="w") row+=1 # Create a label with a custom cursor link = tk.Label(root, text="(Click here to see readme)", bg="lightblue", fg="blue", font=("Arial", 10), cursor="hand2") link.grid(row=row, column=0) # Bind the click event to the label link.bind("", open_github_link) # Process one frame only preview_settings_var = tk.BooleanVar() preview_settings_var.set(config["OTHER"].get("preview_settings", True)) # Set default value preview_settings_checkbox = tk.Checkbutton(root, text="Process one frame only - Frame to process:", variable=preview_settings_var, bg="lightblue") preview_settings_checkbox.grid(row=row, column=1, sticky="w") frame_to_preview_var = tk.StringVar() frame_to_preview_entry = tk.Entry(root, textvariable=frame_to_preview_var, validate="key", width=3, validatecommand=(root.register(validate_frame_preview), "%P")) frame_to_preview_entry.grid(row=row, column=1, sticky="w", padx=255) frame_to_preview_var.set(config["OTHER"].get("frame_to_preview", "100")) # Checkbox for nosmooth option row+=1 nosmooth_var = tk.BooleanVar() nosmooth_var.set(config["OPTIONS"].get("nosmooth", True)) # Set default value nosmooth_checkbox = tk.Checkbutton(root, text="nosmooth - unticking will smooth face detection between 5 frames", variable=nosmooth_var, bg="lightblue") nosmooth_checkbox.grid(row=row, column=1, sticky="w") # Checkbox for use_previous_tracking_data option row+=1 use_previous_tracking_data_var = tk.BooleanVar() use_previous_tracking_data_var.set(config["OPTIONS"].get("use_previous_tracking_data", True)) # Set default value use_previous_tracking_data_checkbox = tk.Checkbutton(root, text="Keep previous face tracking data if using same video", variable=use_previous_tracking_data_var, bg="lightblue") use_previous_tracking_data_checkbox.grid(row=row, column=1, sticky="w") # padding row+=1 tk.Label(root, text="Padding:", bg="lightblue", font=("Arial", 12)).grid(row=row, column=1, sticky="sw", pady=10) row+=1 tk.Label(root, text="(Up, Down, Left, Right)", bg="lightblue").grid(row=row, column=1, rowspan=4, sticky="w", padx=100) padding_vars = {} # Create a list of padding labels and their corresponding keys padding_labels = [("U:", "u"), ("D:", "d"), ("L:", "l"), ("R:", "r")] # Validation function to allow only integers def validate_integer(P): if P == "" or P == "-" or P.lstrip("-").isdigit(): return True return False # Create the padding labels and entry widgets using a loop for label_text, key in padding_labels: label = tk.Label(root, text=label_text, bg="lightblue") label.grid(row=row, column=1, sticky="w", padx=50) # Create a StringVar for the current key padding_var = tk.StringVar() # Set validation to allow positive and negative integers entry = tk.Entry(root, textvariable=padding_var, width=3, validate="key", validatecommand=(root.register(validate_integer), "%P")) entry.grid(row=row, column=1, sticky="w", padx=70) # Set the default value from the 'config' dictionary padding_var.set(config["PADDING"].get(key, "")) # Store the StringVar in the dictionary padding_vars[key] = padding_var # Increment the row row += 1 tk.Label(root, text="", bg="lightblue").grid(row=row, column=0, sticky="w") row+=1 # mask size def validate_custom_number(P): if P == "": return True # Allow empty input try: num = float(P) if 0 <= num <= 6 and (num.is_integer() or (num * 10) % 1 == 0): return True except ValueError: pass return False row+=1 tk.Label(root, text="Mask settings:", bg="lightblue", font=("Arial", 12)).grid(row=row, column=1, sticky="sw") row+=1 size_label = tk.Label(root, text="Mask size:", bg="lightblue", padx=50) size_label.grid(row=row, column=1, sticky="w") size_var = tk.StringVar() size_entry = tk.Entry(root, textvariable=size_var, validate="key", width=3, validatecommand=(root.register(validate_custom_number), "%P")) size_entry.grid(row=row, column=1, sticky="w", padx=120) size_var.set(config["MASK"].get("size", "2.5")) # feathering def validate_feather(P): if P == "": return True # Allow empty input try: num = float(P) if 0 <= num <= 3 and (num.is_integer()): return True except ValueError: pass return False row+=1 feathering_label = tk.Label(root, text="Feathering:", bg="lightblue", padx=50) feathering_label.grid(row=row, column=1, sticky="w") feathering_var = tk.StringVar() feathering_entry = tk.Entry(root, textvariable=feathering_var, validate="key", width=3, validatecommand=(root.register(validate_feather), "%P")) feathering_entry.grid(row=row, column=1, sticky="w", padx=120) feathering_var.set(config["MASK"].get("feathering", "2.5")) # mouth_tracking row+=1 mouth_tracking_var = tk.BooleanVar() mouth_tracking_var.set(config["MASK"].get("mouth_tracking", True)) # Set default value mouth_tracking_checkbox = tk.Checkbutton(root, text="track mouth for mask on every frame", variable=mouth_tracking_var, bg="lightblue", padx=50) mouth_tracking_checkbox.grid(row=row, column=1, sticky="w") # debug_mask row+=1 debug_mask_var = tk.BooleanVar() debug_mask_var.set(config["MASK"].get("debug_mask", True)) # Set default value debug_mask_checkbox = tk.Checkbutton(root, text="highlight mask for debugging", variable=debug_mask_var, bg="lightblue", padx=50) debug_mask_checkbox.grid(row=row, column=1, sticky="w") # Increase spacing between all rows (uniformly) for row in range(row): root.rowconfigure(row, weight=1) root.mainloop()