Transkrypcja YouTube
Pobiera transkrypcje (napisy/podpisy) z filmów YouTube. Działa zarówno z ręcznie tworzonymi, jak i automatycznie generowanymi transkrypcjami. Nie wymaga klucza API ani przeglądarki — korzysta bezpośrednio z API InnerTube YouTube i automatycznie przełącza się na yt-dlp, gdy YouTube blokuje bezpośrednią ścieżkę API.
Przy pierwszym uruchomieniu pobiera metadane wideo i obraz okładki, przechowuje surowe dane w pamięci podręcznej w celu szybkiego ponownego formatowania.
Katalog skryptów
Skrypty w podkatalogu scripts/. {baseDir} = ścieżka katalogu tego SKILL.md. Ustal środowisko wykonawcze ${BUN_X}: jeśli zainstalowano bun → bun; jeśli dostępny jest npx → npx -y bun; w przeciwnym razie zasugeruj instalację bun. Zastąp {baseDir} i ${BUN_X} rzeczywistymi wartościami.
| Skrypt | Przeznaczenie |
|---|---|
scripts/main.ts | CLI do pobierania transkrypcji |
Użycie
# Domyślnie: markdown z znacznikami czasu (angielski)
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>
# Określ języki (kolejność priorytetów)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja
# Bez znaczników czasu
${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps
# Z segmentacją rozdziałów
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters
# Z identyfikacją mówców (wymaga obróbki AI)
${BUN_X} {baseDir}/scripts/main.ts <url> --speakers
# Plik napisów SRT
${BUN_X} {baseDir}/scripts/main.ts <url> --format srt
# Przetłumacz transkrypcję
${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans
# Lista dostępnych transkrypcji
${BUN_X} {baseDir}/scripts/main.ts <url> --list
# Wymuś ponowne pobranie (ignoruj pamięć podręczną)
${BUN_X} {baseDir}/scripts/main.ts <url> --refresh
Opcje
| Opcja | Opis | Domyślnie |
|---|---|---|
<url-or-id> | Adres URL YouTube lub identyfikator wideo (dozwolone wiele) | Wymagane |
--languages <codes> | Kody językowe, oddzielone przecinkami, w kolejności priorytetów | en |
--format <fmt> | Format wyjściowy: text, srt | text |
--translate <code> | Przetłumacz na podany kod języka | |
--list | Wyświetl dostępne transkrypcje zamiast pobierać | |
--timestamps | Dołącz znaczniki czasu [HH:MM:SS → HH:MM:SS] dla każdego akapitu | włączone |
--no-timestamps | Wyłącz znaczniki czasu | |
--chapters | Segmentacja rozdziałów na podstawie opisu wideo | |
--speakers | Surowa transkrypcja z metadanymi do identyfikacji mówców | |
--exclude-generated | Pomiń automatycznie generowane transkrypcje | |
--exclude-manually-created | Pomiń ręcznie tworzone transkrypcje | |
--refresh | Wymuś ponowne pobranie, ignoruj dane z pamięci podręcznej | |
-o, --output <path> | Zapisz do określonej ścieżki pliku | automatycznie generowana |
--output-dir <dir> | Podstawowy katalog wyjściowy | youtube-transcript |
Opcjonalne zmienne środowiskowe
| Zmienna | Opis |
|---|---|
YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER | Przekazywane do yt-dlp --cookies-from-browser podczas przełączania, np. chrome, safari, firefox lub chrome:Profile 1 |
Formaty wejściowe
Akceptuje dowolne z poniższych jako wejście wideo:
- Pełny URL:
https://www.youtube.com/watch?v=dQw4w9WgXcQ - Krótki URL:
https://youtu.be/dQw4w9WgXcQ - URL osadzenia:
https://www.youtube.com/embed/dQw4w9WgXcQ - URL Shorts:
https://www.youtube.com/shorts/dQw4w9WgXcQ - ID wideo:
dQw4w9WgXcQ
Formaty wyjściowe
| Format | Rozszerzenie | Opis |
|---|---|---|
text | .md | Markdown z frontmatter (zawiera description), nagłówek tytułu, podsumowanie, opcjonalny spis treści/okładka/znaczniki czasu/rozdziały/mówcy |
srt | .srt | Format napisów SubRip dla odtwarzaczy wideo |
Katalog wyjściowy
youtube-transcript/
├── .index.json # Mapowanie identyfikatora wideo → ścieżka katalogu (do wyszukiwania w pamięci podręcznej)
└── {channel-slug}/{title-full-slug}/
├── meta.json # Metadane wideo (tytuł, kanał, opis, czas trwania, rozdziały itp.)
├── transcript-raw.json # Surowe fragmenty transkrypcji z API YouTube (buforowane)
├── transcript-sentences.json # Transkrypcja podzielona na zdania (podział według interpunkcji, scalanie między fragmentami)
├── imgs/
│ └── cover.jpg # Miniatura wideo
├── transcript.md # Transkrypcja w formacie Markdown (wygenerowana z zdań)
└── transcript.srt # Napisy SRT (wygenerowane z surowych fragmentów, jeśli użyto --format srt)
{channel-slug}: Nazwa kanału w formacie kebab-case{title-full-slug}: Pełny tytuł wideo w formacie kebab-case
Tryb --list wyprowadza tylko na stdout (nie zapisuje pliku).
Buforowanie
Przy pierwszym pobraniu skrypt zapisuje:
meta.json— metadane wideo, rozdziały, ścieżka do obrazu okładki, informacje o językutranscript-raw.json— surowe fragmenty transkrypcji z API YouTube ({ text, start, duration }[])transcript-sentences.json— transkrypcja podzielona na zdania ({ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]), podzielona według znaków kończących zdanie (.?!…。?!itp.), znaczniki czasu proporcjonalnie przydzielone według długości znaków, scalanie tekstu z uwzględnieniem CJKimgs/cover.jpg— miniatura wideo
Kolejne uruchomienia dla tego samego wideo korzystają z danych z pamięci podręcznej (bez wywołań sieciowych). Użyj --refresh, aby wymusić ponowne pobranie. W przypadku żądania innego języka, pamięć podręczna jest automatycznie odświeżana.
Gdy YouTube zwraca odpowiedzi anty-botowe / zablokowane na bezpośredniej ścieżce InnerTube, skrypt ponawia próby z alternatywnymi tożsamościami klienta, a następnie przełącza się na yt-dlp, jeśli jest dostępny. Jeśli konieczne jest użycie narzędzia zapasowego, ale yt-dlp jest niedostępny, agent powinien zdecydować, jak udostępnić yt-dlp i kontynuować, zamiast zmuszać użytkownika do podjęcia decyzji o instalacji.
Dane wyjściowe SRT (--format srt) są generowane z transcript-raw.json. Wyjście tekstowe/markdown używa transcript-sentences.json dla naturalnych granic zdań.
Przepływ pracy
Gdy użytkownik poda adres URL YouTube i chce uzyskać transkrypcję:
- Uruchom z
--listnajpierw, jeśli użytkownik nie określił języka, aby pokazać dostępne opcje - Zawsze umieszczaj adres URL w pojedynczych cudzysłowach podczas uruchamiania skryptu — zsh traktuje
?jako symbol wieloznaczny glob, więc niecytowany adres URL YouTube powoduje "nie znaleziono dopasowań": użyj'https://www.youtube.com/watch?v=ID' - Domyślnie: uruchom z
--chapters --speakers, aby uzyskać najbogatsze wyniki (rozdziały + identyfikacja mówców) - Skrypt automatycznie zapisuje dane z pamięci podręcznej + plik wyjściowy i drukuje ścieżkę pliku
- Dla trybu
--speakers: po zapisaniu surowego pliku przez skrypt, postępuj zgodnie z poniższym przepływem pracy identyfikacji mówców, aby przeprowadzić obróbkę końcową z etykietami mówców
Gdy użytkownik chce tylko obrazu okładki lub metadanych, uruchomienie skryptu z dowolną opcją spowoduje również zapisanie w pamięci podręcznej meta.json i imgs/cover.jpg.
Podczas ponownego formatowania tego samego wideo (np. najpierw tekst, potem SRT), dane z pamięci podręcznej są ponownie wykorzystywane — nie ma potrzeby ponownego pobierania.
Przepływ pracy rozdziałów i mówców
Rozdziały (--chapters)
Skrypt analizuje znaczniki czasu rozdziałów z opisu wideo (np. 0:00 Wprowadzenie), dzieli transkrypcję według granic rozdziałów, grupuje fragmenty w czytelne akapity i zapisuje jako .md z spisem treści. Nie jest wymagane dalsze przetwarzanie.
Jeśli w opisie nie ma znaczników czasu rozdziałów, transkrypcja jest wyprowadzana jako zgrupowane akapity bez nagłówków rozdziałów.
Identyfikacja mówców (--speakers)
Identyfikacja mówców wymaga przetwarzania AI. Skrypt generuje surowy plik .md zawierający:
- YAML frontmatter z metadanymi wideo (tytuł, kanał, data, okładka, opis, język)
- Opis wideo (do ekstrakcji nazw mówców)
- Lista rozdziałów z opisu (jeśli dostępna)
- Surowa transkrypcja w formacie SRT (wstępnie obliczone znaczniki czasu początku/końca, oszczędne tokenowo)
Po zapisaniu surowego pliku przez skrypt, uruchom pod-agenta (użyj tańszego modelu, np. Sonnet, dla oszczędności kosztów), aby przeprowadzić identyfikację mówców:
- Odczytaj zapisany plik
.md - Odczytaj szablon promptu z
{baseDir}/prompts/speaker-transcript.md - Przetwórz surową transkrypcję zgodnie z promptem:
- Zidentyfikuj mówców, korzystając z metadanych wideo (tytuł → gość, kanał → gospodarz, opis → nazwiska)
- Wykryj zmiany mówców na podstawie przepływu rozmowy, wzorców pytanie-odpowiedź i wskazówek kontekstowych
- Podziel na rozdziały (użyj rozdziałów z opisu, jeśli są dostępne, w przeciwnym razie utwórz na podstawie zmian tematów)
- Formatuj z etykietami
**Imię mówcy:**, grupowaniem akapitów (2-4 zdania) i znacznikami czasu[HH:MM:SS → HH:MM:SS]
- Nadpisz plik
.mdprzetworzoną transkrypcją (zachowaj YAML frontmatter)
Gdy używana jest opcja --speakers, --chapters jest implikowane — przetworzone dane wyjściowe zawsze zawierają segmentację rozdziałów.
Przypadki błędów
| Błąd | Znaczenie |
|---|---|
| Transkrypcje wyłączone | Wideo nie ma wcale napisów |
| Nie znaleziono transkrypcji | Żądany język nie jest dostępny |
| Wideo niedostępne | Wideo usunięte, prywatne lub zablokowane regionalnie |
| IP zablokowane | Zbyt wiele żądań, spróbuj ponownie później |
| Ograniczenie wiekowe | Wideo wymaga logowania w celu weryfikacji wieku |
| Wykryto bota | Skrypt ponawia próby z alternatywnymi klientami, a następnie yt-dlp; jeśli brakuje narzędzi zapasowych, agent powinien sam to rozwiązać, w przeciwnym razie jeśli nadal nie działa, spróbuj YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari (lub swojej przeglądarki) |


