# Blueprint: turn videos into a library I can ask questions of

This is a plan for my agent to follow. I read it. The agent does the steps. I check the file landed. Keep this file at `blueprints/youtube-transcripts.md` in my workbench.

The first time, do only Part 1: one video, one file. Parts 2 and 3 are for when I come back and want more.

## Rules, every time

- Work only inside this workbench. Do not change files outside it.
- Ask me before installing anything, and tell me what the install will do.
- Never sign in to anything, never add cookies or an account to get around a block. If a video will not work, say so and I will pick another.
- Only pull captions for videos I give you or choose from a list you showed me. Choosing what I may keep is my job.
- Be polite to the video site: one video at a time, a three-second pause between videos, no more than twenty in one sitting.
- Never invent a transcript. If there are no captions, stop and tell me.

## Part 1: one video

### 1. Install or update the fetch tool

The tool is `yt-dlp`, a small public program. It reads the captions a video already has.

- First check whether it is already here: run `yt-dlp --version`.
- If it is missing, install it the standard way for this computer: Mac `brew install yt-dlp`; Windows `winget install yt-dlp.yt-dlp` (or `py -3 -m pip install yt-dlp`). Its own install page is https://github.com/yt-dlp/yt-dlp#installation. Tell me the command before you run it. My computer may ask me once.
- Mac only: if Homebrew starts compiling `llvm`, `rust`, or `deno` from source, stop it. That happens on a macOS version Homebrew no longer ships pre-built packages for, and it ends at a wall asking for Xcode, which I do not need. This blueprint only needs a `yt-dlp` command on my PATH, and yt-dlp is plain Python, so install it without compiling anything: `pipx install yt-dlp` if pipx is here, otherwise `python3 -m pip install --user yt-dlp` (add `--break-system-packages` if pip refuses). Then add the folder pip names to my PATH in my shell profile, so a fresh terminal finds it too, and check with `yt-dlp --version`.
- If yt-dlp warns that no JavaScript runtime or no impersonation target was found, keep going; the captions still come through without either. Only if the captions actually fail, tell me before installing anything.
- If it is present but the fetch fails later, update it the same way it was installed (`brew upgrade yt-dlp`, `pipx upgrade yt-dlp`, `python3 -m pip install --user --upgrade yt-dlp`, or `yt-dlp -U`) and try once more. The tool breaks a few times a year when the video site changes something; the fix is the update, never a change to this file. One exception: `HTTP Error 429` or "Too Many Requests" is the video site asking us to slow down, not an old tool. Updating will not help; step 2 says what to do.
- Tell me the version you ended up with.

### 2. Pull the captions for one link

Replace `VIDEO_URL` with the link I give you.

First, see which caption languages the video actually has:

```
yt-dlp --ignore-config --no-playlist --list-subs "VIDEO_URL"
```

Pick one English track, using the exact code from the list, in this order:

1. English written by the channel (listed under "Available subtitles"): usually `en`, sometimes `en-US` or `en-GB`.
2. Otherwise the auto-generated English in its original form: the code that ends in `-orig`, usually `en-orig`. Auto-generated is fine; say so in the report.
3. Only if neither is listed, the plain auto-generated `en`. The video site often refuses this one with `HTTP Error 429`, while `en-orig` holds the same words and comes through.

If the video has no English, pick the language it actually has (its `-orig` code if one is listed). Put that one code in place of `CODE` below; do not use a pattern like `en.*`, because it also matches the auto-translated tracks (`en-en`, `en-es-MX`, and so on) and pulling all of them at once gets the fetch rate-limited. Then fetch only the captions, no video:

```
yt-dlp --ignore-config --no-playlist --skip-download --write-subs --write-auto-subs --sub-format vtt --sub-langs "CODE" --no-overwrites -o "library/%(id)s.%(ext)s" "VIDEO_URL"
```

If the fetch fails with `HTTP Error 429` or "Too Many Requests", the video site is asking us to slow down. Do not update the tool for this. If you used plain `en` and an `-orig` track is listed, switch to it. Otherwise wait 5 seconds and try the same command again, then 10 seconds, then 20: three retries at most. If it still fails, stop and tell me "the video has captions, but the video site refused them right now." That is different from a video with no captions; I can try again later or pick another video.

