| name | podcast-from-research |
| version | 1.0.0 |
| description | Research-to-podcast pipeline for learning new topics: 20-angle full-coverage research (with blind-spot discovery) → steered NotebookLM audio overview → MP3 delivered to you, with everything ingested into a local GBrain knowledge base for permanent recall. When the user says "create a podcast on X", this handles it end-to-end. Installs its own dependencies (notebooklm-py, GBrain) if missing. |
| platforms | ["linux"] |
| metadata | {"hermes":{"tags":["research","notebooklm","podcast","audio","learning","gbrain"],"category":"media"}} |
Podcast From Research
Mission
This pipeline exists to learn new topics. That drives three hard requirements:
- Research must cover the whole territory: including sub-areas the user didn't know to ask about. Blind-spot discovery is a mandatory step, not an option.
- The podcast must teach, not summarize. NotebookLM is always steered with an explicit production brief and generation instruction. Never accept its default output style.
- Everything lands in the knowledge base. The episode is the learning session; GBrain is the reference library you query weeks later.
Prerequisites: Check, Then Auto-Install
Before the first run, verify each dependency. If missing, install it; don't just report it's missing.
1. notebooklm-py (required)
export PATH="$HOME/.local/bin:$PATH" && which notebooklm && notebooklm --version
pip install "notebooklm-py[browser]"
playwright install chromium
notebooklm login
notebooklm auth check
⚠️ PATH pitfall: which notebooklm in a bare shell returns empty even when installed, because ~/.local/bin isn't in the default PATH. Every NotebookLM command in this skill must be prefixed with export PATH="$HOME/.local/bin:$PATH".
NotebookLM itself requires a Google account. Audio generation quality/limits follow the user's NotebookLM plan.
2. GBrain (required: the knowledge base)
export PATH="$HOME/.bun/bin:$PATH" && which gbrain && gbrain doctor
bun install -g github:garrytan/gbrain
gbrain init --pglite
For a guided agent install, follow: https://raw.githubusercontent.com/garrytan/gbrain/master/INSTALL_FOR_AGENTS.md
⚠️ GBrain needs $HOME/.bun/bin in PATH; source ~/.bashrc typically does NOT set it, so export it explicitly. Command verbs can differ slightly between versions (search/think vs query); run gbrain --help once and use what your version exposes.
3. ffmpeg (required)
Used to verify audio duration and re-encode NotebookLM downloads into genuine MP3s. ffmpeg -version; install via your package manager if missing.
4. Web search + extraction (required)
The research phase uses your agent's configured search stack (e.g. web_search / web_extract from hermes_tools, whatever backend your agent is set up with). Any search backend works; a full-page extraction step is strongly recommended over snippets. Optional: if you have an Exa API key, its structured deep search is useful for 3–5 framework-heavy angles.
Language Policy
- Research is ALWAYS in English (sources, angle docs, synthesis) regardless of the podcast language.
- Podcast audio language is configurable: "create a podcast on X in Spanish" → English research, Spanish audio. Default: English.
When This Skill Activates
- "create a podcast on [topic]" (with optional language)
- "generate an audio deep-dive on [topic]"
- "I want to listen to research on [topic]"
- User has existing research docs and wants a podcast from them
Overview
Research (20 angles) → NotebookLM notebook (21 sources) → steered audio overview → quality gate → MP3 delivered → everything into GBrain.
The user gets:
- 20 research documents + topic map + episode production brief (text)
- NotebookLM cross-source synthesis (post-listen study notes)
- The audio episode (genuine MP3, delivered directly; see
docs/optional-rss-feed.md to serve it to a podcast app)
- All content in GBrain for permanent retrieval
Working directory: /opt/data/deep-research/<topic-slug>/ (adjust to your agent's data directory; keep one directory per topic, slug = lowercased-hyphenated topic).
Step-by-Step
Phase 1: Full-Coverage Research (20 Angles)
Never invent 20 angles ad hoc. An ad-hoc list clusters around the obvious center of the topic and misses exactly the areas the user doesn't know exist. Three steps:
Step 1A: Discovery pre-pass (map the territory, ~2 min)
Run 2–4 cheap searches to find how experts already divide the field:
"<topic> syllabus" / "<topic> curriculum" / "<topic> course outline"
"<topic> body of knowledge" / "awesome <topic>" (GitHub curated lists)
"<topic> common mistakes" / "<topic> misconceptions"
"subfields of <topic>" / "<topic> taxonomy"
Mine the results for subtopic names, standard curricula, and named debates. Experts have usually already mapped the territory; steal their map instead of inventing one.
Step 1B: Fill the coverage matrix
Distribute exactly 20 angles across seven mandatory categories. Counts are flexible but every category must be non-empty:
| Category | Angles | What it covers |
|---|
| Foundations | 3–4 | core concepts & mental models; history/evolution; canonical frameworks; terminology & taxonomy |
| State of practice | 3–4 | how top practitioners do it today; tools/standards/ecosystem; data, benchmarks & economics; success case studies |
| Failure & controversy | 3 | misconceptions & beginner mistakes; documented failures & post-mortems; live debates & competing schools |
| Hidden angles | 3 | adjacent disciplines that intersect the topic; second-order & non-obvious consequences; tacit practitioner knowledge (forums, AMAs, conference talks) |
| Depth spikes | 2–3 | the 2–3 most technical subtopics, one level deeper than a survey |
| Frontier | 2 | current research & what's changing now; open problems & future scenarios |
| Learning accelerators | 1–2 | expert learning paths, seminal books/papers/people; heuristics & checklists experts actually use |
Hidden angles and Failure & controversy surface what the user would have missed. Never trim them to make room for more foundations.
Step 1C: Adversarial gap check
Before delegating research, critique the list: "An expert in reviews these 20 angles, which 5 important subtopics are missing?" Answer using the Step 1A findings plus your own knowledge, then swap the weakest angles for the genuine gaps. Verify no two angles overlap more than ~30%.
If the gap check surfaces more than ~25 strong angles, the topic is series-sized; see Series Mode below.
Search execution
For each angle: search (5–8 relevant URLs), extract full page content, synthesize. Batch 3 angles in parallel via delegate_task (7 batches for 20 angles). Each subagent gets the angle, the search approach, the document template below, and synthesis instructions. Write results to 01-*.md through 20-*.md.
Research document template (NotebookLM-optimized)
NotebookLM's hosts latch onto named frameworks, hard numbers, and concrete stories: write every doc to feed them exactly that:
# <Topic>: <Specific angle title, not the generic topic name>
## Why this matters
## Key findings <- dense factual prose, no filler
## Named frameworks & models <- name + description + steps; hosts cite these by name
## Data, numbers & cases <- concrete stats, named companies/people/events, dates
## Misconceptions & pitfalls
## Expert takeaways <- 5-10 sharp bullets
## Sources <- URLs
Each doc: 800–2,000 words of substance. Tell subagents explicitly: one concrete named case with numbers beats three generic paragraphs. A vague source doc yields a vague podcast segment. This is the single biggest quality lever in the pipeline.
Two retrieval rules (the same docs feed GBrain): every section must make sense standalone (retrieval returns chunks out of context, no "as mentioned above"), and the topic + angle must be repeated in headings so chunks stay anchored.
Phase 1.5: Verify Research Completeness
ls /opt/data/deep-research/<topic-slug>/[0-9][0-9]-*.md | wc -l
Missing angles → re-delegate only those. Then spot-check 2–3 docs for real specifics (named frameworks, numbers, cases); re-delegate generic filler with a sharper query.
Phase 1.6: Write the Topic Map (Knowledge-Base Index)
Write 00-topic-map.md, the entry point future queries land on:
# <Topic>: Research Map (<YYYY-MM-DD>)
Full-coverage deep research on <topic>. 20 angles across foundations, state
of practice, failure & controversy, hidden angles, depth spikes, frontier,
and learning accelerators.
## Angle index
- 01 <angle title>: <one-line summary of the doc's key insight>
- ...
- 20 <angle title>: <one-line summary>
## Top 10 insights across all angles
- <the most surprising/valuable findings, one line each, with angle number>
Write it AFTER the research so summaries reflect actual content. Do NOT add the topic map to NotebookLM: it's a knowledge-base index, not episode source material.
Phase 1.7: Write the Episode Production Brief (21st Source)
NotebookLM's audio customization prompt is short (~500 characters, longer gets truncated). The workaround: put detailed steering into a dedicated source document the short prompt points at.
Write 00-episode-brief.md:
# EPISODE PRODUCTION BRIEF: instructions for the podcast hosts, not source content
Audience: one intelligent generalist learning <topic> from scratch toward
practitioner level. Teach, do not merely summarize the sources.
Episode arc:
1. Hook: why <topic> matters right now, with concrete stakes
2. Foundations: core concepts and mental models; explain jargon on first use
3. Frameworks in action: named frameworks applied to real cases with numbers
4. What people get wrong: misconceptions and failure post-mortems
5. Where experts disagree & the frontier: live debates, what's changing now
6. Takeaways: heuristics, checklists, and a learning path for going deeper
Must-cover insights:
- <8-12 bullets: the single most surprising or valuable insight from each
research theme; pull these from the actual research docs>
Style: concrete over abstract; numbers and named cases over generalities;
no filler recaps; spend real time on nuance and disagreement between sources.
The must-cover bullets are the compression of your 20 docs: this is what forces NotebookLM to hit the good material instead of grazing evenly.
Phase 2: NotebookLM Setup
export PATH="$HOME/.local/bin:$PATH"
NOTEBOOK_ID=$(notebooklm create "<Topic> Deep-Dive Podcast" 2>&1 | grep -oP '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
NOTEBOOK_DIR=/opt/data/deep-research/<topic-slug>
notebooklm use "$NOTEBOOK_ID" && notebooklm source add "$NOTEBOOK_DIR/00-episode-brief.md"
for i in $(seq -w 1 20); do
f=$(ls "$NOTEBOOK_DIR"/$i-*.md 2>/dev/null | head -1)
[ -n "$f" ] && { notebooklm use "$NOTEBOOK_ID" && notebooklm source add "$f" || echo "FAILED: $f"; }
done
notebooklm use "$NOTEBOOK_ID" && notebooklm metadata
Tips:
- NotebookLM context is per-call, not sticky: always chain
notebooklm use "$ID" && …, including inside loops.
- If a source add fails or times out, retry that file individually with its full absolute path.
- Never pass a quoted glob to
source add: it ingests the literal string as pasted text with a useless title.
Phase 3: Generate Audio and Steer NotebookLM Hard
Never call bare notebooklm generate audio: the unsteered default is a pleasant, shallow 10–15 minute summary that doesn't teach.
Use the real flags first, then the prompt. Recent notebooklm-py versions expose --format (deep-dive, brief, critique, debate) and --length (short, default, long); always pass --format deep-dive --length long. If your version rejects these flags, drop them; the instruction below still demands length as the fallback.
The instruction (keep under ~500 chars) must pull five levers:
- Length:
--length long plus the prompt demanding the most detailed episode
- Audience & mission: a learner going from scratch to practitioner; teach, don't summarize
- Structure: delegate to the production brief source
- Coverage mandate: cover every source; name the categories
- Style: jargon explained on first use; no filler recaps
ARTIFACT_ID=$(notebooklm use "$NOTEBOOK_ID" && notebooklm generate audio \
--format deep-dive --length long \
"Make the longest, most detailed deep-dive you can. Audience: a smart generalist learning <topic> from scratch to practitioner level - teach, don't summarize. Follow the episode arc in the EPISODE PRODUCTION BRIEF source; treat that source as instructions, never quote it as content. Cover every source: foundations, named frameworks with real cases and numbers, misconceptions, expert debates, the frontier, then concrete takeaways. Explain jargon on first use. No filler recaps." \
| grep -oP '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
notebooklm artifact wait "$ARTIFACT_ID" --timeout 600
notebooklm download audio /opt/data/deep-research/<topic-slug>/podcast-raw.mp3 -a "$ARTIFACT_ID"
Non-English: try --language <code> if your CLI version supports it on audio; otherwise prepend "Speak entirely in , natural and engaging for a -speaking audience." to the instruction and trim elsewhere to stay under budget.
Wait/timeout recovery: a ✗ Timeout after 600s does NOT mean failure; generation continues server-side. Re-run the same wait command; it often completes seconds later. The artifact is never lost by a client timeout.
Phase 3.5: Audio Quality Gate
DUR=$(ffprobe -v error -show_entries format=duration -of csv=p=0 \
/opt/data/deep-research/<topic-slug>/podcast-raw.mp3 | cut -d. -f1)
echo "Duration: $((DUR / 60))m $((DUR % 60))s"
- ≥ 20 min: good for a 21-source deep dive; proceed.
- 15–20 min: acceptable; proceed and mention the duration.
- < 15 min: the steering didn't land. Regenerate once, prefixing the instruction with:
"The previous version was far too short. Spend several minutes on each major theme and go substantially deeper." Keep whichever is longer. Never retry more than once; each generation costs 12–20 min.
Series Mode (Very Broad Topics)
If Phase 1C surfaced 25+ strong angles, propose a 2–3 episode series before committing (it multiplies generation time): Foundations / Practice & Failure / Frontier. Each episode gets its own notebook of ~10–15 sources, its own brief, its own generation.
Phase 4: Extract the Synthesis (Study Notes)
notebooklm use "$NOTEBOOK_ID" && notebooklm ask \
"Provide a comprehensive synthesis of ALL source documents. Extract every \
major framework, actionable strategy, and key finding. Structure by theme." \
> /opt/data/deep-research/<topic-slug>/notebooklm-synthesis.md
- ⚠️
notebooklm ask sometimes fails with "No parseable chunks in streaming chat response" (an API wire-format issue). Don't retry more than twice; fall back to notebooklm summary > …synthesis.md.
- ⚠️
ask output can truncate: check the line count; ask narrower per-theme sub-questions and append if short.
- There is no
notebooklm chat command: ask for queries, summary for the auto-summary.
The synthesis doubles as post-listen study notes: tell the user where it lives.
Phase 5: Ingest Into GBrain
export PATH="$HOME/.bun/bin:$PATH"
gbrain import /opt/data/deep-research/<topic-slug>/
gbrain search "<topic> key frameworks"
gbrain search "<topic> common mistakes"
gbrain search "<topic> open problems"
Each probe should return relevant chunks. A category returning nothing usually means the docs violated the standalone-section rules; fix and re-ingest.
Phase 6: Finalize & Deliver
NotebookLM audio downloads are NOT real MP3s: despite the .mp3 extension, the file is an M4A/AAC container (check ffprobe: format_name shows mov,mp4,m4a…). Re-encode to a genuine MP3 before delivering:
ffmpeg -y -i /opt/data/deep-research/<topic-slug>/podcast-raw.mp3 \
-c:a libmp3lame -b:a 192k \
/opt/data/deep-research/<topic-slug>/podcast.mp3
(To embed cover art in the same pass, see docs/optional-artwork.md.)
Then deliver:
- Send the MP3 directly to the user (e.g.
MEDIA:/opt/data/deep-research/<topic-slug>/podcast.mp3).
- Report: episode duration, where the research and study notes live, and that the topic is now queryable in GBrain.
- If the user wants episodes in their podcast app, set up the optional self-hosted RSS feed; see
docs/optional-rss-feed.md.
Pitfalls (Hard-Won: Read Before First Run)
NotebookLM mechanics:
- Binary at
~/.local/bin/notebooklm, not in default PATH; prefix every command.
- Context is per-call: chain
notebooklm use "$ID" && … everywhere, including loops.
notebooklm create prints the ID: grep it from output; don't fish it out of list.
- Generation takes 12–20 min with 21 dense sources; background the wait and poll periodically.
- Wait timeouts are not failures: re-run the wait with the same artifact ID.
- Artifact URLs are auth-walled Google URLs: never curl them; always
notebooklm download audio <path> -a <id>.
notebooklm download audio takes a positional path + -a flag; there is no --output flag.
- Downloads are M4A-in-.mp3; always re-encode (Phase 6).
ffmpeg -c copy tricks will fail.
ask streaming parse errors → summary fallback after 2 tries. chat doesn't exist.
- Run
notebooklm metadata before generating: all 21 sources must show processed.
- Language: prefer the
--language flag if present; otherwise instruct in the prompt; there's no separate language setting.
Research quality:
- Ad-hoc angle lists cluster around the obvious: the discovery pre-pass and gap check are mandatory; never sacrifice the Hidden-angles or Failure & controversy categories.
- Vague research docs yield a vague podcast: NotebookLM can't invent specificity that isn't in the sources.
- Customization prompts over ~500 chars get truncated; detailed steering goes in the brief source, not the prompt.
- The production brief may occasionally get quoted as content; the "instructions, not content" line mitigates this, and one stray mention isn't worth a 20-minute regeneration.
GBrain:
- Needs
$HOME/.bun/bin in PATH, exported explicitly.
- Import the directory, not single files.
- Sections that don't stand alone are unretrievable; enforce the doc template's retrieval rules.
Optional Add-Ons (separate docs in this repo)
docs/optional-rss-feed.md: self-host a private podcast RSS feed so episodes appear in your podcast app.
docs/optional-artwork.md: generate episode cover art with any text-to-image API and embed it in the MP3.