AudioPrep AI is an enterprise-grade, RAG-grounded system that transforms complex technical PDF documentation into engaging, natural conversational podcasts featuring two AI co-hosts. Built from document ingestion to automated cloud deployment.
Explore Features β’ System Architecture β’ AWS & DuckDNS Deployment β’ Quickstart β’ CI/CD Workflow
- Overview & Philosophy
- End-to-End Architecture
- Key Features
- Deep-Dive Component Workflows
- Cloud Deployment & Networking (AWS + DuckDNS + SSL)
- CI/CD Pipeline (GitHub Actions)
- Repository Structure
- Local Development Setup
- API Documentation
- Evaluation Framework (RAGAS)
- License & Acknowledgements
Engineers and students spend hours reading technical papers, release notes, and documentation during busy schedules. AudioPrep AI bridges this gap by enabling auditory learning with natural, dialogue-driven discussions between an inquisitive Host and an authoritative Expert.
Unlike simple "prompt-and-read" wrappers:
- No Hallucination: RAG-grounded dialogue generation backed by hybrid dense/sparse search and cross-encoder reranking.
- Closed-Loop Verification: A Critic Node validates groundedness, coverage, and conversational pacing before audio synthesis.
- Production Resilience: Multi-tier LLM and TTS fallback chains (NVIDIA/DeepSeek β Gemini β Groq; Gemini TTS β Kokoro TTS).
- Enterprise Storage & Deployment: Scalable AWS S3 media management, PostgreSQL persistent state, and zero-downtime GitHub Actions CI/CD to AWS EC2 with full HTTPS.
flowchart TD
subgraph Client ["Client Layer"]
User["User Browser"] -->|HTTPS / Port 443| Domain["audioprep-ai.duckdns.org"]
Domain -->|Nginx Ingress| Frontend["React 18 SPA (Vite)"]
end
subgraph AWS_EC2 ["AWS EC2 Host (c7i-flex.large / Sydney)"]
Frontend -->|Reverse Proxy /api| Backend["FastAPI REST Server"]
subgraph Pipeline ["Podcast Generation Pipeline"]
direction TB
Ingest["1. Ingestion: PyMuPDF + pymupdf4llm"]
Chunk["2. Chunking: Structure-Aware / Semantic / Contextual / Recursive"]
Index["3. Hybrid Indexing: Qdrant Dense + BM25 Sparse"]
Planner["4. LangGraph Topic Planner (Concept Dependency)"]
Dialogue["5. Dialogue Generation (Host <-> Expert)"]
Critic{"6. Quality Critic: Groundedness & Relevance"}
TTS["7. Audio Synthesis: Gemini TTS (Fallback: Kokoro)"]
FFmpeg["8. Audio Polish: FFmpeg -16 LUFS Normalization"]
Ingest --> Chunk --> Index --> Planner --> Dialogue --> Critic
Critic --"Score < Threshold (Max 1 loop)"--> Dialogue
Critic --"Score Approved"--> TTS --> FFmpeg
end
Backend --> Pipeline
Backend <-->|SQLAlchemy 2.0 Async| Postgres[("PostgreSQL 16 DB\n(Docker Volume: postgres_data)")]
end
subgraph AWS_Cloud ["AWS Cloud Services"]
Backend -->|boto3 API| S3_Bucket[("AWS S3 Bucket\naudioprep-storage-263824")]
S3_Bucket -.->|Presigned Audio/PDF URL| User
end
classDef aws fill:#FF9900,stroke:#232F3E,stroke-width:2px,color:white;
classDef comp fill:#2496ED,stroke:#1D63ED,stroke-width:2px,color:white;
classDef model fill:#00C7B7,stroke:#008080,stroke-width:2px,color:white;
class S3_Bucket,AWS_EC2 aws;
class Backend,Frontend,Postgres comp;
class Pipeline,TTS,Critic model;
- Multi-Speaker Conversational Synthesis: Generates realistic banter, interruptions, and natural questions between two distinct voices (Male host "Puck" & Female expert "Kore").
- 4 Selectable Chunking Strategies: Empirically evaluate and pick between Recursive, Semantic, Contextual, or Structure-Aware document segmentations.
- RRF Hybrid Retrieval: Combines sentence-transformer vector search (
all-MiniLM-L6-v2) with lexical BM25 using server-side Reciprocal Rank Fusion. - Stateful Agentic LangGraph Pipeline: Graph execution with conditional branching, cycle boundaries, and automated quality remediation.
- Dual-Engine Audio Generation: Primary conversational synthesis via Google Gemini Multi-Speaker API with automatic local fallback to Kokoro-82M TTS.
- Podcast Studio Audio Mastering: Post-processes output with FFmpeg to reach EBU R128 / -16 LUFS broadcast volume with smooth intro/outro pauses.
- AWS S3 + PostgreSQL Architecture: Source documents and finished media are streamed through presigned URLs, keeping the EC2 server stateless and lightweight.
- Automated CI/CD: Pushing to
mainbuilds multi-stage Docker images to GitHub Container Registry (GHCR) and performs rolling updates on AWS EC2. - Free Custom Domain with SSL: Bound to
audioprep-ai.duckdns.orgwith Let's Encrypt automated TLS certificate renewal.
- Module:
backend/app/services/ingestion/pdf_parser.py - Memory Footprint: Uses only ~100MB RAM (unlike heavy alternatives such as Docling which require 2-4GB).
- Processing: Extracts Markdown representation preserving
# H1,## H2, bullet points, and code blocks viapymupdf4llm. Scanned image pages automatically fallback to PyMuPDF's Tesseract-compatible textpage OCR pipeline.
- Module:
backend/app/services/chunking/ - Users can tailor chunking to document structure:
| Strategy | Mechanism | Best Suited For |
|---|---|---|
| Structure-Aware (Default) | Splits on markdown header hierarchies (H1 β H2 β H3), preserving logical sections. |
Architecture docs, RFCs, technical guides |
| Semantic | Calculates cosine distance between consecutive sentences; splits when semantic variance spikes. | Dense academic papers, prose |
| Contextual | LLM prepends a 2-sentence document summary to each chunk to prevent orphaned context. | Fragmented FAQs, technical reference tables |
| Recursive Character | Hierarchical token split on \n\n, \n, . , and spaces. |
General notes, unstructured dumps |
-
Module:
backend/app/services/retrieval/ -
Dense Vectors: Encoded using
sentence-transformers/all-MiniLM-L6-v2(384 dimensions) into an in-memory/embedded Qdrant index. Captures conceptual semantics. -
Sparse BM25: Indexed via
rank-bm25over tokenized words. Captures precise acronyms, function names, and technical terminology. -
Reciprocal Rank Fusion (RRF): Merges candidate rankings using standard score formula:
$$\text{Score}(d) = \sum_{m \in {\text{dense}, \text{sparse}}} \frac{1}{60 + \text{rank}_m(d)}$$ -
Reranker: Top candidates pass through a Cross-Encoder (
ms-marco-MiniLM-L-6-v2) scoring query-document pairs jointly to filter out noise.
- Module:
backend/app/agents/podcast_graph.py - Orchestrated through LangGraph's cyclic
StateGraph:- Topic Planner Node: Breaks extracted document into a logical progression of concepts and interview question sequences.
- Retrieval Node: Gathers cross-referenced evidence chunks for each planned topic.
- Dialogue Generation Node: LLM crafts turns using strict speaker rules:
- HOST: Asks clarifying questions, uses analogies, steers pacing.
- EXPERT: Explains mechanisms, references citations, clarifies subtleties.
- Quality Critic Node: Inspects dialogue for hallucinations, coverage of key concepts, and natural flow. If score < 7.0, routes back to dialogue generation with targeted critique notes (bounded to 1 revision loop).
- Module:
backend/app/services/tts/&backend/app/services/audio/processor.py - Primary Engine: Google Gemini Multi-Speaker API synthesizes natural two-person speech with emotional cues in a single multi-turn request.
- Local Fallback: If API limits or connectivity fails, routes gracefully to local Kokoro-82M TTS on CPU without failing the job.
- Audio Post-Processing (FFmpeg):
- Loudness normalization to -16 LUFS (podcast international broadcast standard).
- Silence trimming & intelligent conversational gap insertion (0.4s natural speaker transition).
- Encoded to 192kbps stereo MP3.
- Modules:
backend/app/core/database.py&backend/app/services/storage/s3_service.py - Database (
jobstable):- Tracks UUID
job_id, real-time stage progress (0β100%), error diagnostics, and timestamps. - Retains S3 object keys and generated presigned streaming URLs.
- Tracks UUID
- AWS S3 (
audioprep-storage-263824):- Source documents:
pdfs/{job_id}/{filename} - Output podcasts:
media/{job_id}/podcast_output.mp3 - High durability; ensures the host server's local disk remains unburdened.
- Source documents:
In enterprise cloud setups, binding a bare AWS Public IP address (http://13.236.98.48) directly to end users creates critical issues:
- No Free SSL on Raw IPs: Public Certificate Authorities (like Let's Encrypt) do not issue free SSL/TLS certificates for bare IP addresses; they require a fully qualified domain name (FQDN).
- Browser Blocking: Modern desktop and mobile browsers (Chrome 117+, Safari, Edge) automatically force
https://on URL entries or display severeERR_CONNECTION_REFUSED/ "Dangerous Site" warnings when accessing HTTP over raw IPs. - Dynamic IP Changes: If an AWS EC2 instance is stopped and restarted without an Elastic IP, its public IP changes, breaking all bookmarks.
The DuckDNS Solution:
- DuckDNS provides a free, lightweight Dynamic Domain Name Service (DDNS).
- By registering
audioprep-ai.duckdns.organd mapping it to the EC2 Public IPv4 (13.236.98.48), the server gains an authoritative FQDN at $0.00 cost. - Allows automated DNS resolution so any user or recruiter clicking the link is routed directly to the AWS EC2 instance.
With audioprep-ai.duckdns.org pointed at the server, Certbot was executed via standalone ACME challenge:
sudo certbot certonly --standalone -d audioprep-ai.duckdns.org --agree-tos --register-unsafely-without-email- Certbot validates domain ownership against DuckDNS.
- It generates trusted cryptographic certificates stored at
/etc/letsencrypt/live/audioprep-ai.duckdns.org/. - The Docker container mounts
/etc/letsencryptas a read-only volume. - Nginx handles TLS termination:
- Port 80 requests receive an instant
301 Moved Permanentlyredirect tohttps://. - Port 443 serves TLS 1.2/1.3 with modern cipher suites and terminates the secure connection before proxying to FastAPI.
- Port 80 requests receive an instant
- Region:
ap-southeast-2(Asia Pacific - Sydney) - Compute: EC2
c7i-flex.large(4th Gen Intel Xeon Scalable, 2 vCPUs, 4 GiB RAM)- Selected for dedicated compute performance over burstable
t3instances, providing fast vector embeddings and FFmpeg audio mastering.
- Selected for dedicated compute performance over burstable
- Storage: 30 GB gp3 SSD (EC2 root) + AWS S3 Standard (Object storage).
- Security Groups:
Port 22(SSH Management)Port 80(HTTP Ingress β Redirects to HTTPS)Port 443(HTTPS Ingress β Nginx TLS Termination)
Every push to the main branch triggers an automated build, test, package, and deploy cycle defined in .github/workflows/deploy.yml:
git push origin main
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββ
β GitHub Actions Runner (Ubuntu) β
β βββ Checkout Repository β
β βββ Docker Buildx Setup β
β βββ Build Backend Docker Image β
β βββ Build Frontend React Docker Image β
β βββ Push to GHCR (ghcr.io) β
ββββββββββββββββββββ¬ββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββ
β Continuous Deployment (SSH to EC2) β
β βββ Pre-pull cleanup: docker prune β
β βββ Pull latest images from GHCR β
β βββ Recreate containers via Compose β
β βββ Post-cleanup: prune stale layers β
ββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
Live at audioprep-ai.duckdns.org
Because machine learning containers containing PyTorch and audio binaries are ~3.5 GB, deploying multiple revisions can fill server storage. The deployment script runs automated image pruning:
docker image prune -af || true
docker compose pull backend frontend
docker compose up -d --remove-orphans
docker image prune -af || trueThis guarantees that stale images are scrubbed on every release while keeping the PostgreSQL database volume (postgres_data) and S3 objects completely untouched.
the-podcaster/
βββ .github/
β βββ workflows/
β βββ deploy.yml # GitHub Actions CI/CD deployment pipeline
βββ backend/
β βββ app/
β β βββ agents/ # LangGraph state machine & agent nodes
β β β βββ podcast_graph.py # StateGraph definition & execution logic
β β β βββ topic_planner.py # Concept dependency curriculum planner
β β β βββ quality_critic.py # Factuality & dialogue critic
β β β βββ state.py # Pydantic agent state definitions
β β βββ core/ # Core configurations and infrastructure
β β β βββ config.py # Pydantic Settings (Environment variables)
β β β βββ database.py # SQLAlchemy 2.0 Async PostgreSQL engine
β β β βββ job_store.py # Hybrid memory + PostgreSQL persistent store
β β β βββ llm_provider.py # Fallback provider: NVIDIA -> Gemini -> Groq
β β βββ models/ # Schemas & ORM database models
β β β βββ db_models.py # SQLAlchemy JobEntity table definition
β β β βββ job.py # Pydantic REST schemas for API requests
β β βββ services/ # Domain processing services
β β β βββ audio/processor.py # FFmpeg normalization & mixing
β β β βββ chunking/ # 4 chunking strategy implementations
β β β βββ dialogue/ # Prompt templates & dialogue generation
β β β βββ ingestion/ # PyMuPDF document extraction & OCR
β β β βββ retrieval/ # Qdrant Dense + BM25 Sparse hybrid search
β β β βββ storage/s3_service # AWS S3 client & presigned URL generator
β β β βββ tts/ # Gemini Multi-Speaker & Kokoro fallback
β β βββ main.py # FastAPI HTTP routing & background tasks
β βββ Dockerfile # Multi-stage Python 3.11 + FFmpeg container
β βββ requirements.txt # Python dependencies
βββ frontend/
β βββ src/
β β βββ components/ # React UI components
β β β βββ AudioPlayer.jsx # Custom audio playback & seeking player
β β β βββ FileUpload.jsx # Drag-and-drop PDF upload component
β β β βββ PodcastConfig.jsx # Duration, difficulty & strategy config
β β β βββ StatusTracker.jsx # Real-time pipeline stage progress bar
β β βββ App.jsx # Main application orchestrator
β β βββ index.css # Custom styling
β βββ Dockerfile # Multi-stage Node builder + Nginx image
β βββ nginx.conf # Production Nginx reverse proxy + SSL config
β βββ package.json # Node.js dependencies
βββ docker-compose.yml # Orchestration for Postgres, Backend & Frontend
βββ .gitignore # Git exclusion rules for API keys & binaries
βββ README.md # Comprehensive project documentation
- Python 3.11+
- Node.js 20+ & npm
- FFmpeg installed locally (for audio mastering)
- Docker & Docker Compose (optional, for containerized run)
git clone https://github.com/12ATHARAV/AudioPrep-AI.git
cd AudioPrep-AICreate backend/.env based on the template:
# LLM Providers (At least one required)
GEMINI_API_KEY=your_gemini_api_key
NVIDIA_API_KEY=your_nvidia_api_key
GROQ_API_KEY=your_groq_api_key
LLM_PRIMARY=nvidia
# AWS S3 Configuration
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=ap-southeast-2
AWS_S3_BUCKET=your_s3_bucket_name
# Database Configuration (Defaults to local PostgreSQL or SQLite fallback)
DATABASE_URL=postgresql+asyncpg://audioprep:audioprep_secure_pass@localhost:5432/audioprep_dbLaunch the entire system (PostgreSQL + FastAPI + React + Nginx) with a single command:
docker compose up --build- Open
http://localhost:80for the Web App. - Open
http://localhost:8000/docsfor the interactive API Swagger Documentation.
Start Backend:
cd backend
python -m venv venv
# Windows:
.\venv\Scripts\Activate.ps1
# Linux/macOS:
source venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000Start Frontend:
cd frontend
npm install
npm run devAccess the development UI at http://localhost:5173.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/podcasts |
Uploads PDF, pushes to S3, creates DB record, and triggers async generation. |
GET |
/api/podcasts/{job_id} |
Polls job progress, pipeline stages, and receives S3 streaming audio URLs. |
GET |
/api/podcasts/{job_id}/audio |
Direct audio download endpoint (fallback if direct S3 stream is bypass-requested). |
GET |
/api/health |
Healthcheck endpoint reporting active LLM and TTS status. |
GET |
/docs |
OpenAPI / Swagger interactive documentation UI. |
To ensure audio transcripts remain faithful to source materials, AudioPrep AI implements automated RAG evaluation using RAGAS (backend/evals/):
- Context Precision: Evaluates whether retrieved PDF chunks strictly correspond to topic concepts.
- Context Recall: Verifies all critical technical dependencies were identified by the Topic Planner.
- Faithfulness: Measures whether claims made by the Host and Expert are factually grounded in the source text.
- Answer Relevancy: Assesses whether dialogue explanations address technical concepts clearly and concisely.
Benchmark script:
python backend/evals/run_eval.pyDistributed under the MIT License. See LICENSE for more information.
Built with β€οΈ by 12ATHARAV