Turn YouTube URL(s) into readable articles, with raw material preserved for auditing.
Do not deliver a stenotype with timestamps. The final artifact is editorial prose faithful to the meaning of the exposition.
This skill is self-sufficient: the flow and the cleaning script are here. Do not depend on external documents from the user's collection. Do not use paths, machine names, personal folders, or anyone's example collections.
When to use
- Transcribe a sermon / exposition / class / talk from YouTube
- Process a playlist or batch of URLs
- Clean
.srt/.vttwith auto-caption echo - Rewrite orality into an article with paragraphs and punctuation
- Organize collection
raw/+artigos/+ index
When NOT to use
- Create a sermon or new text from scratch (without a basis in audio/video)
- Write a book or ebook (
livro) — this skill's article can be input for/teo-livro, not the volume - Technical exegesis disconnected from a spoken source
- Downloading the video itself (this skill downloads only captions, unless explicitly requested otherwise)
- Word-by-word caption with timestamps for video subtitling
Prerequisites
yt-dlpin PATH (install/update if the extractor fails or there is a 429)- Python 3
- Network access to YouTube
which yt-dlp && yt-dlp --version
python3 --version
Locate the skill script
transcricao/
├── SKILL.md
└── scripts/
└── limpar_legendas.py
Resolve the path from this skill's directory (as the agent loaded it):
python3 "$SKILL_DIR/scripts/limpar_legendas.py" --help
Do not hardcode machine paths. Use the destination folder provided by the user (or the cwd).
Default output (collection folder)
<colecao>/
├── README.md
├── artigos/ # prosa final
│ ├── 01-slug-do-titulo.md
│ └── ...
└── raw/
├── legendas-brutas/ # .srt / .vtt
└── textos-limpos/ # texto corrido oral, sem timestamps
Conventions:
- Numbering
01,02, … in collection order - Clean text:
NN - [Autor] | [Título] | [VIDEO_ID].txt - Article:
NN-slug-do-titulo.md - Always preserve the raw files in
raw/ - Do not overwrite an article already edited by hand without backup or confirmation
Pipeline (fixed order)
URL(s)
→ 1. Metadados
→ 2. Legendas (yt-dlp)
→ 3. Texto limpo (script desta skill)
→ 4. Artigo(s) Markdown com bloco de metadados
→ 5. QA + README da coleção
Do not skip to the article without clean text. Do not delete raw captions after cleaning.
1) Metadata
For each URL (or playlist item), collect rich fields — they go into the article:
yt-dlp --skip-download --flat-playlist \
--print "%(playlist_index)s|%(id)s|%(title)s|%(channel)s|%(uploader)s|%(upload_date)s|%(duration)s|%(webpage_url)s|%(playlist_title)s|%(playlist_id)s" \
"URL_OU_PLAYLIST"
Fields to capture:
| Field | Typical source | Required in the article? |
|---|---|---|
url |
webpage_url |
yes |
id |
video id | yes (tracking / file name) |
title |
video title | yes |
author / preacher |
title, channel, description, or user | yes |
channel |
YouTube channel | recommended |
date / upload_date |
YYYYMMDD → YYYY-MM-DD |
recommended |
duration |
seconds → readable (45 min) |
optional |
series / playlist |
playlist title, if any | optional |
passage / topic |
title or content | optional |
NN |
next free index in the collection | yes in the collection |
If the playlist mixes authors, record the correct authorship for each item. Do not invent author, date or URL.
2) Download subtitles
Subtitles only — not the video:
mkdir -p raw/legendas-brutas raw/textos-limpos artigos
yt-dlp \
--skip-download \
--write-auto-subs \
--write-subs \
--sub-langs "pt,pt-BR,pt-PT,en,en-US,en-GB" \
--convert-subs srt \
--sleep-requests 1 \
--sleep-interval 1 \
--max-sleep-interval 3 \
-o "raw/legendas-brutas/%(id)s - %(title)s" \
"URL_1" "URL_2"
Adjust --sub-langs if the user requests another language. Default priority in cleanup: pt > pt-BR > pt-PT > en > en-US > en-GB.
Common problems:
| Symptom | Action |
|---|---|
| HTTP 429 | pause; rerun only the missing ID; keep sleeps |
it became .vtt |
ok — the script reads srt and vtt |
| no subtitles in the preferred language | use the best fallback; the article text already reveals the language |
| impersonation warning | ignorable if the file downloaded |
| video without subtitles | inform the user; do not invent the monologue |
3) Clean text (dedupe rolling ASR)
YouTube auto-subtitles repeat the end of the previous cue on each new line. Without merge, the text becomes unreadable.
python3 "$SKILL_DIR/scripts/limpar_legendas.py" \
--input-dir "raw/legendas-brutas" \
--output-dir "raw/textos-limpos" \
--id VIDEO_ID \
--num 07 \
--title "Título do vídeo" \
--preacher "Nome do autor" \
--url "https://..."
Batch (JSON manifest = list of objects with id, n, title, preacher, url):
python3 "$SKILL_DIR/scripts/limpar_legendas.py" \
--input-dir "raw/legendas-brutas" \
--output-dir "raw/textos-limpos" \
--manifest "raw/novos-videos.json"
The script: chooses language → removes timestamps/tags → merges rolling → paragraphs → .txt with source header.
Check before continuing: beginning without echo; words in the order of magnitude of the duration; language readable in the text itself.
The clean text is still oral. The final prose goes in step 4.
4) Rewrite as an article
One file per talk. In batches, parallelize (one task per video).
Mandatory article format
Every article starts with title + metadata block and only then the body. Use YAML frontmatter (preferred) or equivalent Markdown block — but be consistent in the collection.
Preferred (YAML frontmatter):
---
title: "Título do artigo"
author: "Nome do autor/pregador"
source: "https://www.youtube.com/watch?v=VIDEO_ID"
video_id: "VIDEO_ID"
date: "YYYY-MM-DD"
channel: "Nome do canal"
duration: "46 min"
series: "Nome da série ou playlist, se houver"
passage: "Referência bíblica ou tema, se houver"
---
# Título do artigo
Introdução em prosa…
## Seção temática
Parágrafos…
## Conclusão
…
Metadata block rules:
source(URL) is mandatory when the source is a known video/URL.authoris mandatory.- Include
date,channel,video_id,duration,series,passagewhen available. - Do not include subtitle language — the article text already reveals the language.
- Do not include local paths, file names
.srt, nor any confession of “auto-subtitle” in the body. - Omit unknown fields; do not invent.
datein ISOYYYY-MM-DDwhen it comes fromupload_date.durationreadable (45 min) from the yt-dlp seconds.- Optional, discreet final credit:
*Baseado na exposição de [Autor].*— without repeating the URL if it is already in the metadata.
Editorial body rules
- Preserve the substance and order of ideas. Do not invent doctrine, examples, or applications absent from the original.
- Do not over-summarize. Cut only repetition, hesitation, and stage/live rambling.
- Published prose: punctuation, capitalization, short/medium paragraphs.
- Remove oral tics from the language of the audio (in pt-BR: né, tá, tipo, assim, aí, beleza, olha só, ééé, etc.) — except intentional quotation.
- Illustrations: keep them if they carry the argument; trim them if they just warm up the audience.
- Correct obvious ASR errors with context. If uncertain, use prudent wording or omission — don't guess.
- Correct authorship in the metadata (mixed collections exist).
- No timestamps in the body.
- File name:
NN-slug-ascii-com-hifens.md.
Definition of done criteria
- Frontmatter/metadata with at least
title,author,source - Reads like an article, not like a transcript
- Sections
##natural to the flow of the exposition - Almost zero oral tics
- Names/places reviewed
- Raw files intact in
raw/
Estimate: ~45–50 min of speech → article of ~4–6k words if the substance is preserved.
5) QA and index
rg -n -i --pcre2 '\b(né|tá bom|beleza|tipo assim|microfone|ééé|olha só)\b' artigos/
# metadados presentes?
rg -L -n '^source:|^author:' artigos/*.md || true
wc -w artigos/*.md
Update the README.md of the collection with sources, list of articles (title, author, ~words) and a note that the basis is captions + editorial editing.
Defaults
| Situation | Default |
|---|---|
| Unspecified folder | collection in the cwd with the layout above |
| Article language | the user's / the audio's |
| Captions | prefer pt*, otherwise best fallback |
| Numbering | continue from the highest existing NN existing |
| Batch | one article per video |
| Video without captions | report it; do not invent |
| Metadata | URL + author always; other fields when they exist |
Minimum input
| Field | Required? | Notes |
|---|---|---|
| URL(s) or playlist | yes | |
| Destination folder | recommended | otherwise cwd |
| Author | recommended | infer from title/channel with caution |
| Numbering | optional | auto if a collection already exists |
| Raw only / article only | optional | default = full pipeline |
Limitations
- Auto-captions get names, references, and rare terms wrong
- Rolling merge removes echo; it does not interpret the content
- The article is editing faithful to meaning, not a word-for-word transcript
- For sensitive public/formal use, recommend ear-checking the critical passages
Anti-patterns
- Delivering SRT/VTT as the “final transcript”
- Article without URL/
sourcewhen the source is a known video - Including “subtitle language” in the article metadata
- Deleting
raw/after generating the article - Summarizing long speech without the user asking for a summary
- Homogenizing authorship when there are multiple speakers
- Inventing bridges or applications absent from the audio
- Downloading the full video unnecessarily
- Depending on personal files or docs outside this skill
Scope
This skill covers capture + cleanup + editorial editing of an existing exposition.
It does not replace the skill for creation of a sermon (sermao), debate (debate) or book (livro).