I tried to merge my files together to create a would you rather creator, but right now the video creation doesnt work. here is my implementation yet:
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from moviepy.editor import (
    TextClip,
    ColorClip,
    CompositeVideoClip,
    ImageClip,
    AudioFileClip,
    concatenate_videoclips,
    CompositeAudioClip
)
from moviepy.config import change_settings
import numpy as np
from PIL import Image, ImageDraw
import os
import subprocess
from pathlib import Path
import json
import urllib.request
import urllib.parse
import uuid
import random
import shutil
import datetime
import websocket
import re
import threading
import sys

# ---------------------- Configuration ----------------------

# ImageMagick configuration (Ensure this path is correct for your system)
change_settings(
    {"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16-HDRI\magick.exe"}
)

# Paths for various components
BASE_DIR = os.path.abspath("would_you_rather_project")
TEXT_OUTPUT_FILE = os.path.join(BASE_DIR, "would_you_rather.txt")
GENERATED_IMAGES_DIR = os.path.join(BASE_DIR, "generate_images")
VOICE_OUTPUT_DIR = os.path.join(BASE_DIR, "generated_audio")
VIDEO_OUTPUT_FILE = os.path.join(BASE_DIR, "would_you_rather.mp4")
COMFYUI_WORKFLOW_PATH = os.path.join(BASE_DIR, "workflow.json")
F5_TTS_BASE_DIR = r"C:\Users\theod\Desktop\AI\text2voice\F5-TTS"  # Update as needed

# Ensure necessary directories exist
os.makedirs(BASE_DIR, exist_ok=True)
os.makedirs(GENERATED_IMAGES_DIR, exist_ok=True)
os.makedirs(VOICE_OUTPUT_DIR, exist_ok=True)

# ---------------------- Text Generation ----------------------

def generate_would_you_rather():
    import ollama

    prompt = """Generate 6 funny and weird 'Would You Rather' choices. 
Format each pair EXACTLY like this example:

1.
CHOICE: eat a glowing mushroom
IMAGE: A luminescent blue mushroom radiating soft light in the darkness, sitting on a bed of moss with tiny sparkles emanating from its cap
VERSUS
CHOICE: drink liquid rainbow
IMAGE: A crystal glass filled with swirling, iridescent liquid that shifts through all colors of the spectrum, leaving trails of light as it moves

2.
CHOICE: have clouds for shoes
IMAGE: Fluffy white cumulus clouds shaped like sneakers, floating inches above the ground, leaving behind small rainbows with each step
VERSUS
CHOICE: wear a hat made of living butterflies
IMAGE: A graceful arrangement of vibrant butterflies forming a crown-like hat, their wings gently fluttering in unison

Make each pair unique, weird, and entertaining. Write detailed image descriptions that would help create a clear visual."""

    try:
        response = ollama.chat(model='llama3.2', messages=[
            {'role': 'user', 'content': prompt}
        ])
        return response['message']['content'].strip()
        
    except Exception as e:
        print(f"Error: {str(e)}")
        raise

# ---------------------- Image Generation ----------------------

