Video_generator / app.py
parthraninga's picture
Update app.py
03ec8a3 verified
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
)