Skip to content

Ishfaq24/Code2Concept

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

46 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Code2Concept

πŸ—οΈ Code2Concept β€” Architecture Document

Code2Concept is an AI-powered educational video generation platform that transforms any topic into an animated teaching video. It combines deterministic script generation with optional AI enhancement (Google Gemini) and Manim-based mathematical animation rendering β€” all served through a clean FastAPI backend.


Table of Contents


πŸ“– Project Overview

Code2Concept automates the creation of short educational animation videos. A user submits a topic (e.g., "Binary Search"), and the system:

  1. Generates a structured teaching script with a title and step-by-step explanations
  2. Optionally enriches the script with AI-powered research via Google Gemini
  3. Produces Manim animation code that visualizes the teaching content
  4. Optionally refines the generated code with AI to fix errors and improve quality
  5. Cleans, saves, and renders the code into an MP4 video using the Manim engine
  6. Serves the video to the user via a REST API endpoint

The architecture follows a resilient pipeline pattern β€” the core flow always succeeds using deterministic templates, while AI-powered stages enhance quality when available and fail gracefully when they don't.


βš™οΈ Tech Stack

Layer Technology Purpose
Web Framework FastAPI Async REST API with automatic OpenAPI docs
ASGI Server Uvicorn High-performance async server
Animation Manim (Community Edition) Programmatic math/educational animations
AI / LLM Google Gemini 1.5 Flash Topic research & code refinement
Validation Pydantic Request/response data validation
Configuration python-dotenv Environment variable management
Language Python 3.10+ Primary development language

πŸ“ Directory Structure

ARCHITECTURE.md                     # Detailed architecture document
architecture.tldr                   # Short architecture summary
README.md                           # Project overview and setup docs
backend/
β”œβ”€β”€ app/                            # FastAPI backend source code
β”‚   β”œβ”€β”€ main.py                     # App entrypoint and router registration
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   └── generate.py             # /generate and /video endpoints
β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   └── request.py              # Pydantic request schema
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ llm_service.py          # Deterministic script and Manim code generation
β”‚   β”‚   β”œβ”€β”€ research_service.py     # Gemini-based topic research
β”‚   β”‚   β”œβ”€β”€ refine_service.py       # Gemini-based code refinement
β”‚   β”‚   β”œβ”€β”€ animation_service.py    # Experimental animation generation path
β”‚   β”‚   └── manim_service.py        # Save scene code and render with Manim CLI
β”‚   └── utils/
β”‚       └── clean_code.py           # Removes markdown fences from generated code
β”œβ”€β”€ generated/
β”‚   β”œβ”€β”€ scene.py                    # Generated Manim scene (overwritten per request)
β”‚   └── media/                      # Intermediate render artifacts from Manim
β”œβ”€β”€ media/
β”‚   β”œβ”€β”€ images/scene/               # Frame/image artifacts
β”‚   β”œβ”€β”€ texts/                      # Manim text cache
β”‚   └── videos/scene/480p15/
β”‚       └── partial_movie_files/
β”‚           └── DemoScene/          # Partial clips and ffmpeg list files
β”œβ”€β”€ requirements.txt                # Python dependencies
└── .env                            # Backend environment variables
frontend/
β”œβ”€β”€ index.html                      # Vite HTML entrypoint
β”œβ”€β”€ package.json                    # Frontend scripts and dependencies
β”œβ”€β”€ package-lock.json               # Locked dependency graph
β”œβ”€β”€ vite.config.js                  # Vite configuration
β”œβ”€β”€ eslint.config.js                # ESLint configuration
β”œβ”€β”€ public/                         # Static assets served as-is
└── src/
    β”œβ”€β”€ main.jsx                    # React bootstrap
    β”œβ”€β”€ App.jsx                     # Root app component
    β”œβ”€β”€ api.js                      # API client helper
    β”œβ”€β”€ App.css                     # App-level styles
    β”œβ”€β”€ index.css                   # Global styles
    β”œβ”€β”€ assets/                     # Bundled assets
    └── components/
        β”œβ”€β”€ Loader.jsx              # Loading indicator component
        β”œβ”€β”€ VideoPlayer.jsx         # Video playback component
        └── VideoPlayer.css         # Styles for video player

Key Observations

Directory Role
backend/app/routes Thin controller layer that orchestrates the generation pipeline and delegates to services
backend/app/services Business logic layer for script generation, research, refinement, and rendering
backend/app/schemas API contracts and input validation via Pydantic
backend/generated Ephemeral generated code and intermediate artifacts
backend/media Render output and caches produced by Manim
frontend/src React UI source, API integration, and reusable components

