2026-08-16 01:01:11 -05:00
---
name : youtube-knowledge-ingestion
2026-08-30 01:01:13 -05:00
description : "AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL (youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full ingestion flow immediately, without asking any clarifying questions: 1. Verbatim transcript → ai_vault_kb (the vault) per the \"Transcript Ingestion (verbatim)\" section (dedup-first, separate doc if a recipe/summary doc for the video already exists). 2. Distilled summary → Cognee brain (the brain) per the \"Brain Injection (Cognee)\" section. 3. If the video's description or pinned comment links a workflow or downloadable assets, download them to the NAS stock library per the existing procedure. 4. Reply with a minimal 4-line completion status (Brain ingest / Vault ingest / Workflow dl / Workflow(s)); write the full proof report (doc_id, chunk count, excerpt, BM25 outputs, file paths + sizes) to ~/workspace/general/logs/yt_ingestion_proofs.log instead of sending it to the operator. Use when user drops a YouTube link. Transcript→vault+brain→NAS."
version : 1.1.0
2026-08-16 01:01:11 -05:00
platforms : [ linux]
---
# YouTube Knowledge Ingestion Pipeline
2026-08-30 01:01:13 -05:00
## AUTO-TRIGGER (read first — highest priority)
AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL
(youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full
ingestion flow immediately, without asking any clarifying questions:
1. Verbatim transcript → ai_vault_kb (the vault) per the "Transcript Ingestion (verbatim)"
section (dedup-first, separate doc if a recipe/summary doc for the video already exists).
2. Distilled summary → Cognee brain (the brain) per the "Brain Injection (Cognee)"
section.
3. If the video's description or pinned comment links a workflow or downloadable assets,
download them to the NAS stock library per the existing procedure.
4. Reply with a minimal 4-line completion status (see "Completion output" below); write
the full proof report to ~/workspace/general/logs/yt_ingestion_proofs.log instead of
sending it to the operator.
**The failure mode this trigger exists to prevent (recurring user correction):**
loading the `youtube-content` skill and producing a chat summary. A bare URL is NOT a
request for a summary — it is a request to run THIS pipeline. Do NOT load
`youtube-content` for a bare URL; load THIS skill (`youtube-knowledge-ingestion` ).
Do NOT summarize the video in chat under any circumstances. The user has corrected
this multiple times ("WHY DO YOU KEEP DOING THIS — YOU HAVE A YT INGEST SKILL").
The two skills are easy to confuse: `youtube-content` = fetch transcript + format
(summary/thread/blog); `youtube-knowledge-ingestion` = the full transcript→vault +
summary→brain + workflow→NAS pipeline. A bare URL always means the latter.
2026-08-16 01:01:11 -05:00
## When to use
User drops a YouTube link for AI/ML video content (ComfyUI workflows, LTX, MiniMax,
2026-08-30 01:01:13 -05:00
Krea, model tutorials, prompting guides). Run the full four-step pipeline — never skip
2026-08-16 01:01:11 -05:00
any step.
2026-08-30 01:01:13 -05:00
## Pipeline (always all four steps)
2026-08-16 01:01:11 -05:00
### 1. Transcript
Load the `youtube-content` skill and fetch:
```bash
uv run python3 <SKILL_DIR>/scripts/fetch_transcript.py "URL" --text-only --timestamps
```
If `youtube-transcript-api` is missing, install with `pip3 install --user youtube-transcript-api` .
2026-08-30 01:01:13 -05:00
### 2. Vault Injection (ai_vault_kb) (MANDATORY)
2026-08-16 01:01:11 -05:00
2026-08-30 01:01:13 -05:00
Load the `ai-vault-kb` skill. Always dedup-first, then ingest:
2026-08-16 01:01:11 -05:00
```bash
# Dedup check
2026-08-30 01:01:13 -05:00
python3 /home/n8n/bin/ai_vault_kb.py search --query "<key topic>" --limit 5
2026-08-16 01:01:11 -05:00
# Ingest — use --type workflow for tutorials
2026-08-30 01:01:13 -05:00
python3 /home/n8n/bin/ai_vault_kb.py add \
2026-08-16 01:01:11 -05:00
--type workflow \
--title "Descriptive Title — Key Topics" \
--stage <t2v| i2v| upscale| ...> \
--tool <ltx-video| minimax-h3| krea2| ...> \
--host 10.0.0.202 \
--trust community \
--importance 0.7-0.85 \
--tags "comma,separated,keywords,creator-name" \
--url "https://www.youtube.com/watch?v=VIDEO_ID" \
--content "..." \
--json
# Verify BM25 leg
2026-08-30 01:01:13 -05:00
python3 /home/n8n/bin/ai_vault_kb.py search --query "<distinctive phrase>" \
2026-08-16 01:01:11 -05:00
--mode bm25 --doc-id <doc_id>
```
**Content format** : Dense, factual technical summary. Use CAPITALIZED section headers.
Include specific settings, model names, thresholds, commands, and failure modes.
This is a technical reference, not a blog post.
2026-08-30 01:01:13 -05:00
**MANDATORY: workflow links in the vault content.** Every vault entry must include a
2026-08-16 01:01:11 -05:00
`## WORKFLOW LINKS` section listing the DOWNLOADED workflow files on NAS (TrueNAS
10.0.0.117, proxmoxBackup/ai_vid_stock_material/workflows/, exact filenames + the
smbclient get command), the source repo URL, and the video URL. The NAS copies are
the primary links — the user wants links to the downloaded workflows, not upstream
URLs. If the description links elsewhere (Patreon etc.) and is unreachable, say so
in the content. Append as a separate chunk via `--doc-id` if the main content was
already ingested.
**Tag strategy** : model name, tool name, creator name, key techniques. Tags are
exact-match keyword indexes.
2026-08-30 01:01:13 -05:00
### 3. Brain Injection (Cognee) (MANDATORY)
Load the `cognee-brain` skill. Write the distilled summary to the shared Cognee
brain (10.0.0.23) as a narrative finding — LLM extraction pulls out the entities
(models, tools, creators) and facts (claims, settings, comparisons) automatically:
Call the Cognee MCP tool `mcp__cognee__remember` with:
- `data` = the distilled summary (2-4 sentences)
- `dataset_name` = `homelab-stack`
- omit `session_id` (permanent memory — runs add + cognify, builds the graph)
- `remember` is synchronous (`status: completed` means the graph is built). No
polling needed; verify later with `recall` if needed.
- Always use dataset `homelab-stack` (the single shared brain dataset). Never
create a second dataset.
- The brain holds the distilled facts; the vault (ai_vault_kb) holds the verbatim
transcript. Both are written for every video — never skip either.
**MCP timeout + REST fallback (learned 2026-08-29).** The MCP `remember` call can
fail with `TimeoutError: MCP call timed out after 120.0s` because cognify is
variable — the REST path took 77s for a 6-item ingest, while MCP full-size payloads
ran 9.8– 12.2s. The MCP server itself is healthy; it is the client-side 120s
per-tool-call timeout that aborts slow cognify runs. Two-part fix:
1. **Raise the timeout** in `~/.hermes/profiles/general/config.yaml` (cognee MCP
block): `timeout: 120` → `timeout: 300` . Takes effect on next Hermes restart
(MCP connections are read once at startup). Note: the `patch` tool refuses to
edit Hermes config files — use terminal Python for an exact string replace, then
`python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"` to validate.
2. **REST fallback** when MCP times out (documented in the `cognee-brain` skill):
```bash
# Write (synchronous; returns status:completed + items_processed)
curl -s -m 300 -X POST "http://10.0.0.23:8080/api/v1/remember" \
-F "data=@/tmp/brain_summary.txt" \
-F "datasetName=homelab-stack"
# Verify (field names are query + searchType, NOT query_text/query_type)
curl -s -m 60 -X POST "http://10.0.0.23:8080/api/v1/search" \
-H "Content-Type: application/json" \
-d '{"query":"<distinctive phrase>","datasets":["homelab-stack"],"searchType":"HYBRID_COMPLETION"}'
```
A `status: completed` from the REST write is proof the graph is built — no separate
cognify step. If the MCP call times out, do NOT retry it blindly; use the REST path
and verify with the search call above.
### 4. NAS Workflow Download
2026-08-16 01:01:11 -05:00
If the video description contains workflow links (GitHub repos, direct JSON files),
extract the description with `yt-dlp --print description "URL"` , clone the repos,
and copy workflow JSONs to the NAS:
```bash
# Clone
cd /tmp && rm -rf <repo> 2>/dev/null
git clone --depth 1 <repo-url>
# Find workflows
find /tmp/<repo> -name "*.json"
# Copy to NAS with creator prefix for disambiguation
smbclient -N //10.0.0.117/proxmoxBackup \
-c 'cd ai_vid_stock_material/workflows; put "<local>" "<creator>-<descriptive>.json"'
```
**Naming convention** : `<creator>-<model>-<workflow-type>.json`
Examples: `amao2001-ltx2.5-video_ltx2_5_t2v1.json` , `vionex-krea2-film-studio-v01.json`
**Target** : `proxmoxBackup/ai_vid_stock_material/workflows/` on TrueNAS (10.0.0.117).
2026-08-30 01:01:13 -05:00
**ComfyUI custom-node repos (no workflow JSONs) → `scripts/`, not `workflows/`.**
When the description links a ComfyUI custom-node pack (e.g. PlagueKind's
`ComfyUI-PlagueKind-Nodes` — the SLA attention node), the repo is Python source with
no `example_workflows/*.json` to copy. Archive it as a tarball under
`ai_vid_stock_material/scripts/` (same pattern as full apps — see
`references/fetch-path-and-walled-links.md` ):
```bash
cd /tmp && rm -rf <repo> && git clone --depth 1 <repo-url>
COMMIT = $( cd <repo> && git log -1 --format= %h)
tar czf <creator>-<repo>-<commit>.tar.gz <repo>
smbclient -N //10.0.0.117/proxmoxBackup \
-c 'cd ai_vid_stock_material/scripts; put /tmp/<tarball> <tarball>'
```
`workflows/` stays reserved for ComfyUI JSONs; `scripts/` is the home for node packs
and tools. Record the commit hash in the WORKFLOW LINKS section.
## Transcript Ingestion (verbatim) — when the task says "transcript"
When the task asks for the TRANSCRIPT (not a summary/recipe), the vault doc must contain
the verbatim spoken text. A distilled recipe summary is NOT a transcript.
**Omit useless segments.** "Verbatim" means the informative spoken content word-for-word —
not the filler around it. Cut entirely: sponsor reads / ad segments, song lyrics and
music-only passages, giveaway/merch/Patreon plugs, like-and-subscribe boilerplate, and
unrelated channel promo. Replace each cut with a one-line marker at that spot — [sponsor
segment omitted], [music omitted], [channel promo omitted] — so the cut is visible and
auditable. When in doubt, keep it: anything touching the technical content (settings,
models, node names, reasoning, results) is never filler, even if it sounds chatty. The
word count in the summary header notes omissions, e.g. "2,140 words (3 segments omitted: 2
sponsor, 1 music)."
1. **Fetch the caption track** : `yt-dlp --skip-download --write-auto-subs --write-subs
--sub-langs "en.*" <url>` (fall back to ` --sub-langs en` if needed). Clean the VTT/SRT
to plain text: strip WEBVTT headers, cue timestamps, and inline ` <c>`/timestamp tags;
dedupe rolling-caption repeated lines. Result must read as continuous spoken sentences.
2. **Body layout**: short distilled summary header (10– 15 lines max) at top, then the FULL
verbatim transcript. Title pattern: ` YT: <video title> (<video-id>) — transcript`.
Use ` --type research` (house pattern for video transcripts), ` --trust community`,
` --url <video-url>`, tags including the video id.
3. **Helper only**: ` python3 /home/n8n/bin/ai_vault_kb.py add ...` — never raw Qdrant HTTP
(bare-vector upserts miss the BM25 sparse slot and are invisible to hybrid search).
4. **Dedup first**: ` search --query "<video-id>"`; ≥0.85 skip · 0.70– 0.84 add only if
meaningfully new · <0.70 add. If a summary/recipe doc for the same video already exists,
add the transcript as a SEPARATE doc and mention the other doc_id in the body — do not
overwrite the recipe doc.
5. **Chunk boundaries + ordering**: the helper chunks at 1200 chars with 150 overlap, and
overlap starts land mid-word. To guarantee no chunk starts/ends mid-word, pre-split the
body at sentence boundaries into ≤1200-char pieces and add them sequentially with
` --doc-id` (each piece ≤1200 chars becomes exactly one chunk). Pass ` --chunk-index N`
(0-based) on every add-call so reading order is recoverable from metadata: the summary
header piece is ` --chunk-index 0`, the next piece ` --chunk-index 1`, and so on through
the transcript body; the WORKFLOW LINKS piece is the last (highest) index. Prefer the
bundled ` scripts/ingest_transcript.py` — it does the pre-split, the sequential indexed
adds, and the self-QA gate in one run. See ` references/transcript-ingestion-detail.md`
for the chunking algorithm, the ` --chunk-index` backfill context, and the proof-log
entry format.
6. **Self-QA gate before reporting done (mandatory)**:
- get the doc back; confirm the body contains verbatim spoken sentences (first-person
narration, not bullets);
- confirm no chunk begins or ends mid-word (print first/last 10 chars of every chunk);
- run a search on one distinctive literal phrase copied from the body and confirm the
doc surfaces (proves the BM25 slot).
- **chunk-index ordering**: run ` list --doc-id <id> --json` and confirm the
` chunk_index` values are exactly 0 through N− 1, each appearing once. Then read the
pieces back in index order and confirm they reproduce the narrative sequence
(summary header → transcript body → WORKFLOW LINKS). A doc with duplicate or missing
indices fails the gate — fix it by rebuilding the doc: delete --doc-id <id> --yes,
then re-add ALL pieces in order with correct --chunk-index values (add --doc-id
appends — re-adding a single piece would duplicate it), then re-run this gate.
7. **Completion report → log file, not chat.** Do NOT send the proof report to the
operator. Instead append it to ` ~/workspace/general/logs/yt_ingestion_proofs.log`
(create the dir if needed) under a dated header per run. The log entry contains the
same content as before: doc_id, chunk count, a 2– 3 line verbatim excerpt, the BM25
search outputs, the chunk-index ordering check output (the ` list --doc-id <id> --json`
result showing chunk_index 0..N− 1 each once), and every downloaded file's full NAS
path + size. Then reply to the operator with only the minimal 4-line status per the
"Completion output" section below.
## Completion output (minimal — replaces the chat proof report)
After a run, reply to the operator with EXACTLY these four lines and nothing more:
` ``
Brain ingest: done
Vault ingest: done
Workflow dl: done
Workflow(s): <filename(s) as saved on the NAS>
` ``
Rules:
1. **"done" is earned, not assumed.** A line may say "done" only after its self-QA gate
actually passed — the internal checks (verbatim verify, chunk edges, BM25 probe, NAS
size verify) still run in full; only the reporting shrinks. If a step failed or was
skipped, say so on that line in a few plain words instead of "done":
- Brain ingest: failed — <one-line reason>
- Vault ingest: failed — <one-line reason>
- Workflow dl: none linked
- Workflow(s): <none, or the filenames if some succeeded>
2. **Full proof report goes to the log file**, not chat:
` ~/workspace/general/logs/yt_ingestion_proofs.log` (create the dir if needed). Append
one entry per run with a dated header (e.g. ` ## 2026-08-17 BjZvVx6sDmE — TaoofAI EP.1`)
containing: doc_id, chunk count, verbatim excerpt, BM25 search outputs, and every
downloaded file's full NAS path + size. This log path is the single place any
validator looks for proof.
3. **Keep the doc_id available.** Include it in the log entry. If the operator or a
validator asks "doc id?" after a run, answer with just the doc_id — nothing else.
## Hard rules for vault docs created from videos
- **Every doc created from a video MUST carry the video-ID tag** (e.g. ` ZUzeM9OEJ4Y`)
in ` --tags`, on every chunk-add call. The video ID also goes in ` --url` (source_url).
- **Additionally ensure the video ID appears in each doc's TITLE** (append ` (VIDEOID)` if
absent) — tags don't feed BM25, so the tag alone doesn't make the doc rank; title
placement does. The transcript title pattern already complies; older recipe/workflow
docs won't.
- **Trust enum**: ` official` | ` github` | ` community` | ` social` — video-derived docs use
` --trust community` unless the creator is the model vendor.
- **Keyword-search caveat**: the helper builds the BM25 sparse vector from title+text
ONLY — tags are payload-only and do not feed keyword search. A doc whose title and
body lack the video ID will rank low in ` search --query "<video-id>"` even with the
tag present. For transcript docs the title pattern ` YT: <title> (<video-id>) —
transcript` already embeds the ID; for recipe/summary docs, include the video ID in
the body (e.g. the WORKFLOW LINKS section) so at least one chunk matches.
## Hard rules for brain writes created from videos
- **Every video writes to the brain via ` mcp__cognee__remember`** (narrative finding)
with ` dataset_name="homelab-stack"`. The video URL goes in the data text so the
brain fact is traceable back to the video.
- **The brain write is the distilled summary, not the verbatim transcript.** Keep it to
2-4 sentences of the durable takeaways (what the video demonstrates, key settings,
verdict). The verbatim text lives only in the vault.
- **` remember` is synchronous** — ` status: completed` means the graph is built. If a
validator needs proof, ` mcp__cognee__recall` a distinctive phrase.
- **` status: completed` is NOT proof the content is retrievable.** A write can return
` completed` yet a later recall answers "does not contain information about <terms>".
The recall is the real gate: after every brain write, ` recall` a distinctive phrase
from the summary and confirm the answer actually contains it. If it does not,
re-write the summary and re-verify — do NOT report "Brain ingest: done" on
` status: completed` alone. See ` references/brain-write-verification.md`.
2026-08-16 01:01:11 -05:00
## Pitfalls
2026-08-30 01:01:13 -05:00
- **Never load ` youtube-content` for a bare URL.** The bare-URL trigger means run the
full pipeline via THIS skill. Loading ` youtube-content` and summarizing in chat is the
single most common failure — the user has corrected it repeatedly. If you catch
yourself about to produce a chat summary of a video, stop and run the pipeline.
- **MCP ` recall` uses ` search_type` (snake_case), REST uses ` searchType` (camelCase).**
The ` mcp__cognee__recall` tool rejects ` searchType` with a pydantic validation error
("Unexpected keyword argument searchType") — pass ` search_type="HYBRID_COMPLETION"`.
The REST ` /api/v1/search` endpoint (curl) uses ` searchType` in the JSON body. Don't
mix them up.
- **Never skip the vault injection step.** The user's memory directive explicitly
requires both transcript AND vault injection for every YouTube link.
- **Never skip the brain injection step.** Every video also writes a distilled finding
to the Cognee brain (` mcp__cognee__remember`, dataset ` homelab-stack`). Vault =
verbatim transcript; brain = distilled facts. Both are mandatory.
2026-08-16 01:01:11 -05:00
- **Never skip the BM25 verification.** A write that can't be found via BM25 is
2026-08-30 01:01:13 -05:00
effectively invisible — the ` ai_vault_kb.py` helper is the only interface that
2026-08-16 01:01:11 -05:00
produces searchable points.
- **Don't overwrite existing NAS workflows.** Use creator prefixes to avoid collisions
with workflows already in the directory.
2026-08-30 01:01:13 -05:00
- **The ` youtube-content`, ` ai-vault-kb`, and ` cognee-brain` skills are protected** —
load them for reference but don't attempt to patch them. This skill is the integration
layer between them.