import gradio as gr import google.generativeai as genai import os import re import tempfile import shutil from pathlib import Path import time from moviepy.editor import * from PIL import Image, ImageDraw, ImageFont import numpy as np # Check if API key is available api_key = os.getenv("GEMINI_API_KEY") if not api_key: print("⚠️ Warning: GEMINI_API_KEY not found in environment variables") print("Please set your Gemini API key in the Hugging Face Spaces secrets") # Configure Gemini API if api_key: genai.configure(api_key=api_key) model = genai.GenerativeModel( model_name="gemini-1.5-flash", generation_config={ "temperature": 0.3, "top_p": 0.95, "top_k": 40, "max_output_tokens": 8000, } ) def create_text_clip(text, duration=3, fontsize=48, color='black', bg_color='white', size=(1280, 720)): """Create a video clip with text using PIL and MoviePy""" # Create image with text img = Image.new('RGB', size, bg_color) draw = ImageDraw.Draw(img) # Try to use a default font, fallback to basic if not available try: font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", fontsize) except: try: font = ImageFont.truetype("arial.ttf", fontsize) except: font = ImageFont.load_default() # Calculate text position (centered) bbox = draw.textbbox((0, 0), text, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1] position = ((size[0] - text_width) // 2, (size[1] - text_height) // 2) # Draw text draw.text(position, text, fill=color, font=font) # Convert PIL image to numpy array img_array = np.array(img) # Create video clip clip = ImageClip(img_array, duration=duration) return clip def generate_video(topic, duration_minutes=1): if not api_key: return None, "❌ Error: GEMINI_API_KEY not configured. Please set it in Hugging Face Spaces secrets." try: # Step 1: Generate content plan planning_prompt = f""" Create a simple presentation plan for the topic: "{topic}" Requirements: - Create 10-11 slides maximum for {duration_minutes} minute(s) - Each slide should have ONE clear, concise message (max 10 words) - Start with a title slide - Include 3-4 key points about the topic - End with a conclusion slide - Keep text simple and readable Format your response as: Slide 1: [Title text][details in points] Slide 2: [Key point 1][details in points] Slide 3: [Key point 2][details in points] Slide 4: [Key point 3][details in points] Slide 5: [Conclusion][details in points] Example for "Python Programming": Slide 1 – Python Programming Basics What is Python? High-level, general-purpose language Popular for web, data, AI, automation, and more Slide 2 – Why Python? Versatile and widely used in multiple industries Large community and active development Open-source and free to use Slide 3 – Easy to Learn and Read English-like syntax for easy understanding Minimal boilerplate code Example: print("Hello, World!") Slide 4 – Python's Key Features Cross-platform compatibility Large standard library Object-oriented and functional programming support Interactive interpreter Slide 5 – Powerful Libraries Available Data Analysis: NumPy, Pandas Visualization: Matplotlib, Seaborn Web Development: Django, Flask Machine Learning: TensorFlow, PyTorch Slide 6 – Popular Use Cases Web and app development Data science and analytics Artificial intelligence and machine learning Game development Automation and scripting Slide 7 – Great for Beginners Clear documentation and tutorials Friendly learning curve Lots of free resources available online Slide 8 – Tools You’ll Need Python interpreter (python.org) Code editor (VS Code, PyCharm, Sublime Text) Optional: Jupyter Notebook for interactive coding Slide 9 – Start Your Python Journey! Install Python and set up your editor Practice with small programs daily Work on mini-projects to gain confidence Join coding communities for support Slide 10 – Resources to Learn Python Official Python documentation FreeCodeCamp, Real Python, W3Schools Online coding platforms (HackerRank, LeetCode) """ plan_response = model.generate_content(planning_prompt) plan = plan_response.text.strip() # Parse the slides from the plan slides = [] for line in plan.split('\n'): if line.strip() and 'Slide' in line and ':' in line: slide_text = line.split(':', 1)[1].strip() if slide_text: slides.append(slide_text) if not slides: return None, f"❌ Could not parse slides from plan:\n{plan}" # Create video clips clips = [] slide_duration = max(3, (duration_minutes * 60) / len(slides)) # At least 3 seconds per slide for i, slide_text in enumerate(slides): if i == 0: # Title slide clip = create_text_clip(slide_text, duration=slide_duration, fontsize=56, color='navy') else: # Content slides clip = create_text_clip(slide_text, duration=slide_duration, fontsize=42, color='darkblue') clips.append(clip) # Concatenate all clips final_video = concatenate_videoclips(clips, method="compose") # Save video timestamp = int(time.time()) output_file = f"video_{timestamp}.mp4" final_video.write_videofile( output_file, fps=24, codec='libx264', audio_codec='aac' if final_video.audio else None, temp_audiofile='temp-audio.m4a', remove_temp=True ) # Clean up final_video.close() for clip in clips: clip.close() success_msg = f"""✅ Video generated successfully using MoviePy! **📋 Slides Created:** {chr(10).join([f"{i+1}. {slide}" for i, slide in enumerate(slides)])} **🎬 Video Details:** - Duration: {duration_minutes} minute(s) - Slides: {len(slides)} - Resolution: 1280x720 - FPS: 24 **📝 Original Plan:** {plan} """ return output_file, success_msg except Exception as e: return None, f"❌ Error generating video: {str(e)}" # Create Gradio interface with gr.Blocks(title="AI Video Generator", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 🎬 AI Video Generator (MoviePy Edition) Generate educational videos using AI and MoviePy! **Features:** - 🤖 AI-powered content generation using Gemini - 🎥 Clean slide-based videos using MoviePy - ⏱️ Customizable duration (1-3 minutes) - 📱 Simple, professional presentation style - ☁️ Fully compatible with Hugging Face Spaces **Note:** Video generation takes 30-90 seconds. """) with gr.Row(): with gr.Column(scale=2): topic_input = gr.Textbox( label="📝 Video Topic", placeholder="Enter an educational topic (e.g., 'Introduction to Python', 'Basic Math Concepts')", value="Introduction to Python Programming", lines=2 ) duration_input = gr.Slider( minimum=1, maximum=3, value=1, step=1, label="⏱️ Duration (minutes)", info="Shorter durations generate faster" ) generate_btn = gr.Button("🚀 Generate Video", variant="primary", size="lg") with gr.Column(scale=1): gr.Markdown(""" ### 💡 Tips for Best Results: - Use clear, educational topics - Simple topics work better - Shorter durations are faster - Educational content works best ### 🎯 Great Topic Examples: - "Introduction to Python" - "Basic Math Operations" - "How Plants Grow" - "Understanding Colors" - "Solar System Facts" - "Healthy Eating Tips" """) with gr.Row(): with gr.Column(): video_output = gr.Video( label="🎥 Generated Video", height=400 ) with gr.Column(): log_output = gr.Textbox( label="📋 Generation Details", lines=15, max_lines=25, show_copy_button=True, placeholder="Generation logs and AI-created content will appear here..." ) # Progress indicator with gr.Row(): status_text = gr.Textbox( label="📊 Status", value="Ready to generate video - MoviePy edition loaded", interactive=False ) def generate_with_status(topic, duration): yield None, "🔄 Starting video generation...", "🔄 Generating content with AI..." try: result_video, result_log = generate_video(topic, duration) if result_video: yield result_video, result_log, "✅ Video generated successfully!" else: yield None, result_log, "❌ Video generation failed" except Exception as e: yield None, f"❌ Error: {str(e)}", "❌ Generation failed with error" generate_btn.click( fn=generate_with_status, inputs=[topic_input, duration_input], outputs=[video_output, log_output, status_text], show_progress=True ) if __name__ == "__main__": print("🎬 Starting AI Video Generator with MoviePy...") demo.launch( server_name="0.0.0.0" if os.getenv("SPACE_ID") else "127.0.0.1", server_port=7860, show_error=True )