class ComfyUIGenerator:
    def __init__(self, server_address="127.0.0.1:8188"):
        self.server_address = server_address
        self.client_id = str(uuid.uuid4())
        
        # Create generate_images folder if it doesn't exist
        Path(GENERATED_IMAGES_DIR).mkdir(exist_ok=True)
        
    def load_workflow(self, workflow_path):
        """Load workflow JSON from file"""
        with open(workflow_path, 'r') as f:
            return json.load(f)
            
    def queue_prompt(self, prompt):
        """Queue a prompt on the ComfyUI server"""
        p = {"prompt": prompt, "client_id": self.client_id}
        data = json.dumps(p).encode('utf-8')
        req = urllib.request.Request(f"http://{self.server_address}/prompt", data=data)
        return json.loads(urllib.request.urlopen(req).read())

    def get_image(self, filename, subfolder, folder_type):
        """Get image data from the server"""
        data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
        url_values = urllib.parse.urlencode(data)
        with urllib.request.urlopen(f"http://{self.server_address}/view?{url_values}") as response:
            return response.read()

    def get_history(self, prompt_id):
        """Get history data for a prompt"""
        with urllib.request.urlopen(f"http://{self.server_address}/history/{prompt_id}") as response:
            return json.loads(response.read())

    def save_image(self, image_data, filename):
        """Save image data to file"""
        output_path = Path(GENERATED_IMAGES_DIR) / filename
        with open(output_path, 'wb') as f:
            f.write(image_data)
        print(f"Image saved to: {output_path}")

    def get_images(self, ws, prompt):
        """Get images using the history endpoint"""
        prompt_id = self.queue_prompt(prompt)['prompt_id']
        
        # Wait for execution to complete
        while True:
            try:
                out = ws.recv()
            except websocket.WebSocketConnectionClosedException:
                break  # Exit if connection is closed
                
            if isinstance(out, str):
                message = json.loads(out)
                if message['type'] == 'executing':
                    data = message['data']
                    if data.get('node') is None and data.get('prompt_id') == prompt_id:
                        break
            else:
                continue  # Skip binary messages (previews)

        # Get the images from history
        history = self.get_history(prompt_id)[prompt_id]
        output_images = {}
        
        for node_id in history['outputs']:
            node_output = history['outputs'][node_id]
            images_output = []
            if 'images' in node_output:
                for image in node_output['images']:
                    image_data = self.get_image(
                        image['filename'], 
                        image['subfolder'], 
                        image['type']
                    )
                    images_output.append(image_data)
            output_images[node_id] = images_output
            
        return output_images, prompt_id

    def generate_image(self, workflow_path, prompt_text, seed=None):
        """Generate an image using the workflow"""
        # Load the workflow
        workflow = self.load_workflow(workflow_path)
        
        # Generate random seed if none provided
        if seed is None:
            seed = random.randint(0, 1000000000)
            
        # Find the CLIPTextEncode node for positive prompt
        for node_id, node in workflow.items():
            if node.get("class_type") == "CLIPTextEncode" and \
               "_meta" in node and \
               "title" in node["_meta"] and \
               "Positive" in node["_meta"]["title"]:
                node["inputs"]["text"] = prompt_text
                
        # Find the KSampler node to update the seed
        for node_id, node in workflow.items():
            if node.get("class_type") == "KSampler":
                node["inputs"]["seed"] = seed

        # Save the modified workflow
        with open(workflow_path, 'w') as f:
            json.dump(workflow, f)

        # Connect to websocket
        ws = websocket.WebSocket()
        ws.connect(f"ws://{self.server_address}/ws?clientId={self.client_id}")
        
        try:
            # Get images using history endpoint
            images, prompt_id = self.get_images(ws, workflow)
            
            # Save all generated images
            saved_image_paths = []
            for node_id, image_list in images.items():
                for i, image_data in enumerate(image_list):
                    filename = f"generated_{seed}_{node_id}_{i}.png"
                    self.save_image(image_data, filename)
                    saved_image_paths.append(str(Path(GENERATED_IMAGES_DIR) / filename))
                    
            return saved_image_paths
        
        finally:
            ws.close()

# ---------------------- Voice Generation ----------------------

def generate_tts(text, base_dir=F5_TTS_BASE_DIR, ref_audio=None, output_dir=VOICE_OUTPUT_DIR):
    """
    Generate TTS audio using F5-TTS model.
    
    Args:
        text (str): Text to convert to speech
        base_dir (str): Base directory where F5-TTS is installed
        ref_audio (str): Path to reference audio file
        output_dir (str): Directory to save output files
    """
    if ref_audio is None:
        ref_audio = os.path.join(base_dir, "tests", "ref_audio", "tiktok.mp3")
    
    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Reference text that matches your sample
    ref_text = "Never go to school again. Or, Get paid to go to school. Be able to fly like a bird or be able to swim like a fish. Have a long but ordinary life or have a short but extraordinary life I love God or reject the offer have a ferrari."
    
    # Build the command without extra quotes
    cmd = [
        "python", "inference-cli.py",
        "--model", "F5-TTS",
        "--ref_audio", ref_audio,
        "--ref_text", ref_text,
        "--gen_text", text,
        "--output", "out.wav"  # Ensures the output file is named consistently
    ]
    
    try:
        # Change to the base directory
        original_dir = os.getcwd()
        os.chdir(base_dir)
        
        # Path to the Python executable in the virtual environment
        if os.name == 'nt':  # Windows
            python_executable = os.path.join(base_dir, "venv", "Scripts", "python.exe")
        else:  # Linux/Mac
            python_executable = os.path.join(base_dir, "venv", "bin", "python")
        
        # Replace "python" with the virtual environment's Python
        cmd[0] = python_executable
        
        # Run the subprocess and capture output
        result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=False)
        
        if result.returncode != 0:
            print(f"Error in TTS generation:\n{result.stderr}")
            return None
        
        # Path to the output file
        output_file = os.path.join(base_dir, "out.wav")
        if os.path.exists(output_file):
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            sanitized_text = "_".join(text.split())
            sanitized_text = re.sub(r'[^a-zA-Z0-9_]', '', sanitized_text)  # Remove invalid characters
            new_filename = f"tts_output_{sanitized_text[:30]}_{timestamp}.wav"  # Limit filename length
            new_filepath = os.path.join(output_dir, new_filename)
            shutil.move(output_file, new_filepath)  # Use move to ensure the file is relocated
            print(f"Audio generated successfully: {new_filepath}")
            return new_filepath
        else:
            print("Error: Output file not found")
            print(f"Subprocess Output:\n{result.stdout}\n{result.stderr}")
            return None
                
    except subprocess.CalledProcessError as e:
        print(f"Command execution failed: {str(e)}")
        return None
    except Exception as e:
        print(f"Error occurred: {str(e)}")
        return None
    finally:
        # Return to original directory
        os.chdir(original_dir)

