npx skills add ...
npx skills add moonlight-lupin/agent-skills --skill youtube-topic-research
Use when a topic is best explained by YouTube videos β find and summarize YouTube videos for topics where visual explanation, demos, tutorials, talks, walkthroughs, or screen recordings are useful. Can run standalone, or export transcript-backed video source notes into notebooklm-mode vaults for grounded research.
npx skills add moonlight-lupin/agent-skills --skill youtube-topic-research
Use when the user wants to find and summarize YouTube videos on a specific topic β not when they already have a URL (use a transcript extraction skill for that). This skill searches, filters, fetches transcripts, and returns the top relevant videos with summaries.
Examples:
Search YouTube, fetch transcripts, rank videos, and return the top recommendations with summaries, freshness indicators, and watch/skip guidance.
After the user approves videos, save each selected video as a source file
compatible with notebooklm-mode, including metadata, URL, transcript
extracts, visual/demo notes, summary, and freshness status.
Trigger phrases for feeder mode:
This generates source files in sources/ inside the vault, formatted for
notebooklm-mode ingestion. The agent can then run notebooklm-mode for
grounded Q&A, notes, reports, or slides built on the video sources.
This skill can be used standalone or as a feeder into notebooklm-mode:
| Use case | Mode |
|---|---|
| "Find me good YouTube tutorials on Docker networking" | Standalone |
| "Find recent visual demos of Godot 4 agent workflows" | Standalone |
| "Research this topic using YouTube and save sources" | Feeder β notebooklm-mode |
| "Build me a grounded brief from videos and articles" | youtube-topic-research + notebooklm-mode |
| "Summarize this one YouTube URL" | Separate transcript extraction skill |
Most users asking for videos just want recommendations. Feeder mode is for real research β when video sources should ground further Q&A and deliverables.
The ddgs CLI (DuckDuckGo search) is the primary search backend.
youtube-transcript-api is used for transcript fetching. Pin to <1.0:
the script uses the get_transcript() / list_transcripts() static-method
API, which was removed in youtube-transcript-api 1.0 (renamed to instance
methods .fetch() / .list()). An unpinned install pulls 1.x and transcript
fetching silently returns nothing.
Steps 2 and 4 have LLM prompt templates (references/qualify_prompt.md and
references/review_prompt.md). The script uses heuristic scoring by default.
To enable LLM qualification/review, an agent runtime overrides call_llm():
When call_llm() returns a valid JSON dict, the script uses LLM scoring. When
it returns None, the script falls back to heuristic scoring. The heuristic
uses keyword overlap (with stopwords removed), view count, duration, and age.
For long transcripts (>40K chars), the script chunks the transcript and reviews each chunk individually via LLM, then merges the results.
This skill can identify likely visual/demo-rich videos from metadata, titles, descriptions, and transcripts, but unless the runtime supports frame/image inspection, it does not truly inspect the video visuals. Transcript-grounded summary is not the same as visual analysis. The skill flags videos that likely contain demos, walkthroughs, or visual explanations based on title/description keywords, but cannot confirm what the viewer will actually see on screen.
When --export-vault is used, each video is saved as a source file compatible
with notebooklm-mode:
references/fast_moving_domains.yaml)Defines freshness thresholds for topics where recent content matters more:
Unmatched topics use defaults (stale > 36mo, aging > 24mo).
| Parameter | Default | Override |
|---|---|---|
max_candidates | 8 | --max-candidates |
qualify_top_k | 4 | --qualify-top |
transcript_top_k | 3 | --transcript-top |
final_top_k | 2 | --top |
min_transcript_chars | 500 | --min-transcript |
chunk_size | 40000 | --chunk-size |
enable_freshness | true | --no-freshness |
| Failure Point | Behavior |
|---|---|
ddgs not installed | Exit with install instruction |
ddgs videos returns empty | Retry once with broader query; report if still empty |
| No YouTube results in DDG | Report "no YouTube videos found for query" |
| All transcripts fail/disabled | Return raw DDG list + "could not fetch transcripts" |
| LLM qualification fails | Fallback: heuristic scoring |
| Transcript > chunk_size | Auto-chunk with 2K overlap, review each, merge |
| Output formatting fails | Fallback to plain text summary |
| IP blocked (cloud VM) | See references/ip-blocking-workaround.md |
references/fast_moving_domains.yamlreferences/qualify_prompt.md / references/review_prompt.mdtemplates/output.md.j2 for different output formats (Discord, Slack)TRANSCRIPT_SCRIPT env var to point at an alternative transcript fetchercall_llm() for LLM-driven qualification and reviewpip install ddgs "youtube-transcript-api<1.0" jinja2 pyyaml# Standalone β returns top 2 videos with summaries
python scripts/search_and_summarize.py "python async tutorial"
# Custom top-k
python scripts/search_and_summarize.py "LLM fine-tuning 2024" --top 3
# Disable freshness flags (for evergreen topics)
python scripts/search_and_summarize.py "linux basics" --no-freshness
# JSON output for programmatic use
python scripts/search_and_summarize.py "rust ownership" --format json
# Feeder mode β export to a notebooklm-mode vault
python scripts/search_and_summarize.py "docker networking" --export-vault /path/to/vaultUser Query
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 1. SEARCH (ddgs videos) β
β -q "query" -m 8 -o json β
β Filter: publisher == "YouTube" β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 2. QUALIFY (heuristic or LLM) β
β Score 0-100 per candidate β
β Criteria: topic_match, authority,β
β duration_signal, freshness β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 3. FETCH TRANSCRIPTS (top 3-4) β
β youtube_transcript_api direct β
β OR external fetch_transcript.py β
β Health check: len > 500 chars β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 4. REVIEW (heuristic or LLM) β
β Relevance score + summary bulletsβ
β Chunk if > 40K chars β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β 5. FORMAT & OUTPUT β
β Standalone: output.md.j2 β
β Feeder: notebooklm source files β
βββββββββββββββββββββββββββββββββββββββimport search_and_summarize
def my_llm_call(prompt: str) -> dict | None:
# Call your LLM API (OpenAI, Ollama, Hermes, etc.)
# Must return a parsed JSON dict matching the prompt's output schema
response = my_llm_api.chat(prompt)
return json.loads(response)
search_and_summarize.LLM_CALL = my_llm_call# YouTube Source: [Video Title]
| Field | Value |
|------|-------|
| URL | https://youtube.com/watch?v=... |
| Uploader | Channel Name |
| Published | YYYY-MM-DD |
| Duration | 18:42 |
| Views | 1.2M |
| Retrieved | YYYY-MM-DD |
| Type | youtube |
| Transcript Quality | good |
| Freshness | fresh |
## Why Selected
[Short reason based on query fit, authority, freshness, and transcript relevance.]
## Visual / Demo Value
- Shows live coding / dashboard / product walkthrough / diagrams / UI demo.
- Useful because this topic benefits from visual explanation.
## Transcript Extracts
> "Relevant transcript quote..."
> β approx. timestamp: 04:12
> "Another relevant quote..."
> β approx. timestamp: 09:45
## Summary
- Key point 1
- Key point 2
- Key point 3
## Gaps
- Does not cover X
- Assumes Ydomains:
- name: ai_ml
keywords: ["ai", "llm", "fine-tuning", "gpt", "claude", ...]
stale_months: 12
aging_months: 6
# ... web_frameworks, cloud_devops, programming_languages, databasesyoutube-topic-research/
βββ SKILL.md # This file
βββ scripts/
β βββ search_and_summarize.py # Main entry point
βββ references/
β βββ qualify_prompt.md # LLM prompt for metadata qualification
β βββ review_prompt.md # LLM prompt for transcript review
β βββ fast_moving_domains.yaml # Freshness thresholds by domain
β βββ debugging-patterns.md # DDG CLI quirks, date parsing, transcript cleaning
β βββ ip-blocking-workaround.md # YouTube IP blocking workarounds (cloud VMs)
βββ templates/
βββ output.md.j2 # Jinja2 template for standalone output