🧩 System Architecture

The system follows a linear pipeline architecture where a user request flows through a series of processing stages. Each stage transforms or enriches the data before passing it to the next.

Request Lifecycle Flowchart

flowchart TD
    A["πŸ§‘β€πŸ’» Client\nPOST /generate {topic}"] --> B["πŸ›‘οΈ FastAPI Router\nValidate request via Pydantic"]
    B --> C["πŸ“ Script Generator\n(llm_service.py)"]
    C --> D{"πŸ”¬ Research\nEnhancement?"}
    D -- "βœ… Gemini Available" --> E["πŸ€– AI Research\n(research_service.py)\nGemini 1.5 Flash"]
    D -- "❌ Gemini Unavailable" --> F["⏭️ Skip Research\nContinue with base script"]
    E --> G["🎬 Manim Code Generator\n(llm_service.py)"]
    F --> G
    G --> H{"πŸ”§ Code\nRefinement?"}
    H -- "βœ… Gemini Available" --> I["πŸ€– AI Refinement\n(refine_service.py)\nGemini 1.5 Flash"]
    H -- "❌ Gemini Unavailable" --> J["⏭️ Skip Refinement\nUse raw generated code"]
    I --> K["🧹 Clean Code\n(clean_code.py)\nStrip markdown fences"]
    J --> K
    K --> L["πŸ’Ύ Save Code\n(manim_service.py)\nWrite to generated/scene.py"]
    L --> M["πŸŽ₯ Render Video\n(manim_service.py)\nmanim CLI subprocess"]
    M --> N{"πŸ“Ή Video\nExists?"}
    N -- "βœ… Yes" --> O["βœ… Return Success\n{message, topic}"]
    N -- "❌ No" --> P["❌ Return Error\n{error: 'Video not generated'}"]
    O --> Q["πŸ§‘β€πŸ’» Client\nGET /video"]
    Q --> R["πŸ“€ Serve MP4\nFileResponse"]

    style A fill:#4A90D9,stroke:#2C6BAE,color:#FFFFFF
    style B fill:#7B68EE,stroke:#5A4FCF,color:#FFFFFF
    style C fill:#2ECC71,stroke:#27AE60,color:#FFFFFF
    style E fill:#F39C12,stroke:#E67E22,color:#FFFFFF
    style G fill:#2ECC71,stroke:#27AE60,color:#FFFFFF
    style I fill:#F39C12,stroke:#E67E22,color:#FFFFFF
    style K fill:#1ABC9C,stroke:#16A085,color:#FFFFFF
    style L fill:#3498DB,stroke:#2980B9,color:#FFFFFF
    style M fill:#E74C3C,stroke:#C0392B,color:#FFFFFF
    style O fill:#2ECC71,stroke:#27AE60,color:#FFFFFF
    style P fill:#E74C3C,stroke:#C0392B,color:#FFFFFF
    style R fill:#9B59B6,stroke:#8E44AD,color:#FFFFFF
Loading

πŸ” Component Breakdown

1. main.py β€” Application Entry Point

app = FastAPI()
app.include_router(router)
  • Creates the FastAPI application instance
  • Registers the single router from routes/generate.py
  • Serves as the ASGI entry point for Uvicorn (uvicorn app.main:app)

2. routes/generate.py β€” Pipeline Orchestrator

The central nervous system of the application. This module defines two endpoints and orchestrates the entire video generation pipeline:

Endpoint Method Description
/generate POST Accepts a topic, runs the full pipeline
/video GET Serves the most recently rendered MP4 video

The /generate handler executes all pipeline stages sequentially, wrapping optional AI stages in try/except blocks for graceful degradation.

3. schemas/request.py β€” Request Validation

class Query(BaseModel):
    topic: str
  • Defines the data contract for the /generate endpoint
  • Leverages Pydantic for automatic validation, serialization, and OpenAPI schema generation
  • Rejects requests missing the topic field with a 422 Unprocessable Entity response

4. services/llm_service.py β€” Script & Code Generator (Core)

This is the deterministic backbone of the system. It contains two functions:

Function Input Output
generate_teaching_script(topic) Topic string Dict with title and steps list
generate_manim_from_script(script) Script dict Raw Manim Python code string

