Video-generator / app.py
parthraninga's picture
Upload 8 files
1dfc9df verified
import gradio as gr
import google.generativeai as genai
import os
import re
import subprocess
import tempfile
import shutil
from pathlib import Path
import sys
# 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
genai.configure(api_key=api_key)
model = genai.GenerativeModel(
model_name="gemini-1.5-flash", # Using more stable model for deployment
generation_config={
"temperature": 0.3,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 8000, # Reduced for better performance
}
)
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 plan for Manim animation
planning_prompt = f"""
You are a professional with deep expertise in Manim CE 0.18.0.
Your task is to design a presentation-style video using Manim for the topic: "{topic}"
Guidelines:
- The video should consist of **slides of text** with **smooth transitions** between them.
- Structure the scene logically with 3-5 main points maximum.
- Target duration: {duration_minutes} minute(s).
- Use **simple text objects only**, no equations, graphs, or complex animations.
- Keep text concise and readable.
- Include details like:
- Text to be shown (keep it short and clear)
- When to fade in/out
- Slide duration (2-4 seconds per slide)
- Transitions (FadeIn, FadeOut, Transform)
- Do not output any code here β€” only the **presentation plan**, step by step.
Output Format:
Scene 1:
- Text: "Title: {topic}"
- Action: FadeIn
- Duration: 3 seconds
Scene 2:
- Text: "Key Point 1: [brief description]"
- Action: Transform from previous
- Duration: 4 seconds
...
"""
plan_response = model.generate_content(planning_prompt)
plan = plan_response.text.strip()
# Step 2: Generate Manim code based on the plan
code_prompt = f"""
Using this animation plan:
{plan}
Write a complete Manim CE 0.18.0 compatible Python file with a class called `VideoScene` that inherits from Scene.
Critical Requirements:
- Import all necessary modules: from manim import *
- Use ONLY basic text objects and simple transitions
- Background should be WHITE: self.camera.background_color = WHITE
- Text should be BLACK for contrast
- Keep text size reasonable (font_size=24 to 36)
- Use FadeIn, FadeOut, and Transform only
- Add self.clear() between slides to avoid overlapping text
- Include proper self.wait() durations
- Make sure the class is properly indented and structured
- NO complex animations, NO equations, NO images
- Keep it simple and clean
Example structure:
```python
from manim import *
class VideoScene(Scene):
def construct(self):
self.camera.background_color = WHITE
# Title slide
title = Text("Your Title", font_size=36, color=BLACK)
self.play(FadeIn(title))
self.wait(3)
self.play(FadeOut(title))
self.clear()
# Next slide...
```
Output: Just the complete Python code, no explanations.
"""
final_code = model.generate_content(code_prompt)
raw_code = final_code.text.strip()
# Clean the code
cleaned_code = re.sub(r"^(```|''')python\s*", "", raw_code)
cleaned_code = re.sub(r"(```|''')\s*$", "", cleaned_code)
# Create temporary directory for this generation
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Save the generated code
manim_file = temp_path / "generated_video.py"
with open(manim_file, "w", encoding="utf-8") as f:
f.write(cleaned_code)
# Run manim to generate video with error handling
try:
# Use low quality for faster generation in cloud environment
result = subprocess.run([
"manim", "-pql", "--fps", "15", str(manim_file), "VideoScene"
],
cwd=temp_dir,
capture_output=True,
text=True,
check=True,
timeout=120 # 2 minute timeout
)
# Find the generated video file
media_dir = temp_path / "media"
video_files = list(media_dir.rglob("*.mp4"))
if video_files:
video_file = video_files[0]
# Copy to a location accessible by Gradio
output_file = f"video_{abs(hash(topic)) % 10000}.mp4"
shutil.copy2(video_file, output_file)
success_msg = f"βœ… Video generated successfully!\n\n**Plan:**\n{plan}\n\n**Generated Code:**\n```python\n{cleaned_code}\n```"
return output_file, success_msg
else:
error_msg = f"❌ No video file found after generation.\n\n**Plan:**\n{plan}\n\n**Generated Code:**\n```python\n{cleaned_code}\n```\n\n**Manim Output:**\n{result.stdout}"
return None, error_msg
except subprocess.TimeoutExpired:
return None, f"❌ Video generation timed out. Try a shorter duration or simpler topic.\n\n**Plan:**\n{plan}"
except subprocess.CalledProcessError as e:
error_msg = f"❌ Manim generation failed:\n{e.stderr}\n\n**Plan:**\n{plan}\n\n**Generated Code:**\n```python\n{cleaned_code}\n```"
return None, error_msg
except Exception as e:
return None, f"❌ Unexpected error: {str(e)}"
# Create Gradio interface
with gr.Blocks(title="AI Video Generator", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎬 AI Video Generator
Generate educational videos using AI and Manim animations. Simply enter a topic and get a professional presentation-style video!
**Features:**
- πŸ€– AI-powered content generation using Gemini
- 🎨 Professional Manim animations
- ⏱️ Customizable duration (1-3 minutes)
- πŸ“± Clean presentation style
**Note:** Video generation may take 1-3 minutes depending on complexity.
""")
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
- Avoid overly complex subjects
- Shorter durations work better
- Be patient - generation takes time
### 🎯 Great Topic Examples:
- "Introduction to Python"
- "Basic Data Structures"
- "How Photosynthesis Works"
- "Understanding Fractions"
- "Solar System Overview"
""")
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",
interactive=False
)
def update_status(message):
return message
def generate_with_status(topic, duration):
yield None, "πŸ”„ Starting video generation...", "πŸ”„ Initializing AI content creation..."
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__":
demo.launch(
share=False,
server_name="0.0.0.0",
server_port=7860,
show_error=True
)