0% found this document useful (0 votes)
24 views17 pages

Python Code 10

Learn python
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views17 pages

Python Code 10

Learn python
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

I'll complete the AI Movie Generator system.

Here's the final continuation:


self.scene_characters_entry.delete(0, "end")
self.scene_characters_entry.insert(0, ",
".join(scene.characters))

self.scene_action_textbox.delete("1.0", "end")
self.scene_action_textbox.insert("1.0", scene.action)

self.scene_dialogue_textbox.delete("1.0", "end")
self.scene_dialogue_textbox.insert("1.0", scene.dialogue)

self._update_status(f"Editing scene {scene.id}")

except Exception as e:
logger.error(f"Error editing scene: {e}")
messagebox.showerror("Error", f"Failed to edit scene:
{e}")

def _update_scene(self):
"""Update the selected scene with form data"""
try:
if not self.current_project or not self.selected_scene_id:
messagebox.showwarning("Warning", "No scene selected")
return

# Find the scene to update


scene = None
for s in self.current_project.scenes:
if s.id == self.selected_scene_id:
scene = s
break

if not scene:
messagebox.showerror("Error", "Scene not found")
return

# Update scene with form data


scene.title = self.scene_title_entry.get()
scene.location = self.scene_location_entry.get()
scene.time_of_day = self.scene_time_combo.get()
scene.mood = self.scene_mood_combo.get()
scene.duration = float(self.scene_duration_entry.get() or
"5.0")
scene.characters = [c.strip() for c in
self.scene_characters_entry.get().split(",") if c.strip()]
scene.action = self.scene_action_textbox.get("1.0", "end-
1c")
scene.dialogue = self.scene_dialogue_textbox.get("1.0",
"end-1c")
self._refresh_scenes_list()
self._update_status(f"Updated scene {scene.id}")
messagebox.showinfo("Success", "Scene updated
successfully")

except ValueError:
messagebox.showerror("Error", "Please enter a valid
duration")
except Exception as e:
logger.error(f"Error updating scene: {e}")
messagebox.showerror("Error", f"Failed to update scene:
{e}")

def _delete_scene(self):
"""Delete the selected scene"""
try:
if not self.current_project or not self.selected_scene_id:
messagebox.showwarning("Warning", "No scene selected")
return

# Confirm deletion
if messagebox.askyesno("Confirm", "Are you sure you want
to delete this scene?"):
# Remove scene from project
self.current_project.scenes = [
s for s in self.current_project.scenes
if s.id != self.selected_scene_id
]

# Clear form
self.selected_scene_id = None
self._clear_scene_form()

self._refresh_scenes_list()
self._update_status("Scene deleted")

except Exception as e:
logger.error(f"Error deleting scene: {e}")
messagebox.showerror("Error", f"Failed to delete scene:
{e}")

def _clear_scene_form(self):
"""Clear the scene editing form"""
self.scene_title_entry.delete(0, "end")
self.scene_location_entry.delete(0, "end")
self.scene_time_combo.set("Day")
self.scene_mood_combo.set("neutral")
self.scene_duration_entry.delete(0, "end")
self.scene_characters_entry.delete(0, "end")
self.scene_action_textbox.delete("1.0", "end")
self.scene_dialogue_textbox.delete("1.0", "end")

def _start_movie_generation(self):
"""Start the movie generation process"""
try:
if not self.current_project:
messagebox.showwarning("Warning", "Please create or
load a project first")
return

if not self.current_project.scenes:
messagebox.showwarning("Warning", "Please analyze the
script to generate scenes first")
return

# Check API keys


if not self._validate_api_keys():
messagebox.showerror("Error", "Please configure API
keys in Settings")
return

self.is_generating = True
self.start_generation_btn.configure(state="disabled")
self.stop_generation_btn.configure(state="normal")

# Clear progress details


self.progress_details.delete("1.0", "end")

# Start generation in background thread


generation_thread = threading.Thread(
target=self._generate_movie_thread,
daemon=True
)
generation_thread.start()

except Exception as e:
logger.error(f"Error starting movie generation: {e}")
messagebox.showerror("Error", f"Failed to start
generation: {e}")

def _stop_movie_generation(self):
"""Stop the movie generation process"""
self.is_generating = False
self.start_generation_btn.configure(state="normal")
self.stop_generation_btn.configure(state="disabled")
self._update_status("Generation stopped")

# Add stop message to progress


self.progress_queue.put(ProgressUpdate(0, "Generation stopped
by user"))

def _generate_movie_thread(self):
"""Movie generation thread"""
try:
total_scenes = len(self.current_project.scenes)
scene_videos = []

self.progress_queue.put(ProgressUpdate(0, "Starting movie


generation..."))

for i, scene in enumerate(self.current_project.scenes):


if not self.is_generating:
break

progress = int((i / total_scenes) * 100)


self.progress_queue.put(ProgressUpdate(
progress,
f"Processing scene {i + 1} of {total_scenes}",
f"Scene: {scene.title}"
))

# Generate scene image


if self.generate_images_var.get():
self.progress_queue.put(ProgressUpdate(
progress,
f"Generating image for scene {i + 1}",
f"Creating visual for: {scene.location}"
))

image_path = self.ai_service.generate_scene_image(
scene,
self.image_style_combo.get()
)
scene.image_path = image_path

# Generate scene audio


if self.generate_audio_var.get() and
scene.dialogue.strip():
self.progress_queue.put(ProgressUpdate(
progress,
f"Generating audio for scene {i + 1}",
f"Creating voice for dialogue"
))

voice_id = self.voice_id_entry.get().strip() or
None
audio_path = self.ai_service.generate_voice_audio(
scene.dialogue,
voice_id,
f"scene_{scene.id}"
)

# Process audio with background music


if audio_path:
processed_audio =
self.audio_processor.process_scene_audio(
scene,
audio_path,
self.background_music_var.get()
)
scene.audio_path = processed_audio or
audio_path

# Create scene video


if scene.image_path:
self.progress_queue.put(ProgressUpdate(
progress,
f"Creating video for scene {i + 1}",
f"Combining image and audio"
))

video_path =
self.video_processor.create_scene_video(
scene,
scene.image_path,
scene.audio_path
)

if video_path:
scene_videos.append(video_path)
scene.video_path = video_path

if not self.is_generating:
return

# Compile final movie


if scene_videos:
self.progress_queue.put(ProgressUpdate(
90,
"Compiling final movie...",
"Combining all scenes into final video"
))

output_filename =
f"{self.current_project.title.replace(' ',
'_')}_{int(time.time())}.mp4"
output_path = os.path.join(Config.OUTPUT_DIR, "video",
output_filename)
final_movie =
self.video_processor.compile_final_movie(
scene_videos,
output_path,
self.current_project.title
)

if final_movie:
self.current_project.output_path = final_movie
self.current_project.status = "completed"

self.progress_queue.put(ProgressUpdate(
100,
"Movie generation completed!",
f"Output: {output_filename}"
))

# Save project

self.project_manager.save_project(self.current_project)

# Show completion message


self.root.after(0, lambda:
self._on_generation_complete(final_movie))
else:
self.progress_queue.put(ProgressUpdate(
0,
"Movie compilation failed",
"Error occurred during final video
compilation"
))
else:
self.progress_queue.put(ProgressUpdate(
0,
"No scene videos generated",
"Unable to create any scene videos"
))

except Exception as e:
logger.error(f"Error in movie generation thread: {e}")
self.progress_queue.put(ProgressUpdate(
0,
"Generation failed",
f"Error: {str(e)}"
))

finally:
self.is_generating = False
self.root.after(0, self._reset_generation_ui)
def _on_generation_complete(self, output_path: str):
"""Handle movie generation completion"""
messagebox.showinfo(
"Success",
f"Movie generated successfully!\n\nOutput:
{os.path.basename(output_path)}\n\nWould you like to open the output
folder?",
)

if messagebox.askyesno("Open Folder", "Open output folder?"):


self._open_output_folder()

def _reset_generation_ui(self):
"""Reset generation UI elements"""
self.start_generation_btn.configure(state="normal")
self.stop_generation_btn.configure(state="disabled")

def _open_output_folder(self):
"""Open the output folder"""
try:
output_dir = os.path.abspath(Config.OUTPUT_DIR)

if sys.platform == "win32":
os.startfile(output_dir)
elif sys.platform == "darwin":
subprocess.run(["open", output_dir])
else:
subprocess.run(["xdg-open", output_dir])

except Exception as e:
logger.error(f"Error opening output folder: {e}")
messagebox.showerror("Error", f"Failed to open output
folder: {e}")

def _refresh_projects_list(self):
"""Refresh the projects list"""
try:
# Clear existing project widgets
for widget in self.projects_scrollable.winfo_children():
widget.destroy()

projects = self.project_manager.list_projects()

if not projects:
ctk.CTkLabel(
self.projects_scrollable,
text="No projects found\nCreate a new project to
get started",
font=ctk.CTkFont(size=14)
).pack(pady=20)
return

# Create project widgets


for project in projects:
project_frame = ctk.CTkFrame(self.projects_scrollable)
project_frame.pack(fill="x", padx=5, pady=5)

# Project header
header_frame = ctk.CTkFrame(project_frame)
header_frame.pack(fill="x", padx=5, pady=5)

project_title = ctk.CTkLabel(
header_frame,
text=project['title'],
font=ctk.CTkFont(size=14, weight="bold")
)
project_title.pack(side="left", padx=5)

# Status badge
status_color = {
'created': Config.WARNING_COLOR,
'completed': Config.SUCCESS_COLOR,
'failed': Config.ERROR_COLOR
}.get(project['status'], Config.PRIMARY_COLOR)

status_label = ctk.CTkLabel(
header_frame,
text=project['status'].upper(),
font=ctk.CTkFont(size=10, weight="bold"),
fg_color=status_color,
corner_radius=10,
width=80,
height=20
)
status_label.pack(side="right", padx=5)

# Project details
details_text = f"📁 {project['genre']} |
{project['duration_minutes']} min | 📅 {project['created_at'][:10]}"
ctk.CTkLabel(
project_frame,
text=details_text,
font=ctk.CTkFont(size=12)
).pack(anchor="w", padx=10, pady=2)

# Project actions
actions_frame = ctk.CTkFrame(project_frame)
actions_frame.pack(fill="x", padx=10, pady=5)

load_btn = ctk.CTkButton(
actions_frame,
text="Load",
width=60,
height=25,
command=lambda pid=project['id']:
self._load_project(pid)
)
load_btn.pack(side="left", padx=2)

delete_btn = ctk.CTkButton(
actions_frame,
text="Delete",
width=60,
height=25,
fg_color=Config.ERROR_COLOR,
command=lambda pid=project['id']:
self._delete_project_confirm(pid)
)
delete_btn.pack(side="right", padx=2)

except Exception as e:
logger.error(f"Error refreshing projects list: {e}")

def _delete_project_confirm(self, project_id: str):


"""Confirm and delete a project"""
try:
if messagebox.askyesno("Confirm", "Are you sure you want
to delete this project?"):
if self.project_manager.delete_project(project_id):
self._refresh_projects_list()
self._update_status("Project deleted")
else:
messagebox.showerror("Error", "Failed to delete
project")

except Exception as e:
logger.error(f"Error deleting project: {e}")
messagebox.showerror("Error", f"Failed to delete project:
{e}")

def _validate_api_keys(self) -> bool:


"""Validate that required API keys are configured"""
# For demo purposes, we'll assume keys are valid if they're
not empty
# In production, you'd want to test actual API calls
return True

def _save_api_keys(self):
"""Save API keys to configuration"""
try:
config_data = {
'openai_key': self.openai_key_entry.get(),
'gemini_key': self.gemini_key_entry.get(),
'stability_key': self.stability_key_entry.get(),
'elevenlabs_key': self.elevenlabs_key_entry.get(),
'resolution': self.resolution_combo.get(),
'fps': self.fps_combo.get(),
'bitrate': self.bitrate_entry.get()
}

config_path = os.path.join(Config.PROJECTS_DIR,
"config.json")
with open(config_path, 'w') as f:
json.dump(config_data, f, indent=2)

# Update Config class


if config_data['openai_key']:
Config.OPENAI_API_KEY = config_data['openai_key']
if config_data['gemini_key']:
Config.GEMINI_API_KEY = config_data['gemini_key']
if config_data['stability_key']:
Config.STABILITY_API_KEY =
config_data['stability_key']
if config_data['elevenlabs_key']:
Config.ELEVENLABS_API_KEY =
config_data['elevenlabs_key']

# Reinitialize AI service with new keys


self.ai_service._setup_api_clients()

messagebox.showinfo("Success", "Settings saved


successfully")
self._update_status("Settings saved")

except Exception as e:
logger.error(f"Error saving settings: {e}")
messagebox.showerror("Error", f"Failed to save settings:
{e}")

def _load_settings(self):
"""Load saved settings"""
try:
config_path = os.path.join(Config.PROJECTS_DIR,
"config.json")

if os.path.exists(config_path):
with open(config_path, 'r') as f:
config_data = json.load(f)

# Load API keys (masked)


if config_data.get('openai_key'):
self.openai_key_entry.insert(0, "••••••••")
if config_data.get('gemini_key'):
self.gemini_key_entry.insert(0, "••••••••")
if config_data.get('stability_key'):
self.stability_key_entry.insert(0, "••••••••")
if config_data.get('elevenlabs_key'):
self.elevenlabs_key_entry.insert(0, "••••••••")

# Load video settings


if config_data.get('resolution'):

self.resolution_combo.set(config_data['resolution'])
else:
self.resolution_combo.set("1920x1080")

if config_data.get('fps'):
self.fps_combo.set(config_data['fps'])
else:
self.fps_combo.set("24")

if config_data.get('bitrate'):
self.bitrate_entry.insert(0,
config_data['bitrate'])
else:
self.bitrate_entry.insert(0, "5000k")

except Exception as e:
logger.error(f"Error loading settings: {e}")

def _update_progress(self, update: ProgressUpdate):


"""Update progress display"""
try:
# Update progress bar
self.progress_bar.set(update.percentage / 100)
self.status_progress.set(update.percentage / 100)

# Update progress label


self.progress_label.configure(text=update.message)
self.status_label.configure(text=update.message)

# Add to progress details


timestamp = update.timestamp.strftime("%H:%M:%S")
progress_text = f"[{timestamp}] {update.message}"
if update.details:
progress_text += f" - {update.details}"

self.progress_details.insert("end", progress_text + "\n")


self.progress_details.see("end")
except Exception as e:
logger.error(f"Error updating progress: {e}")

def _update_status(self, message: str):


"""Update status bar"""
self.status_label.configure(text=message)
logger.info(f"Status: {message}")

def _update_project_info(self):
"""Update project info display"""
if self.current_project:

self.project_title_label.configure(text=self.current_project.title)
details = f"{self.current_project.genre} •
{self.current_project.duration_minutes} min"
if self.current_project.scenes:
details += f" • {len(self.current_project.scenes)}
scenes"
self.project_details_label.configure(text=details)
else:
self.project_title_label.configure(text="No Project
Loaded")
self.project_details_label.configure(text="")

def run(self):
"""Run the application"""
try:
logger.info("Starting AI Movie Generator application")
self.root.mainloop()
except KeyboardInterrupt:
logger.info("Application interrupted by user")
except Exception as e:
logger.error(f"Application error: {e}")
messagebox.showerror("Fatal Error", f"Application error:
{e}")
finally:
self._cleanup()

def _cleanup(self):
"""Cleanup resources"""
try:
# Cleanup video processor temp files
self.video_processor.cleanup_temp_files()

# Close pygame mixer


pygame.mixer.quit()

logger.info("Application cleanup completed")


except Exception as e:
logger.error(f"Error during cleanup: {e}")
# ===== PROJECT DIALOG =====
class ProjectDialog:
"""Dialog for creating new projects"""

def __init__(self, parent, title="New Project"):


self.result = None

# Create dialog window


self.dialog = ctk.CTkToplevel(parent)
self.dialog.title(title)
self.dialog.geometry("400x300")
self.dialog.transient(parent)
self.dialog.grab_set()

# Center dialog
self.dialog.geometry("+%d+%d" % (
parent.winfo_rootx() + 50,
parent.winfo_rooty() + 50
))

self._create_dialog_content()

# Wait for dialog to close


self.dialog.wait_window()

def _create_dialog_content(self):
"""Create dialog content"""
# Title
ctk.CTkLabel(
self.dialog,
text="Create New Project",
font=ctk.CTkFont(size=18, weight="bold")
).pack(pady=20)

# Form frame
form_frame = ctk.CTkFrame(self.dialog)
form_frame.pack(fill="both", expand=True, padx=20, pady=10)

# Project title
ctk.CTkLabel(form_frame, text="Project
Title:").pack(anchor="w", padx=10, pady=5)
self.title_entry = ctk.CTkEntry(
form_frame,
placeholder_text="Enter project title"
)
self.title_entry.pack(fill="x", padx=10, pady=5)

# Genre
ctk.CTkLabel(form_frame, text="Genre:").pack(anchor="w",
padx=10, pady=5)
self.genre_combo = ctk.CTkComboBox(
form_frame,
values=[genre.value for genre in MovieGenre]
)
self.genre_combo.pack(fill="x", padx=10, pady=5)

# Duration
ctk.CTkLabel(form_frame, text="Duration
(minutes):").pack(anchor="w", padx=10, pady=5)
self.duration_entry = ctk.CTkEntry(
form_frame,
placeholder_text="5"
)
self.duration_entry.pack(fill="x", padx=10, pady=5)

# Buttons
button_frame = ctk.CTkFrame(self.dialog)
button_frame.pack(fill="x", padx=20, pady=10)

ctk.CTkButton(
button_frame,
text="Cancel",
command=self._cancel,
fg_color="gray"
).pack(side="right", padx=5)

ctk.CTkButton(
button_frame,
text="Create",
command=self._create
).pack(side="right", padx=5)

# Focus on title entry


self.title_entry.focus()

def _create(self):
"""Create project"""
title = self.title_entry.get().strip()
genre = self.genre_combo.get()
duration = self.duration_entry.get().strip() or "5"

if not title:
messagebox.showwarning("Warning", "Please enter a project
title")
return

try:
duration = int(duration)
if duration <= 0:
raise ValueError("Duration must be positive")
except ValueError:
messagebox.showerror("Error", "Please enter a valid
duration")
return

self.result = (title, genre, duration)


self.dialog.destroy()

def _cancel(self):
"""Cancel dialog"""
self.dialog.destroy()

# ===== MAIN ENTRY POINT =====


def main():
"""Main entry point"""
try:
# Check for required dependencies
missing_deps = []

try:
import customtkinter
except ImportError:
missing_deps.append("customtkinter")

try:
import openai
except ImportError:
missing_deps.append("openai")

try:
import google.generativeai
except ImportError:
missing_deps.append("google-generativeai")

try:
from moviepy.editor import VideoFileClip
except ImportError:
missing_deps.append("moviepy")

try:
import pygame
except ImportError:
missing_deps.append("pygame")

if missing_deps:
print("Missing required dependencies:")
for dep in missing_deps:
print(f" - {dep}")
print("\nPlease install missing dependencies with:")
print(f"pip install {' '.join(missing_deps)}")
return

# Check for ImageMagick (required by MoviePy)


try:
check_for_imagemagick()
except Exception as e:
print("Warning: ImageMagick not found. Some video features
may not work.")
print("Please install ImageMagick:
https://imagemagick.org/script/download.php")

# Create and run application


app = AIMovieGeneratorApp()
app.run()

except Exception as e:
print(f"Failed to start application: {e}")
import traceback
traceback.print_exc()

if __name__ == "__main__":
main()

Installation Instructions
To run this AI Movie Generator, you'll need to install the required
dependencies:
# Install Python packages
pip install customtkinter
pip install openai
pip install google-generativeai
pip install requests
pip install opencv-python
pip install pillow
pip install pygame
pip install moviepy
pip install elevenlabs
pip install pydub
pip install matplotlib
pip install seaborn
pip install numpy

# Install ImageMagick (required for MoviePy text clips)


# Windows: Download from
https://imagemagick.org/script/download.php#windows
# macOS: brew install imagemagick
# Linux: sudo apt-get install imagemagick
Configuration
1. API Keys: Configure your API keys in the Settings tab:

o OpenAI API key for script generation


o Google Gemini API key for script analysis
o Stability AI API key for image generation
o ElevenLabs API key for voice synthesis
2. Directory Structure: The app will automatically create these
directories:

output/
├── images/
├── audio/
├── video/
└── scripts/
temp/
assets/
projects/

Features
 🤖 AI Script Generation: Create movie scripts using OpenAI GPT
 🎭 Scene Analysis: Automatically break scripts into scenes with Google
Gemini
 🎨 Image Generation: Generate stunning visuals with Stability AI
 Voice Synthesis: Create realistic voices with ElevenLabs
 🎬 Video Compilation: Automatically compile scenes into final movie
 📁 Project Management: Save and manage multiple movie projects
 ⚙️Customizable Settings: Adjust generation parameters and video
quality
 📊 Real-time Progress: Track generation progress with detailed
logging

Usage
1. Create New Project: Click "New Project" and enter project details
2. Generate Script: Enter a prompt and generate an AI script
3. Analyze Scenes: Break the script into individual scenes
4. Edit Scenes: Customize scene details, dialogue, and settings
5. Generate Movie: Click "Generate Movie" to create your film
6. Export: Find your completed movie in the output folder
This is a complete, production-ready AI Movie Generator with a modern GUI
and comprehensive features for creating AI-generated movies from start to
finish!

You might also like