Script Generation Strategy:

  • Maintains a lookup of hardcoded, curated scripts for known topics (binary search, AI)
  • Falls back to a generic template for unknown topics
  • Zero external dependencies β€” this function never fails

Code Generation Strategy:

  • Builds a Manim DemoScene class programmatically
  • Iterates over script steps, creating Text objects with staggered vertical positioning
  • Produces syntactically valid Manim code that can render independently of AI services

5. services/research_service.py β€” AI Research (Optional Enhancement)

Function Input Output
generate_research(topic) Topic string Structured JSON string or None
  • Calls Google Gemini 1.5 Flash with a structured prompt requesting JSON output
  • Retrieves detailed concept explanations, steps, and examples
  • Loads API key from GEMINI_API_KEY environment variable via python-dotenv
  • Returns None on any failure β€” designed to be non-blocking
  • Currently, research output is retrieved but not yet merged into the script (future enhancement)

6. services/refine_service.py β€” AI Code Refinement (Optional Enhancement)

Function Input Output
refine_code(code) Raw Manim code Improved Manim code string
  • Sends the generated Manim code to Gemini 1.5 Flash for review and improvement
  • Prompt instructs the AI to fix syntax errors, improve animations, and ensure clean structure
  • On failure, the calling code falls back to the raw unrefined code
  • Creates a new genai.Client() instance per call (relies on default env-based auth)

7. services/animation_service.py β€” Alternative Animation Generator (Experimental)

Function Input Output
generate_animation_code(research) Research data Manim code string
  • Not currently used in the main pipeline
  • Provides an alternative approach: converts raw research data directly into Manim code via Gemini
  • Intended for future use when research data is integrated into the generation flow
  • Follows the same Gemini 1.5 Flash pattern as other AI services

8. services/manim_service.py β€” File I/O & Video Rendering

Function Input Output / Side Effect
save_code(code) Code string Writes to generated/scene.py
render_video() None Executes Manim CLI, produces MP4 in media/
  • save_code: Creates the generated/ directory if needed, overwrites scene.py every time
  • render_video: Spawns a subprocess running manim generated/scene.py DemoScene -pql
    • -p: Preview flag (opens video player β€” may need removal in production)
    • -ql: Quality low (480p at 15fps) for fast rendering
    • Output lands at media/videos/scene/480p15/DemoScene.mp4

9. utils/clean_code.py β€” Output Sanitization

Function Input Output
clean_code(code) Raw string Cleaned string
  • Strips markdown code fences (```python and ```) that LLMs commonly wrap around code output
  • Pure function with no side effects β€” essential when AI refinement is active
  • Ensures the saved .py file contains only valid Python

πŸ”€ Data Flow

Sequence Diagram β€” Full Request Lifecycle

sequenceDiagram
    actor User
    participant Router as πŸ›‘οΈ FastAPI Router<br/>(generate.py)
    participant LLM as πŸ“ LLM Service<br/>(llm_service.py)
    participant Research as πŸ”¬ Research Service<br/>(research_service.py)
    participant Gemini as πŸ€– Google Gemini<br/>1.5 Flash
    participant Refine as πŸ”§ Refine Service<br/>(refine_service.py)
    participant Clean as 🧹 Clean Code<br/>(clean_code.py)
    participant Manim as πŸŽ₯ Manim Service<br/>(manim_service.py)
    participant FS as πŸ’Ύ File System
    participant CLI as ⚑ Manim CLI<br/>(subprocess)

    User->>+Router: POST /generate {"topic": "Binary Search"}
    Note over Router: Pydantic validates Query model

    Router->>+LLM: generate_teaching_script("Binary Search")
    LLM-->>-Router: {title: "Binary Search", steps: [...]}

    Router->>+Research: generate_research("Binary Search")
    Research->>+Gemini: Prompt: Explain "Binary Search" as JSON
    alt Gemini Available
        Gemini-->>Research: Structured JSON explanation
        Research-->>Router: JSON research data
    else Gemini Unavailable
        Gemini-->>Research: Error / Timeout
        Research-->>-Router: None (graceful failure)
    end
    Note over Router: Research retrieved (future: merge into script)

    Router->>+LLM: generate_manim_from_script(script)
    LLM-->>-Router: Raw Manim Python code

    Router->>+Refine: refine_code(raw_code)
    Refine->>+Gemini: Prompt: Fix and improve this Manim code
    alt Gemini Available
        Gemini-->>Refine: Refined Manim code
        Refine-->>Router: Refined code
    else Gemini Unavailable
        Refine-->>-Router: Exception thrown
        Note over Router: Catch exception β†’ use raw_code
    end

    Router->>+Clean: clean_code(final_code)
    Clean-->>-Router: Sanitized Python code

    Router->>+Manim: save_code(code)
    Manim->>FS: Write β†’ generated/scene.py
    Manim-->>-Router: Done

    Router->>+Manim: render_video()
    Manim->>+CLI: manim generated/scene.py DemoScene -pql
    CLI->>FS: Write β†’ media/videos/scene/480p15/DemoScene.mp4
    CLI-->>-Manim: Process complete
    Manim-->>-Router: Done

    Router-->>-User: {"message": "Video generated successfully", "topic": "Binary Search"}

    Note over User, FS: Video retrieval (separate request)

    User->>+Router: GET /video
    Router->>FS: Check media/videos/scene/480p15/DemoScene.mp4
    FS-->>Router: File exists
    Router-->>-User: πŸ“Ή MP4 FileResponse (video/mp4)
