Spaces:
Runtime error
Runtime error
File size: 4,050 Bytes
4040be0 54ca85f 5657511 4040be0 e65b972 5657511 4040be0 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 54ca85f fa3da87 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | ---
title: PDF → Manim → LLM App
emoji: "🎬"
colorFrom: "red"
colorTo: "blue"
sdk: gradio
sdk_version: "6.8.0"
python_version: "3.11"
app_file: app.py
pinned: false
---
# 🎬 PDF → Manim Animation Pipeline
A Hugging Face Spaces Gradio app that converts any PDF into an animated Manim video and delivers it to your inbox.
---
## 🚀 Quick Start
### 1. Upload to Hugging Face Spaces
Create a new Space on [huggingface.co/spaces](https://huggingface.co/spaces) with:
- **SDK:** Gradio
- **Hardware:** CPU Basic (or better — more RAM = faster renders)
Upload all files in this folder.
---
### 2. Set Environment Secrets
In your Space settings → **Secrets**, add:
| Secret Name | Value |
|-----------------|--------------------------------------------|
| `SMTP_EMAIL` | Your Gmail address (e.g. `you@gmail.com`) |
| `SMTP_PASSWORD` | Gmail App Password (16-char, not login pw) |
**How to get a Gmail App Password:**
1. Enable 2-Step Verification on your Google account.
2. Go to [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords).
3. Create a new app password for "Mail".
> ⚠️ **Never commit secrets to your repo.** Only use the Spaces secret store.
---
### 3. Usage
1. Open your Space URL.
2. Upload a PDF file.
3. Enter your email address *(saved in browser — no need to re-enter)*.
4. Enter your **Gemini API key** *(saved in browser)* — get one free at [aistudio.google.com](https://aistudio.google.com).
5. Click **Generate Video**.
6. Watch live status updates — the generated Manim code appears in-app, and the video arrives in your inbox!
---
## 🏗️ Architecture
```
PDF Upload
│
▼
Extract Text (pypdf)
│
▼
Gemini 2.5 Flash (google-genai)
│ → generated code shown live in UI
▼
Manim Render (-qm, 1280×720, 30fps)
│
▼
Video < 24MB? ──YES──▶ Email Attachment
│ │
NO │
▼ │
Catbox.moe Upload │
│ │
▼ │
Email Link ◀─────────────────┘
│
▼
Cleanup temp files
```
---
## ⚙️ Configuration
| Setting | Default | Location |
|--------------------|--------------|---------------------------------|
| Max concurrent jobs| 100 | `app.py` → `JobQueue(max_jobs=)`|
| Thread workers | 8 | `app.py` → `JobQueue(max_workers=)`|
| Manim quality | `-qm` 720p30 | `pipeline.py` → `_render_manim` |
| Render timeout | 600s | `pipeline.py` → `_render_manim` |
| Catbox retries | 5 | `utils.py` |
---
## 📁 File Structure
```
.
├── app.py # Gradio UI + streaming status + BrowserState persistence
├── pipeline.py # Job pipeline orchestrator
├── queue_manager.py # Thread-pool queue with state tracking
├── utils.py # PDF, Gemini, email, Catbox helpers
├── requirements.txt # Python dependencies
├── packages.txt # System packages (LaTeX, ffmpeg, cairo…)
└── README.md # This file
```
---
## 🔒 Security Notes
- Gemini API keys are passed per-request and **never stored server-side**.
- Email/API key persisted in **browser localStorage** (client only).
- SMTP credentials live only in HF Secrets (env vars).
- All temporary files deleted after pipeline completion.
- Each job uses a UUID to prevent path collisions.
---
## 🐛 Troubleshooting
| Issue | Fix |
|-------|-----|
| `SMTP_EMAIL not set` | Add the secret in HF Space settings |
| `latex not found` | Ensure `packages.txt` is in your Space root |
| Render timeout | Use a higher-tier Space hardware |
| Gemini API error | Check your API key and quota |
| Empty PDF | PDF must have selectable text (not scanned image) |
| Large video | Catbox fallback used automatically |
|