Video-generator / app.py
parthraninga's picture
Upload 8 files
1dfc9df verified
raw
history blame
9.79 kB
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
)