A small, resumable pipeline for turning a large podcast (or any large audio) archive into something you can actually search and ask questions of — transcription, structured summaries, semantic search, and grounded Q&A, all scripted around the OpenAI API.
Built to process 230 episodes (~145 hours of audio) for about $33 total.
Full write-up of how it works and what broke along the way: see
technical-blog.html (open it directly in a
browser, or publish it wherever you like).
Feeding a large transcript archive into an LLM's context window doesn't scale, and reading it yourself doesn't either. This pipeline gives you three ways to actually use a large audio archive:
- Structured summaries — a fast, cheap overview per episode (topics, quotes, takeaways, tone)
- Semantic search — embed everything once, then find the exact passage relevant to any question in milliseconds
- RAG-based Q&A — ask a natural-language question and get an answer grounded in, and cited to, the actual source material — no hallucinated advice
transcribe.py mp3s → transcripts/*.txt
build_index.py transcripts → index/ (embeddings + metadata)
summarize.py transcripts → summaries/*.json
ask.py question → cited answer (stdout)
analyze_themes.py summaries → themes.json (cross-corpus synthesis)
Every script only reads from the previous stage's output directory and only writes to its own — nothing is ever mutated in place, and every script skips work that's already done. That means you can kill any stage mid-run, add more source files later, or swap models between batches, and just rerun.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
brew install ffmpeg # or your platform's equivalentCreate a .env file in the project root:
OPENAI_API_KEY=sk-...
# 1. Drop your audio files into audio-files/, then:
python transcribe.py
# 2. Generate per-episode structured summaries:
python summarize.py
# 3. Build the semantic search index:
python build_index.py
# 4. Ask questions grounded in the transcripts:
python ask.py "what did they say about X?"
# 5. (Optional) synthesize themes across the whole corpus:
python analyze_themes.pysummarize.py and analyze_themes.py both have a short constant near the
top (SHOW_DESCRIPTION, FOCUS_THEMES) you should edit to match your own
show and what you actually want extracted — they ship with generic
placeholders, not any specific podcast's content.
- Transcription defaults to gpt-4o-mini-transcribe;whisper-1also works and may transcribe slightly better for noisy audio, at roughly double the per-minute cost.
- Source files get chunked to ~15-minute, 64kbps mono segments before upload — this keeps you well under API file-size limits and works for any audio length.
- Concurrency is capped at two levels (files × chunks-per-file) to stay
under provider rate limits without going fully sequential. Tune
FILE_WORKERS/CHUNK_WORKERS_PER_FILEintranscribe.pyfor your own rate limit tier.
- The search index is a single numpyarray + JSON metadata file — no vector database needed until you're well past tens of thousands of chunks.
The actual transcripts, summaries, and embeddings produced by running this against a real show aren't included — that's someone else's copyrighted audio content, even in text form. This repo is the workflow, not any particular show's content. Point it at your own audio.
MIT — see LICENSE.