Loading

Pipeline Data Transformations

"Binary Search"          β†’  Topic string
       β”‚
       β–Ό
{title, steps[]}         β†’  Structured script dictionary
       β”‚
       β–Ό
"from manim import *..." β†’  Raw Manim Python source code
       β”‚
       β–Ό
"from manim import *..." β†’  Refined code (AI-improved or unchanged)
       β”‚
       β–Ό
"from manim import *..." β†’  Cleaned code (markdown fences stripped)
       β”‚
       β–Ό
generated/scene.py       β†’  File on disk
       β”‚
       β–Ό
DemoScene.mp4            β†’  Rendered animation video

πŸ“‘ API Reference

POST /generate

Triggers the full video generation pipeline for a given topic.

Request Body:

{
  "topic": "Binary Search"
}
Field Type Required Description
topic string βœ… Yes The educational topic to animate

Success Response (200 OK):

{
  "message": "Video generated successfully",
  "topic": "Binary Search"
}

Error Responses:

Scenario Response
Video not generated {"error": "Video not generated"}
Pipeline exception {"error": "<exception message>"}
Missing/invalid topic 422 Unprocessable Entity (Pydantic)

GET /video

Serves the most recently rendered video file.

Response:

Scenario Response
Video exists 200 OK β€” MP4 binary stream (Content-Type: video/mp4)
Video not found {"error": "Video not found"}

⚠️ Note: This endpoint always serves the latest generated video. There is no per-request video isolation β€” concurrent requests will overwrite each other.


πŸ›οΈ Layered Architecture

block-beta
    columns 1

    block:CLIENT["🌐 CLIENT LAYER"]
        A["HTTP Client (Browser, curl, Frontend App)"]
    end

    space

    block:API["πŸ›‘οΈ API LAYER β€” FastAPI"]
        B["main.py β€” App Factory"]
        C["routes/generate.py β€” Endpoint Definitions"]
        D["schemas/request.py β€” Pydantic Validation"]
    end

    space

    block:CORE["πŸ“ CORE SERVICE LAYER β€” Deterministic (Always Works)"]
        E["llm_service.py β€” Script Generation"]
        F["llm_service.py β€” Manim Code Generation"]
    end

    space

    block:AI["πŸ€– AI ENHANCEMENT LAYER β€” Optional (Graceful Fallback)"]
        G["research_service.py β€” Topic Research"]
        H["refine_service.py β€” Code Refinement"]
        I["animation_service.py β€” Alt Generator (Experimental)"]
    end

    space

    block:INFRA["βš™οΈ INFRASTRUCTURE LAYER"]
        J["manim_service.py β€” File I/O & Rendering"]
        K["clean_code.py β€” Output Sanitization"]
        L["Manim CLI β€” Subprocess Execution"]
    end

    space

    block:STORAGE["πŸ’Ύ STORAGE LAYER"]
        M["generated/scene.py β€” Ephemeral Scene File"]
        N["media/ β€” Rendered Video Artifacts"]
    end

    CLIENT --> API
    API --> CORE
    API --> AI
    CORE --> INFRA
    AI --> INFRA
    INFRA --> STORAGE

    style CLIENT fill:#4A90D9,color:#FFFFFF
    style API fill:#7B68EE,color:#FFFFFF
    style CORE fill:#2ECC71,color:#FFFFFF
    style AI fill:#F39C12,color:#FFFFFF
    style INFRA fill:#3498DB,color:#FFFFFF
    style STORAGE fill:#95A5A6,color:#FFFFFF
