Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when user asks YouTube video extraction, get, fetch, transcripts, subtitles, or captions. Writes video details and transcription into structured markdown file.
.claude/skills/nicepkg-youtube-to-markdown/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | -3% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 30% | 0% |
| case-11 | ✓→✓ | = Same ✓ | 9% | 0% |
| case-20 | ✓→✓ | = Same ✓ | 71% | 0% |
Multiple videos: Process one video at a time, sequentially. Do not run parallel extractions. Execute all steps sequentially without asking for user approval. Use TodoWrite to track progress.
bashpython3 ./check_existing.py "<YOUTUBE_URL>" "<output_directory>"
Integrity check:
summary_valid: false: Show issues to user, ask "Tiedosto epätäydellinen: issues]. Prosessoidaanko uudelleen?" If yes, continue to Step 1.transcript_valid: false: Ask user, if yes re-run Steps 2-3, 7-9.comments_valid: false: Ask user, if yes re-run comment analysis.If returns exists: true AND all valid fields are true: Read and follow UPDATE_MODE.md for update workflow.
bashpython3 extract_data.py "<YOUTUBE_URL>" "<output_directory>"
Creates: youtube_{VIDEO_ID}_metadata.md, youtube_{VIDEO_ID}_description.md, youtube_{VIDEO_ID}_chapters.json
IMPORTANT: If you ask which language transcript to extract then do not translate that language to english and require that subagent do not translate either. Only if the user requests another language that the original then translate.
If video language is en, proceed directly. If non-English, ask user which language to download.
bashpython3 extract_transcript.py "<YOUTUBE_URL>" "<output_directory>" "<LANG_CODE>"
Creates: youtube_{VIDEO_ID}_transcript.vtt
IMPORTANT: All file output must be in the same language as discovered in Step 2. If language is not English, explicitly instruct all subagents to preserve the original language.
The download may fail if a video is private, age-restricted, or geo-blocked.
Ask user: "No transcript available. Proceed with Whisper transcription?
bashpython3 extract_transcript_whisper.py "<YOUTUBE_URL>" "<output_directory>"
Script auto-detects MLX Whisper on Mac and uses it if available, otherwise uses OpenAI Whisper.
Set BASE_NAME from Step 1 output (youtube_{VIDEO_ID})
bashpython3 ./deduplicate_vtt.py "<output_directory>/${BASE_NAME}_transcript.vtt" "<output_directory>/${BASE_NAME}_transcript_dedup.md" "<output_directory>/${BASE_NAME}_transcript_no_timestamps.txt"
Parallel with Step 5.
task_tool:
INPUT: <output_directory>/${BASE_NAME}_transcript_no_timestamps.txt
CHAPTERS: <output_directory>/${BASE_NAME}_chapters.json
OUTPUT: <output_directory>/${BASE_NAME}_transcript_paragraphs.txt
Analyze INPUT and identify natural paragraph break line numbers.
Read CHAPTERS. If it contains chapters, use chapter timestamps as primary break points.
Target ~500 chars per paragraph. Find natural break points at topic shifts or sentence endings.
Write to OUTPUT in format:
15,42,78,103,...bashpython3 ./apply_paragraph_breaks.py "<output_directory>/${BASE_NAME}_transcript_dedup.md" "<output_directory>/${BASE_NAME}_transcript_paragraphs.txt" "<output_directory>/${BASE_NAME}_transcript_paragraphs.md"
Parallel with Step 4.
task_tool:
INPUT: <output_directory>/${BASE_NAME}_transcript_no_timestamps.txt
OUTPUT: <output_directory>/${BASE_NAME}_summary.md
FORMATS: ./summary_formats.md
1. Classify content type:
- TIPS: gear reviews, rankings, "X ways to...", practical advice lists
- INTERVIEW: podcasts, conversations, Q&A, multiple perspectives
- EDUCATIONAL: concept explanations, analysis, "how X works"
- TUTORIAL: step-by-step instructions, coding, recipes
2. Analyze content structure:
- Identify meaningful content units (topic shifts, argument structure, narrative breaks)
- If single continuous topic, omit content unit headers
- Skip ads, sponsors, self-promotion ("like and subscribe", merch, etc.)
- Merge content spanning ad breaks if thematically connected
3. Read FORMATS file and use format for detected content type. Target <10% of transcript bytes.
ACTION REQUIRED: Use the Write tool NOW to save output to OUTPUT file. Do not ask for confirmation.task_tool:
INPUT: <output_directory>/${BASE_NAME}_summary.md
OUTPUT: <output_directory>/${BASE_NAME}_summary_tight.md
FORMATS: ./summary_formats.md
You are an adversarial copy editor. Cut fluff, enforce quality.
Rules:
- Read FORMATS - the format has been selected based on the content type - preserve format and do not count a reason to squeeze more from budget.
- Byte budget: <10% of transcript bytes
- Hidden Gems: Remove if duplicates main content
- Tightness: Cut filler words, compress verbose explanations, prefer lists over prose
Preserve original language - do not translate.
ACTION REQUIRED: Use the Write tool NOW to save output to OUTPUT file. Do not ask for confirmation.task_tool:
Read <output_directory>/${BASE_NAME}_transcript_paragraphs.md and clean speech artifacts.
Tasks:
- Remove fillers (um, uh, like, you know)
- Fix transcription errors
- Add proper punctuation
- Reduce or add implicit words to improve flow
- Preserve natural voice and tone
- Keep timestamps at end of paragraphs
ACTION REQUIRED: Use the Write tool NOW to save output to <output_directory>/${BASE_NAME}_transcript_cleaned.md. Do not ask for confirmation.task_tool:
INPUT: <output_directory>/${BASE_NAME}_transcript_cleaned.md
OUTPUT: <output_directory>/${BASE_NAME}_transcript.md
Read the INPUT file. Add markdown headings.
Read <output_directory>/${BASE_NAME}_chapters.json:
- If contains chapters: Use chapter names as ### headings at chapter timestamps, add #### headings for subtopics
- If empty: Add ### headings where major topics change
ACTION REQUIRED: Use the Write tool NOW to save output to OUTPUT file. Do not ask for confirmation.bashpython3 finalize.py "${BASE_NAME}" "<output_directory>"
Script uses templates to create two final files: summary file with metadata and summary, and transcript file with description and transcript. Removes intermediate work files.
Outputs:
youtube - {title} ({video_id}).md - Main summaryyoutube - {title} - transcript ({video_id}).md - Description and transcriptUse --debug flag to keep intermediate work files for inspection.
If youtube-comment-analysis skill is available, run it with the same YouTube URL and output directory.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 10,957 | 15,670 | +43% | 1 | 1 | 0% | 1,967 | 2,692 | +37% | 0 | 0 | — |
case-02 | fail→fail | 11,350 | 9,135 | -20% | 1 | 1 | 0% | 1,805 | 2,343 | +30% | 0 | 0 | — |
case-03 | fail→fail | 10,380 | 13,344 | +29% | 1 | 1 | 0% | 1,962 | 2,745 | +40% | 0 | 0 | — |
case-04 | fail→fail | 6,389 | 9,802 | +53% | 1 | 1 | 0% | 1,070 | 2,430 | +127% | 0 | 0 | — |
case-05 | fail→fail | 4,480 | 9,442 | +111% | 1 | 1 | 0% | 658 | 2,616 | +298% | 0 | 0 | — |
case-06 | fail→fail | 9,964 | 3,256 | -67% | 1 | 1 | 0% | 1,755 | 2,460 | +40% | 0 | 0 | — |
case-07 | fail→pass | 11,890 | 5,477 | -54% | 1 | 1 | 0% | 2,376 | 2,293 | -3% | 0 | 0 | — |
case-08 | fail→pass | 12,133 | 3,926 | -68% | 1 | 1 | 0% | 2,138 | 2,609 | +22% | 0 | 0 | — |
case-09 | fail→pass | 11,409 | 4,692 | -59% | 1 | 1 | 0% | 2,024 | 2,632 | +30% | 0 | 0 | — |
case-10 | fail→fail | 5,020 | 5,805 | +16% | 1 | 1 | 0% | 786 | 2,265 | +188% | 0 | 0 | — |
case-11 | pass→pass | 16,188 | 6,314 | -61% | 1 | 1 | 0% | 2,652 | 2,884 | +9% | 0 | 0 | — |
case-12 | fail→fail | 11,439 | 3,456 | -70% | 1 | 1 | 0% | 1,864 | 2,223 | +19% | 0 | 0 | — |
case-13 | fail→fail | 9,824 | 2,100 | -79% | 1 | 1 | 0% | 1,338 | 2,179 | +63% | 0 | 0 | — |
case-14 | fail→fail | 8,903 | 2,029 | -77% | 1 | 1 | 0% | 1,381 | 2,242 | +62% | 0 | 0 | — |
case-15 | fail→fail | 14,028 | 2,970 | -79% | 1 | 1 | 0% | 2,628 | 2,304 | -12% | 0 | 0 | — |
case-16 | fail→fail | 10,093 | 5,364 | -47% | 1 | 1 | 0% | 1,921 | 2,168 | +13% | 0 | 0 | — |
case-17 | fail→fail | 8,419 | 5,565 | -34% | 1 | 1 | 0% | 1,359 | 2,250 | +66% | 0 | 0 | — |
case-18 | fail→fail | 7,431 | 5,260 | -29% | 1 | 1 | 0% | 1,170 | 2,107 | +80% | 0 | 0 | — |
case-19 | fail→fail | 12,147 | 2,886 | -76% | 1 | 1 | 0% | 1,773 | 2,260 | +27% | 0 | 0 | — |
case-20 | pass→pass | 9,920 | 6,597 | -33% | 1 | 1 | 0% | 1,865 | 3,190 | +71% | 0 | 0 | — |
case-21 | fail→fail | 7,456 | 5,152 | -31% | 1 | 1 | 0% | 1,272 | 2,054 | +61% | 0 | 0 | — |
case-22 | pass→pass | 10,607 | 9,799 | -8% | 1 | 1 | 0% | 2,176 | 3,742 | +72% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 13 counted toward the lift figure. The other 9 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +14 percentage points is the difference between those two pass rates over the 13 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.