Skip to content
Back to skills

Youtube Topic Research

ASecurity

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.

  • 89 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 19, 2026
ai-agentspythonrustgobashreactdockerdebuggingapidatabasebackend

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 10 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add moonlight-lupin/agent-skills --skill youtube-topic-research --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Youtube Topic Research?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Youtube Topic Research
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/moonlight-lupin-youtube-topic-research/badge)](https://www.skillsdirectory.com/skills/moonlight-lupin-youtube-topic-research)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: youtube-topic-research
description: "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."
license: MIT
metadata:
  version: 2.0.0
  author: moonlight-lupin
  platforms: [linux, macos, windows]
---

# YouTube Topic Research Skill

## When to Use

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:**
- "Find YouTube videos on Python async programming"
- "Show me recent videos about LLM fine-tuning"
- "What are the best tutorials for React Server Components?"
- "Research this topic through YouTube, then build a vault" → feeder mode

## Two Modes

### Standalone mode (default)

Search YouTube, fetch transcripts, rank videos, and return the top
recommendations with summaries, freshness indicators, and watch/skip guidance.

### NotebookLM feeder mode

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:**
- "add these to notebooklm"
- "make a source vault from these videos"
- "research this through YouTube first, then build a vault"
- "use videos as sources"

```bash
# Feeder mode — export selected videos as notebooklm-mode source files
python scripts/search_and_summarize.py "docker networking" --export-vault /path/to/vault
```

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.

### Architecture

```
youtube-topic-research
        │
        ├── standalone recommendation output (default)
        │
        └── --export-vault: selected videos as source files
                    │
                    ▼
             notebooklm-mode vault
                    │
                    ▼
          grounded Q&A / notes / reports / slides
```

## Relationship to notebooklm-mode

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.

## Prerequisites

```bash
pip install ddgs "youtube-transcript-api<1.0" jinja2 pyyaml
```

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.

## Quick Start

```bash
# 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/vault
```

## Pipeline

```
User 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   │
└─────────────────────────────────────┘
```

### LLM Integration

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()`:

```python
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
```

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.

### Visual Analysis Caveat

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.

## Feeder Mode Source File Format

When `--export-vault` is used, each video is saved as a source file compatible
with `notebooklm-mode`:

```markdown
# 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 Y
```

## Configuration

### Fast-Moving Domains (`references/fast_moving_domains.yaml`)

Defines freshness thresholds for topics where recent content matters more:

```yaml
domains:
  - name: ai_ml
    keywords: ["ai", "llm", "fine-tuning", "gpt", "claude", ...]
    stale_months: 12
    aging_months: 6
  # ... web_frameworks, cloud_devops, programming_languages, databases
```

Unmatched topics use defaults (stale > 36mo, aging > 24mo).

### Defaults

| 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` |

## Error Handling

| 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` |

## Limitations

- **No YouTube API** — relies on DuckDuckGo video index (may miss very new/unindexed videos)
- **Transcript availability** ~50-70% of videos; auto-captions may have errors
- **Rate limits** — DDG may throttle rapid requests; skill adds 1-2s delay between calls
- **Token cost** — Full transcript review via LLM uses ~5-15K tokens per video
- **Language** — Prefers English; falls back to any available transcript
- **IP blocking** — Cloud provider IPs may be blocked by YouTube; see workaround reference
- **No visual inspection** — identifies likely visual/demo videos from metadata, not frame analysis

## Extending

- Add domains to `references/fast_moving_domains.yaml`
- Customize `references/qualify_prompt.md` / `references/review_prompt.md`
- Modify `templates/output.md.j2` for different output formats (Discord, Slack)
- Set `TRANSCRIPT_SCRIPT` env var to point at an alternative transcript fetcher
- Override `call_llm()` for LLM-driven qualification and review

### Files

```text
youtube-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
```

Files in this skill

  • SKILL.md11.6 KB
  • references/debugging-patterns.md4.6 KB
  • references/fast_moving_domains.yaml3.2 KB
  • references/ip-blocking-workaround.md4.2 KB
  • references/qualify_prompt.md2.7 KB
  • references/review_prompt.md3 KB
  • requirements.txt306 B
  • scripts/search_and_summarize.py40.5 KB
  • templates/output.md.j21.7 KB
  • tests/test_search_and_summarize.py34.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.