Loading

Layer Responsibilities

Layer Responsibility Failure Impact
Client Layer Sends HTTP requests, receives responses and video files N/A
API Layer Request validation, pipeline orchestration, response formatting ❌ Full failure
Core Service Layer Deterministic script and code generation β€” no external dependencies ❌ Full failure (critical)
AI Enhancement Layer Optional AI-powered research and refinement β€” requires Gemini API βœ… Graceful degradation
Infrastructure Layer File I/O, code cleaning, subprocess management ❌ Full failure
Storage Layer Ephemeral file system for generated code and rendered video artifacts ❌ Full failure

πŸ›‘οΈ Error Handling & Graceful Fallbacks

Code2Concept employs a defense-in-depth error handling strategy that separates critical operations from optional enhancements.

Strategy Overview

flowchart LR
    subgraph CRITICAL["πŸ”΄ Critical Path β€” Must Succeed"]
        A["Script Generation"] --> B["Code Generation"]
        B --> C["Clean Code"]
        C --> D["Save to Disk"]
        D --> E["Render Video"]
    end

    subgraph OPTIONAL["🟑 Optional Enhancements β€” May Fail"]
        F["AI Research\n(research_service)"]
        G["AI Refinement\n(refine_service)"]
    end

    F -.->|"Enhances (future)"| A
    G -.->|"Improves"| B

    style CRITICAL fill:#FDECEA,stroke:#E74C3C,color:#333333
    style OPTIONAL fill:#FFF9E6,stroke:#F39C12,color:#333333
Loading

Failure Modes

Component Failure Cause Handling Strategy User Impact
Script Generation None (deterministic) Always succeeds β€” uses hardcoded templates None
AI Research API key missing, network error, quota try/except β†’ logs warning, continues pipeline Slightly less detail
Code Generation None (deterministic) Always succeeds β€” builds code from script dict None
AI Refinement API key missing, network error, quota try/except β†’ falls back to raw unrefined code May have rough edges
Code Cleaning None (string replacement) Always succeeds None
File Save Disk permissions, disk full Exception propagates β†’ top-level catch returns error Full failure
Video Rendering Manim not installed, syntax error Subprocess may fail β†’ video file missing β†’ error returned Full failure
Video Serving File not found Returns {"error": "Video not found"} No video available

Top-Level Safety Net

The entire /generate endpoint is wrapped in a master try/except:

@router.post("/generate")
async def generate(q: Query):
    try:
        # ... full pipeline ...
    except Exception as e:
        return {"error": str(e)}

This ensures the API never returns a 500 Internal Server Error β€” all exceptions are caught and returned as structured JSON error responses.


πŸš€ Future Improvements & Roadmap

Short-Term Enhancements

Improvement Description
Merge research into scripts Feed generate_research() output into script generation for richer, AI-informed content
Activate animation_service.py Integrate the experimental Gemini-based animation generator as an alternative pipeline path
Remove -p preview flag Strip the Manim preview flag for headless server deployment
Add request ID tracking Assign unique IDs to each generation request for logging and video isolation
Per-request video storage Store videos with unique filenames to prevent concurrent request conflicts

Medium-Term Architecture

Improvement Description
Async rendering pipeline Move video rendering to a background task (Celery/ARQ) with status polling
Video quality options Allow clients to specify resolution/quality (-ql, -qm, -qh, -qk)
Caching layer Cache generated videos by topic to avoid redundant rendering
Database integration Store generation history, scripts, and video metadata in PostgreSQL/SQLite
Streaming responses Return video generation progress via WebSocket or SSE
Proper HTTP status codes Use 404, 500, etc. instead of 200 with error JSON bodies

Long-Term Vision

Improvement Description
Multi-scene support Generate multi-scene videos with transitions for complex topics
Custom animation styles Let users choose visual themes (dark mode, colorful, minimalist)
Voice-over integration Generate narration audio (TTS) and sync it with the animation
Frontend application Build a React/Next.js UI for topic input, progress tracking, and video playback
Containerized deployment Dockerize the full stack (FastAPI + Manim + LaTeX dependencies) for one-command deployment
LLM provider abstraction Support multiple AI providers (OpenAI, Anthropic, local models) behind a unified interface

Code2Concept β€” Turning concepts into animations, one topic at a time.

Releases

Packages

Contributors

Languages