Spaces:
Configuration error
Configuration error
| """ | |
| Animetrix AI - Gradio Interface for Hugging Face Spaces | |
| Educational Animation Generator powered by AI and Manim | |
| """ | |
| import gradio as gr | |
| import os | |
| import sys | |
| from pathlib import Path | |
| import asyncio | |
| import shutil | |
| # Add backend to path | |
| backend_path = Path(__file__).parent / "backend" | |
| sys.path.insert(0, str(backend_path)) | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| # Configure FFmpeg for Hugging Face Spaces (already available in system PATH) | |
| if shutil.which('ffmpeg') is None: | |
| print("β οΈ FFmpeg not found - installing...") | |
| os.system("apt-get update && apt-get install -y ffmpeg") | |
| # Import backend functions | |
| from teacher import generate_outline | |
| from compiler import generate_manim_code | |
| from runner import render_scene | |
| from narrator import generate_narration_audio, merge_audio_video | |
| async def generate_animation(prompt, progress=gr.Progress()): | |
| """Generate educational animation from text prompt""" | |
| try: | |
| # Validate input | |
| if not prompt or len(prompt.strip()) < 10: | |
| return None, "β Please enter a more detailed prompt (at least 10 characters)" | |
| progress(0, desc="π― Initializing...") | |
| # Step 1: Generate outline | |
| progress(0.1, desc="π Planning animation structure...") | |
| outline = await generate_outline(prompt) | |
| # Step 2: Generate per-step narration | |
| progress(0.3, desc="ποΈ Generating narration audio...") | |
| steps = outline.get("steps", []) | |
| step_audio_paths = [] | |
| for idx, step in enumerate(steps): | |
| narration = step.get("narration", "") | |
| if narration: | |
| audio_filename = f"step_{idx+1}_narration.mp3" | |
| audio_path = generate_narration_audio(narration, filename=audio_filename) | |
| step_audio_paths.append(audio_path) | |
| progress(0.3 + (0.1 * (idx+1) / len(steps)), desc=f"ποΈ Narration {idx+1}/{len(steps)}...") | |
| else: | |
| step_audio_paths.append(None) | |
| # Step 3: Generate Manim code | |
| progress(0.5, desc="π» Generating animation code...") | |
| code = await generate_manim_code(outline, step_audio_paths=step_audio_paths) | |
| # Step 4: Render video | |
| progress(0.7, desc="π¬ Rendering video (this takes 30-60s)...") | |
| video_path = await render_scene(code) | |
| # Step 5: Merge audio | |
| progress(0.9, desc="π Finalizing with audio...") | |
| if any(step_audio_paths): | |
| # For now, merge the first available audio | |
| first_audio = next((a for a in step_audio_paths if a), None) | |
| if first_audio and os.path.exists(first_audio): | |
| video_path = merge_audio_video(video_path, first_audio) | |
| progress(1.0, desc="β Complete!") | |
| # Return video and success message | |
| if os.path.exists(video_path): | |
| return video_path, f"β Animation generated successfully!\n\nπ Stats:\n- Steps: {len(steps)}\n- Topic: {outline.get('topic', 'N/A')}" | |
| else: | |
| return None, "β Video file not found after rendering" | |
| except Exception as e: | |
| error_msg = f"β Error: {str(e)}\n\nPlease try:\n1. A simpler prompt\n2. Check if GEMINI_API_KEY is set\n3. Report this issue on GitHub" | |
| print(f"Error in generate_animation: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| return None, error_msg | |
| def generate_sync(prompt): | |
| """Synchronous wrapper for Gradio""" | |
| return asyncio.run(generate_animation(prompt)) | |
| # Example prompts | |
| EXAMPLES = [ | |
| ["Explain the Pythagorean theorem with a right triangle and show a^2 + b^2 = c^2"], | |
| ["Show how binary search algorithm works with a sorted array"], | |
| ["Visualize the structure of an atom with nucleus and orbiting electrons"], | |
| ["Demonstrate how compound interest grows over time with a graph"], | |
| ["Explain Newton's first law of motion with a simple example"], | |
| ["Show bubble sort algorithm sorting an array step by step"], | |
| ] | |
| # Custom CSS | |
| custom_css = """ | |
| .gradio-container { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .contain { | |
| max-width: 1200px; | |
| margin: auto; | |
| } | |
| footer { | |
| display: none !important; | |
| } | |
| """ | |
| # Create Gradio interface | |
| with gr.Blocks( | |
| theme=gr.themes.Soft( | |
| primary_hue="orange", | |
| secondary_hue="gray", | |
| neutral_hue="slate", | |
| ), | |
| css=custom_css, | |
| title="Animetrix AI - Educational Animation Generator" | |
| ) as demo: | |
| gr.Markdown( | |
| """ | |
| # π¬ Animetrix AI | |
| ## AI-Powered Educational Animation Generator | |
| Transform your ideas into professional educational animations using AI and Manim. | |
| Powered by Google Gemini and Manim Community Edition. | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| prompt_input = gr.Textbox( | |
| label="π‘ Describe the concept you want to animate", | |
| placeholder="e.g., Explain how photosynthesis works in plants...", | |
| lines=4, | |
| max_lines=6 | |
| ) | |
| with gr.Row(): | |
| clear_btn = gr.ClearButton([prompt_input]) | |
| submit_btn = gr.Button("π¬ Generate Animation", variant="primary", size="lg") | |
| with gr.Column(scale=2): | |
| gr.Markdown( | |
| """ | |
| ### π‘ Tips for Best Results | |
| - **Be specific**: Include what you want to see | |
| - **Use simple language**: Avoid complex jargon | |
| - **Mention visuals**: Circles, arrows, graphs, etc. | |
| - **Keep it focused**: One concept per animation | |
| ### β±οΈ Processing Time | |
| - Planning: ~5 seconds | |
| - Narration: ~10 seconds | |
| - Rendering: ~30-60 seconds | |
| **Total: 1-2 minutes** | |
| """ | |
| ) | |
| video_output = gr.Video(label="πΉ Generated Animation", height=400) | |
| status_output = gr.Textbox(label="Status", lines=4, show_label=True) | |
| gr.Markdown("### π Example Prompts (Click to try)") | |
| gr.Examples( | |
| examples=EXAMPLES, | |
| inputs=[prompt_input], | |
| label="Try these examples:" | |
| ) | |
| gr.Markdown( | |
| """ | |
| --- | |
| ### π οΈ Tech Stack | |
| - **AI**: Google Gemini 2.0 Flash | |
| - **Animation**: Manim Community Edition | |
| - **Narration**: gTTS (Google Text-to-Speech) | |
| - **Video Processing**: MoviePy + FFmpeg | |
| ### π Links | |
| - [GitHub Repository](https://github.com/SayedZahur786/Animetrix_AI) | |
| - [Report Issues](https://github.com/SayedZahur786/Animetrix_AI/issues) | |
| - [Documentation](https://github.com/SayedZahur786/Animetrix_AI#readme) | |
| **Made with β€οΈ by Sayed Zahur** | |
| """ | |
| ) | |
| # Event handlers | |
| submit_btn.click( | |
| fn=generate_sync, | |
| inputs=[prompt_input], | |
| outputs=[video_output, status_output], | |
| api_name="generate" | |
| ) | |
| # Launch configuration | |
| if __name__ == "__main__": | |
| demo.queue(max_size=5).launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_error=True | |
| ) | |