# ---------------------- Video Generation ----------------------

class WouldYouRatherGenerator:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Would You Rather - All-in-One Generator")
        self.window.geometry("800x800")  # Increased height to accommodate all fields

        # Video dimensions (9:16 ratio)
        self.width = 1080
        self.height = 1920
        self.middle_y = self.height // 2

        # Initialize ComfyUI Generator
        self.comfyui = ComfyUIGenerator()

        # Store generated audio paths
        self.generated_audio_paths = []

        self.setup_ui()

    def setup_ui(self):
        main_frame = ttk.Frame(self.window, padding="20")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # Configure grid columns for consistent alignment
        for i in range(4):
            main_frame.columnconfigure(i, weight=1, pad=5)

        # Text Generation Section
        text_frame = ttk.LabelFrame(main_frame, text="Text Generation", padding="10")
        text_frame.grid(row=0, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        self.generate_text_button = ttk.Button(
            text_frame, text="Generate 'Would You Rather' Text", command=self.generate_text
        )
        self.generate_text_button.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)

        self.text_output = tk.Text(text_frame, width=80, height=10, wrap=tk.WORD)
        self.text_output.grid(row=1, column=0, padx=5, pady=5)

        # Image Generation Section (Auto-generated)
        image_frame = ttk.LabelFrame(main_frame, text="Image Generation", padding="10")
        image_frame.grid(row=1, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(image_frame, text="Choose Workflow File:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.workflow_path_entry = ttk.Entry(image_frame, width=50)
        self.workflow_path_entry.grid(row=0, column=1, padx=5, pady=5)
        self.workflow_path_entry.insert(0, COMFYUI_WORKFLOW_PATH)  # Default path

        ttk.Label(image_frame, text="Prompt File:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.prompt_file_entry = ttk.Entry(image_frame, width=50)
        self.prompt_file_entry.grid(row=1, column=1, padx=5, pady=5)
        self.prompt_file_entry.insert(0, TEXT_OUTPUT_FILE)  # Default path

        self.generate_images_button = ttk.Button(
            image_frame, text="Generate Images", command=self.generate_images
        )
        self.generate_images_button.grid(row=2, column=0, columnspan=2, pady=10)

        # Voice Generation Section
        voice_frame = ttk.LabelFrame(main_frame, text="Voice Generation", padding="10")
        voice_frame.grid(row=2, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(voice_frame, text="Text File:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.voice_text_file_entry = ttk.Entry(voice_frame, width=50)
        self.voice_text_file_entry.grid(row=0, column=1, padx=5, pady=5)
        self.voice_text_file_entry.insert(0, TEXT_OUTPUT_FILE)  # Default path

        self.generate_voice_button = ttk.Button(
            voice_frame, text="Generate Voice", command=self.generate_voice
        )
        self.generate_voice_button.grid(row=1, column=0, columnspan=2, pady=10)

        # Video Generation Section
        video_frame = ttk.LabelFrame(main_frame, text="Video Generation", padding="10")
        video_frame.grid(row=3, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(video_frame, text="Audio Files Directory:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.audio_dir_entry = ttk.Entry(video_frame, width=50)
        self.audio_dir_entry.grid(row=0, column=1, padx=5, pady=5)
        self.audio_dir_entry.insert(0, VOICE_OUTPUT_DIR)  # Default path

        self.generate_video_button = ttk.Button(
            video_frame, text="Generate Video", command=self.generate_video
        )
        self.generate_video_button.grid(row=1, column=0, columnspan=2, pady=10)

    def generate_text(self):
        """Generate 'Would You Rather' text pairs and display them."""
        def task():
            try:
                self.generate_text_button.config(state=tk.DISABLED)
                text = generate_would_you_rather()
                self.text_output.delete('1.0', tk.END)
                self.text_output.insert(tk.END, text)

                # Save to file
                with open(TEXT_OUTPUT_FILE, 'w', encoding='utf-8') as f:
                    f.write(text)

                messagebox.showinfo("Success", "Text generation completed and saved.")
            except Exception as e:
                messagebox.showerror("Error", f"Failed to generate text: {str(e)}")
            finally:
                self.generate_text_button.config(state=tk.NORMAL)

        threading.Thread(target=task).start()

    def generate_images(self):
        """Generate images based on the generated text."""
        def task():
            try:
                self.generate_images_button.config(state=tk.DISABLED)
                
                # Read the text file and extract image descriptions
                with open(self.prompt_file_entry.get(), 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # Parse the content to extract image descriptions
                pattern = re.compile(
                    r'\d+\.\s+CHOICE:\s*(.*?)\s+IMAGE:\s*(.*?)\s+VERSUS\s+CHOICE:\s*(.*?)\s+IMAGE:\s*(.*?)\s*',
                    re.DOTALL
                )
                matches = pattern.findall(content)
                if not matches:
                    raise ValueError("No valid 'Would You Rather' pairs found in the text file.")

                image_prompts = []
                for match in matches:
                    choice1, image1, choice2, image2 = match
                    image_prompts.append((choice1.strip(), image1.strip()))
                    image_prompts.append((choice2.strip(), image2.strip()))

                # Generate images
                all_generated_images = []
                for choice, image_desc in image_prompts:
                    generated_paths = self.comfyui.generate_image(COMFYUI_WORKFLOW_PATH, image_desc)
                    if generated_paths:
                        all_generated_images.append({
                            'choice': choice,
                            'images': generated_paths
                        })
                    else:
                        raise ValueError(f"Failed to generate image for prompt: {image_desc}")

                messagebox.showinfo("Success", "Image generation completed and saved.")
            except Exception as e:
                messagebox.showerror("Error", f"Failed to generate images: {str(e)}")
            finally:
                self.generate_images_button.config(state=tk.NORMAL)

        threading.Thread(target=task).start()

    def generate_voice(self):
        """Generate voice recordings for the choices."""
        def task():
            try:
                self.generate_voice_button.config(state=tk.DISABLED)
                
                # Read the text file and extract choices
                with open(self.voice_text_file_entry.get(), 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # Parse the content to extract choices
                pattern = re.compile(
                    r'\d+\.\s+CHOICE:\s*(.*?)\s+IMAGE:', re.DOTALL
                )
                choices = pattern.findall(content)
                if not choices:
                    raise ValueError("No valid 'Would You Rather' choices found in the text file.")

                # Generate TTS for each choice
                self.generated_audio_paths = []
                for choice in choices:
                    audio_path = generate_tts(choice)
                    if audio_path:
                        self.generated_audio_paths.append(audio_path)
                    else:
                        raise ValueError(f"Failed to generate audio for choice: {choice}")

                messagebox.showinfo("Success", "Voice generation completed and saved.")
            except Exception as e:
                messagebox.showerror("Error", f"Failed to generate voice: {str(e)}")
            finally:
                self.generate_voice_button.config(state=tk.NORMAL)

        threading.Thread(target=task).start()

    def generate_video(self):
        """Assemble the video with generated images and audio."""
        def task():
            try:
                self.generate_video_button.config(state=tk.DISABLED)
                
                # Validate that audio files are present
                audio_dir = self.audio_dir_entry.get()
                if not os.path.isdir(audio_dir):
                    raise ValueError("Invalid audio directory.")

                audio_files = sorted([
                    os.path.join(audio_dir, f) for f in os.listdir(audio_dir) 
                    if f.endswith('.wav')
                ])
                if not audio_files:
                    raise ValueError("No audio files found in the specified directory.")

                # Read the text file and extract choices
                with open(TEXT_OUTPUT_FILE, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # Parse the content to extract choices and image descriptions
                pair_pattern = re.compile(
                    r'\d+\.\s+CHOICE:\s*(.*?)\s+IMAGE:\s*(.*?)\s+VERSUS\s+CHOICE:\s*(.*?)\s+IMAGE:\s*(.*?)\s*',
                    re.DOTALL
                )
                pairs = pair_pattern.findall(content)
                if not pairs:
                    raise ValueError("No valid 'Would You Rather' pairs found in the text file.")

                # Load images corresponding to choices
                images = []
                image_files = sorted(os.listdir(GENERATED_IMAGES_DIR))
                if len(image_files) < len(pairs) * 2:
                    raise ValueError("Not enough images generated for the number of pairs.")

                for idx, pair in enumerate(pairs):
                    choice1, img_desc1, choice2, img_desc2 = pair
                    image1 = os.path.join(GENERATED_IMAGES_DIR, image_files[idx*2])
                    image2 = os.path.join(GENERATED_IMAGES_DIR, image_files[idx*2 + 1])
                    images.append((
                        image1,
                        choice1.strip(),
                        image2,
                        choice2.strip()
                    ))

                # Validate that the number of audio files matches expectations
                expected_audio_count = len(pairs) * 2  # Two choices per pair
                if len(audio_files) < expected_audio_count:
                    raise ValueError(f"Expected at least {expected_audio_count} audio files, found {len(audio_files)}.")

                # Define desired duration for each video segment (in seconds)
                desired_segment_duration = 5  # You can adjust this as needed

                # Start assembling video clips
                clips = []
                total_duration = 0

                for idx, (img1, choice1, img2, choice2) in enumerate(images):
                    # Load images
                    img1_clip = ImageClip(img1).resize(width=500).set_position(("center", self.height * 0.3))
                    img2_clip = ImageClip(img2).resize(width=500).set_position(("center", self.height * 0.7))
                    
                    # Load audio
                    audio1 = AudioFileClip(audio_files[idx*2]).volumex(0.5)
                    audio2 = AudioFileClip(audio_files[idx*2 + 1]).volumex(0.5)

                    # Pad audio to the desired duration
                    audio1 = audio1.set_duration(desired_segment_duration)
                    audio2 = audio2.set_duration(desired_segment_duration)

                    # Combine audio using CompositeAudioClip
                    combined_audio = CompositeAudioClip([audio1, audio2]).set_duration(desired_segment_duration)

                    # Create text clips
                    txt1 = TextClip(choice1, fontsize=80, color='white', stroke_color='black', stroke_width=2).set_position(("center", self.height * 0.2)).set_duration(desired_segment_duration)
                    txt2 = TextClip(choice2, fontsize=80, color='white', stroke_color='black', stroke_width=2).set_position(("center", self.height * 0.6)).set_duration(desired_segment_duration)
                    
                    # Combine image and text
                    composite = CompositeVideoClip([img1_clip, img2_clip, txt1, txt2]).set_duration(desired_segment_duration)
                    
                    # Set combined audio
                    composite = composite.set_audio(combined_audio)
                    
                    clips.append(composite)
                    total_duration += desired_segment_duration

                # Concatenate all clips
                final_clip = concatenate_videoclips(clips, method="compose")
                final_clip = final_clip.set_duration(total_duration)

                # Export the video
                final_clip.write_videofile(
                    VIDEO_OUTPUT_FILE,
                    fps=30,
                    codec="libx264",
                    audio_codec="aac",
                    remove_temp=True,
                    threads=4,
                    preset="medium",
                )
                messagebox.showinfo("Success", f"Video generated successfully!\nSaved to: {VIDEO_OUTPUT_FILE}")
            except Exception as e:
                messagebox.showerror("Error", f"Failed to generate video: {str(e)}")
            finally:
                self.generate_video_button.config(state=tk.NORMAL)

        threading.Thread(target=task).start()

    def run(self):
        self.window.mainloop()

# ---------------------- Main Execution ----------------------

if __name__ == "__main__":
    app = WouldYouRatherGenerator()
    app.run()
	
	
	
	
	
	
	
	
	
	
and here is the code I tried to implement, but doesnt work right, please find the issues and fix all the bugs, work with debug print statements.
Code:
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from moviepy.editor import (
    TextClip,
    ColorClip,
    CompositeVideoClip,
    ImageClip,
)
from moviepy.config import change_settings
import numpy as np
from PIL import Image, ImageDraw
import os

# Configure ImageMagick (Ensure this path is correct for your system)
change_settings(
    {"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16-HDRI\magick.exe"}
)


class WouldYouRatherGenerator:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Would You Rather Generator")
        self.window.geometry("800x700")  # Increased height to accommodate new field

        # Video dimensions (9:16 ratio)
        self.width = 1080
        self.height = 1920
        self.middle_y = self.height // 2

        # Store image paths
        self.image1_path = None  # Top image (Black socks)
        self.image2_path = None  # Bottom image (White socks)

        self.setup_ui()

    def setup_ui(self):
        main_frame = ttk.Frame(self.window, padding="20")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # Configure grid columns for consistent alignment
        for i in range(4):
            main_frame.columnconfigure(i, weight=1, pad=5)

        # Option 1 Section (Top Half - Black Socks)
        option1_frame = ttk.LabelFrame(main_frame, text="Option 1 (Black Socks)", padding="10")
        option1_frame.grid(row=0, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(option1_frame, text="Text:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.option1_text = ttk.Entry(option1_frame, width=50)
        self.option1_text.grid(row=0, column=1, columnspan=2, sticky=(tk.W, tk.E), pady=5)
        self.option1_text.insert(0, "SCHWARZE SOCKEN")  # Default text

        ttk.Label(option1_frame, text="Image:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.image1_label = ttk.Label(option1_frame, text="No image selected")
        self.image1_label.grid(row=1, column=1, sticky=tk.W, pady=5)
        ttk.Button(
            option1_frame, text="Browse...", command=lambda: self.select_image(1)
        ).grid(row=1, column=2, padx=5, pady=5)

        ttk.Label(option1_frame, text="Percentage:").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.percent1 = ttk.Entry(option1_frame, width=10)
        self.percent1.grid(row=2, column=1, sticky=tk.W, pady=5)
        self.percent1.insert(0, "1,02%")  # Default percentage

        # Option 2 Section (Bottom Half - White Socks)
        option2_frame = ttk.LabelFrame(main_frame, text="Option 2 (White Socks)", padding="10")
        option2_frame.grid(row=1, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(option2_frame, text="Text:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.option2_text = ttk.Entry(option2_frame, width=50)
        self.option2_text.grid(row=0, column=1, columnspan=2, sticky=(tk.W, tk.E), pady=5)
        self.option2_text.insert(0, "WEIßE SOCKEN")  # Default text

        ttk.Label(option2_frame, text="Image:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.image2_label = ttk.Label(option2_frame, text="No image selected")
        self.image2_label.grid(row=1, column=1, sticky=tk.W, pady=5)
        ttk.Button(
            option2_frame, text="Browse...", command=lambda: self.select_image(2)
        ).grid(row=1, column=2, padx=5, pady=5)

        ttk.Label(option2_frame, text="Percentage:").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.percent2 = ttk.Entry(option2_frame, width=10)
        self.percent2.grid(row=2, column=1, sticky=tk.W, pady=5)
        self.percent2.insert(0, "999,72%")  # Default percentage

        # Timing Controls Section
        timing_frame = ttk.LabelFrame(main_frame, text="Timing Controls", padding="10")
        timing_frame.grid(row=2, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)

        ttk.Label(timing_frame, text="Initial Pause (seconds):").grid(
            row=0, column=0, sticky=tk.W, pady=5
        )
        self.initial_pause = ttk.Entry(timing_frame, width=10)
        self.initial_pause.grid(row=0, column=1, sticky=tk.W, pady=5)
        self.initial_pause.insert(0, "2")  # Default 2 seconds

        ttk.Label(timing_frame, text="Timer Delay Before Second Image (seconds):").grid(
            row=1, column=0, sticky=tk.W, pady=5
        )
        self.timer_delay = ttk.Entry(timing_frame, width=10)
        self.timer_delay.grid(row=1, column=1, sticky=tk.W, pady=5)
        self.timer_delay.insert(0, "1")  # Default 1 second

        ttk.Label(timing_frame, text="Wait Before Countdown (seconds):").grid(
            row=2, column=0, sticky=tk.W, pady=5
        )
        self.wait_before_countdown = ttk.Entry(timing_frame, width=10)
        self.wait_before_countdown.grid(row=2, column=1, sticky=tk.W, pady=5)
        self.wait_before_countdown.insert(0, "1")  # Default 1 second

        ttk.Label(timing_frame, text="Countdown (seconds):").grid(
            row=3, column=0, sticky=tk.W, pady=5
        )
        self.countdown_duration = ttk.Entry(timing_frame, width=10)
        self.countdown_duration.grid(row=3, column=1, sticky=tk.W, pady=5)
        self.countdown_duration.insert(0, "5")  # Default 5 seconds

        # Generate Button
        generate_button = ttk.Button(
            main_frame, text="Generate Video", command=self.generate_video
        )
        generate_button.grid(row=4, column=0, columnspan=4, pady=20)

    def select_image(self, option_num):
        """
        Open a file dialog to select an image and update the corresponding label.
        """
        file_path = filedialog.askopenfilename(
            filetypes=[("Image files", "*.png *.jpg *.jpeg *.gif *.bmp")]
        )
        if file_path:
            if option_num == 1:
                self.image1_path = file_path
                self.image1_label.config(text=os.path.basename(file_path))
            elif option_num == 2:
                self.image2_path = file_path
                self.image2_label.config(text=os.path.basename(file_path))

    def process_image(self, image_path, size=(500, 500), start_time=0, duration=0):
        """
        Process the image by converting mode and resizing proportionally without warping.

        :param image_path: Path to the image file.
        :param size: Maximum width and height as a tuple. Increased to (500, 500).
        :param start_time: Time at which the image should appear in the video.
        :param duration: Duration of the image clip.
        :return: An ImageClip object.
        """
        img = Image.open(image_path)

        if img.mode != "RGBA":
            img = img.convert("RGBA")

        # Resize image proportionally if size is provided
        if size:
            img.thumbnail(size, Image.LANCZOS)  # In-place resizing

        img_array = np.array(img)

        clip_duration = duration if duration > 0 else self.total_duration

        clip = ImageClip(img_array).set_duration(clip_duration)

        if start_time > 0:
            clip = clip.set_start(start_time)

        return clip

    def create_styled_text(
        self, text, y_position, duration, start_time=0, fontsize=70, color="yellow",
        stroke_color="black", stroke_width=2
    ):
        """
        Create a styled TextClip.

        :param text: Text content.
        :param y_position: Vertical position of the text.
        :param duration: Duration for which the text is visible.
        :param start_time: Time at which the text appears.
        :param fontsize: Font size of the text.
        :param color: Text color.
        :param stroke_color: Stroke (outline) color.
        :param stroke_width: Width of the stroke.
        :return: A TextClip object.
        """
        text_clip = TextClip(
            text,
            font="Arial-Bold",
            color=color,
            fontsize=fontsize,
            method="label",  # Changed to 'label' for better positioning
            stroke_color=stroke_color,
            stroke_width=stroke_width,
        ).set_duration(duration)

        if start_time > 0:
            text_clip = text_clip.set_start(start_time)

        return text_clip.set_position(("center", y_position))

    def create_timer_clips(self, start_time, countdown_seconds, total_duration):
        """
        Create countdown timer clips from countdown_seconds to 1 (excluding 0).

        :param start_time: The time at which the countdown starts.
        :param countdown_seconds: Number of seconds to count down from.
        :param total_duration: Total duration of the video.
        :return: A list of TextClip objects for the countdown.
        """
        timer_clips = []
        for i in range(countdown_seconds, 0, -1):  # Excludes 0
            current_time = countdown_seconds - i
            timer_text = str(i)
            timer_duration = 1  # Each number shows for 1 second
            timer_clip = self.create_styled_text(
                timer_text,
                self.middle_y - 100,  # Positioned slightly above the center
                timer_duration,
                start_time + current_time,
                fontsize=150,
                color="white",
                stroke_color="black",
                stroke_width=3
            )
            timer_clips.append(timer_clip)
        return timer_clips

    def generate_video(self):
        """
        Generate the 'Would You Rather' video based on user inputs.
        """
        # Validate inputs
        if not self.image1_path or not self.image2_path:
            messagebox.showerror("Input Error", "Please select both images (Option 1 and Option 2).")
            return

        option1_text = self.option1_text.get().strip()
        option2_text = self.option2_text.get().strip()

        if not option1_text or not option2_text:
            messagebox.showerror(
                "Input Error", "Please enter text for both options."
            )
            return

        # Validate timing inputs
        try:
            initial_pause = float(self.initial_pause.get())
            timer_delay = float(self.timer_delay.get())
            countdown_wait = float(self.wait_before_countdown.get())
            countdown_seconds = int(self.countdown_duration.get())
        except ValueError:
            messagebox.showerror(
                "Input Error", "Please enter valid numeric values for timings."
            )
            return

        if countdown_wait < 0:
            messagebox.showerror(
                "Input Error", "Wait Before Countdown cannot be negative."
            )
            return

        # Validate percentage inputs
        try:
            # Replace comma with dot for decimal conversion if used
            percent1_val = self.percent1.get().strip().replace(',', '.').replace('%', '')
            percent2_val = self.percent2.get().strip().replace(',', '.').replace('%', '')
            percent1 = float(percent1_val)
            percent2 = float(percent2_val)
        except ValueError:
            messagebox.showerror(
                "Input Error", "Please enter valid numeric values for percentages (e.g., 1.02%)."
            )
            return

        # Define percentage display duration and desired extra time
        percentage_duration = 3  # seconds (increased from 2)
        desired_extra_time = 0    # seconds (no extra buffer after percentages)

        # Calculate buffer_time as the sum of percentage_duration and desired_extra_time
        buffer_time = percentage_duration + desired_extra_time  # 3 + 0 = 3 seconds

        # Calculate total_duration
        self.total_duration = (
            initial_pause
            + timer_delay
            + countdown_wait
            + countdown_seconds
            + buffer_time
        )  # e.g., 2 + 1 + 1 + 5 + 3 = 12 seconds

        # Create background clips
        red_clip = ColorClip((self.width, self.middle_y), color=(255, 0, 0)).set_duration(
            self.total_duration
        )
        blue_clip = ColorClip((self.width, self.middle_y), color=(0, 0, 255)).set_duration(
            self.total_duration
        )

        clips = [
            red_clip.set_position((0, 0)),
            blue_clip.set_position((0, self.middle_y)),
        ]

        # Fixed Positions

        # Top Half
        top_image_y = 250    # Moved further down from 200 to 250
        top_text_y = 650     # Moved up by 50 pixels from 700 to 650
        top_percentage_y = 750  # Moved up by 50 pixels from 800 to 750

        # Bottom Half
        bottom_image_y = self.middle_y + 350  # Moved further down from self.middle_y + 300 to +350
        bottom_text_y = 1200  # Fixed position for bottom text
        bottom_percentage_y = 1100  # Changed from 1300 to 1100 to place above the bottom text

        # Add top image (Black Socks) with initial_pause delay
        img1_clip = self.process_image(
            self.image1_path,
            size=(500, 500),       # Increased size to 500x500
            start_time=initial_pause,          # Starts after initial_pause
            duration=self.total_duration - initial_pause  # Adjust duration accordingly
        )
        if img1_clip:
            clips.append(img1_clip.set_position(("center", top_image_y)))

        # Add top text with initial_pause delay
        option1_txt = self.create_styled_text(
            option1_text.upper(),
            y_position=top_text_y,
            duration=self.total_duration - initial_pause,  # Duration until end
            start_time=initial_pause,          # Starts after initial_pause
            fontsize=80,
            color="white",
            stroke_color="black",
            stroke_width=3
        )
        clips.append(option1_txt)

        # Add bottom image (White Socks) after initial_pause + timer_delay
        img2_start_time = initial_pause + timer_delay
        img2_clip = self.process_image(
            self.image2_path,
            size=(500, 500),       # Increased size to 500x500
            start_time=img2_start_time,
            duration=self.total_duration - img2_start_time  # Adjust duration accordingly
        )
        if img2_clip:
            clips.append(img2_clip.set_position(("center", bottom_image_y)).set_start(img2_start_time))

        # Add bottom text below the bottom image after initial_pause + timer_delay
        option2_txt = self.create_styled_text(
            option2_text.upper(),
            y_position=bottom_text_y,
            duration=self.total_duration - img2_start_time,  # Duration until the end
            start_time=img2_start_time,
            fontsize=80,
            color="white",
            stroke_color="black",
            stroke_width=3
        )
        clips.append(option2_txt)

        # Add dividing line
        line_thickness = 8
        black_line = ColorClip((self.width, line_thickness), color=(0, 0, 0)).set_duration(self.total_duration)
        black_line = black_line.set_position((0, self.middle_y - line_thickness // 2))
        clips.append(black_line)

        # Add small black circle in the middle of the dividing line
        circle_diameter = 50  # Adjust size as needed
        circle_size = (circle_diameter, circle_diameter)

        # Create a transparent image with a black circle
        circle_img = Image.new("RGBA", circle_size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(circle_img)
        draw.ellipse((0, 0, circle_diameter, circle_diameter), fill=(0, 0, 0, 255))
        circle_array = np.array(circle_img)

        # Create ImageClip for the circle
        circle_clip = ImageClip(circle_array).set_duration(self.total_duration)
        # Position the circle in the middle of the dividing line
        circle_position = (self.width // 2 - circle_diameter // 2, self.middle_y - circle_diameter // 2)
        clips.append(circle_clip.set_position(circle_position))

        # Add countdown timer after initial_pause + timer_delay + countdown_wait
        countdown_start_time = initial_pause + timer_delay + countdown_wait
        timer_clips = self.create_timer_clips(countdown_start_time, countdown_seconds, self.total_duration)
        clips.extend(timer_clips)

        # Add Percentage 1 Text ("1.02%") in Yellow after countdown
        percent1_txt = self.create_styled_text(
            f"{percent1:.2f}%",
            y_position=top_percentage_y,
            duration=percentage_duration,  # 3 seconds
            start_time=countdown_start_time + countdown_seconds,
            fontsize=100,  # Increased font size
            color="yellow",
            stroke_color="black",
            stroke_width=2
        )
        clips.append(percent1_txt)

        # Add Percentage 2 Text ("999.72%") in Yellow above the bottom text after countdown
        percent2_txt = self.create_styled_text(
            f"{percent2:.2f}%",
            y_position=bottom_percentage_y,
            duration=percentage_duration,  # 3 seconds
            start_time=countdown_start_time + countdown_seconds,
            fontsize=100,  # Increased font size
            color="yellow",
            stroke_color="black",
            stroke_width=2
        )
        clips.append(percent2_txt)

        # No additional buffer_time; video will end after percentages are hidden

        # Create final video
        final_clip = CompositeVideoClip(clips, size=(self.width, self.height))

        # Render the video
        final_clip.write_videofile(
            "would_you_rather.mp4",
            fps=30,
            codec="libx264",
            audio=False,
            threads=4,
            preset="medium",
        )
        messagebox.showinfo("Success", "Video generated successfully!")

    def run(self):
        self.window.mainloop()


if __name__ == "__main__":
    app = WouldYouRatherGenerator()
    app.run()