Then grab the facts about the video, so the file can name them:

```
yt-dlp --ignore-config --no-playlist --skip-download --print "%(title)s | %(channel)s | %(upload_date)s | %(duration_string)s | %(id)s" "VIDEO_URL"
```

If there are no captions at all, stop and tell me. I will pick another video.

In Codex, the first fetch needs network access, and the app asks me once; wait for me to approve it. If the fetch fails with a name-lookup or connection error, that is the missing network permission, not an old tool: ask me for the permission before offering an update.

### 3. Save it in library/, in a shape I can search later

Turn the `.vtt` file into one readable Markdown file next to it: `library/<video-id>.md`. Start the file with a short header block so every transcript in my library has the same facts in the same place:

```
---
title: "the video's title"
channel: "the channel name"
url: "the link"
date: "upload date, written out"
length: "how long"
captions: "auto-generated" or "written by the channel", and the track code (for example en-orig)
saved: "today's date"
topics: []
---
```

Then the words, in order, with a timestamp every minute or so, like `[12:40]`, so I can find a passage again. Keep the `.vtt` file too; it is the source. Do not fix names or quotations you are unsure of; leave them as the captions had them.

If I gave you a topic or two for this video, put them in `topics`. Otherwise leave it empty; I can add them later.

### 4. Report, then stop

Three lines: the file name, how long the video was, and whether the captions were auto-generated. Do not summarize the video unless I ask.

## Part 2: more than one video

Same rules, same four steps per video, with two additions: **skip anything already in my library** (if `library/<video-id>.md` exists, do not fetch it again; tell me you skipped it), and **pause three seconds between videos**.

The only thing that changes is how you get the list of videos. Show me the list first, with titles, and wait for me to say which ones. Never fetch a whole list I have not looked at.

**Several links.** I paste them; you go one at a time.

**A playlist.** Newest first, no more than `N` (I will say how many; if I do not, use 10):

```
yt-dlp --ignore-config --flat-playlist --playlist-end N --print "%(id)s | %(title)s | %(duration_string)s" "PLAYLIST_URL"
```

**A channel's latest.** The channel's videos page is `https://www.youtube.com/@handle/videos`:

```
yt-dlp --ignore-config --flat-playlist --playlist-end N --print "%(id)s | %(title)s | %(duration_string)s" "https://www.youtube.com/@handle/videos"
```

**A search.** I give you a topic; you show me the top results and I choose:

```
yt-dlp --ignore-config --flat-playlist --print "%(id)s | %(title)s | %(channel)s | %(duration_string)s" "ytsearch10:MY TOPIC HERE"
```

After a batch, report one line per video: saved, skipped (already here), no captions, or refused (captions there, but the site said 429 after three retries). If two videos in a row are refused, stop the batch and tell me; it is better to come back later than to keep asking.

## Part 3: make a card, so I never have to reread the transcript

A transcript is the source. A card is the one page I actually reuse. When I ask for cards, or when I say "what in my library has no card yet":

1. Look at every `library/<video-id>.md`. For each one with no `work/cards/<video-id>.md`, it is pending. Tell me the pending list and wait; I may not want all of them.
2. For each one I choose, read the whole transcript and write `work/cards/<video-id>.md` with exactly these sections:
   - **The claim in three lines.** What this person is actually arguing.
   - **The points, with timestamps.** Five to eight, each one a sentence, each with the `[mm:ss]` where it is said, so I can check it against the video.
   - **The one thing to try.** What they would tell me to do first, in my situation, from my context note.
   - **What it does not cover.** The gap I would still have after taking their advice.
   - **My questions.** Two or three things I would ask them.
3. Copy the header block from the transcript to the top of the card, so the card knows where it came from.
4. Show me each card. I will correct it. Save only what I confirmed.

When I ask a question about a subject later, read the cards first, then the transcript only for the passage you need. Quote it with its timestamp. Say which video each point came from.

## When I come back

Before we stop: write what I was doing and my next unanswered question into `context/handoff.md`, and offer `aibl-checkpoint` for the exact files we made today (the transcripts, the cards, the handoff). I decide whether the transcripts belong on my private GitHub copy; they are big, and they are someone else's words.

Next time, read the handoff first, then the cards it names, then wait for me.
